diff --git a/api/server/auth/auth.go b/api/server/auth/auth.go index 07d28068..5837dfa8 100644 --- a/api/server/auth/auth.go +++ b/api/server/auth/auth.go @@ -70,7 +70,7 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { // within. If not forbid the request and log the occurance. if acc.Namespace != namespace { logger.Warnf("Cross namespace request forbidden: account %v (%v) requested access to %v in the %v namespace", acc.ID, acc.Namespace, req.URL.Path, namespace) - w.WriteHeader(http.StatusForbidden) + http.Error(w, "Forbidden namespace", 403) } // Determine the name of the service being requested @@ -80,13 +80,13 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { endpoint = &resolver.Endpoint{Path: req.URL.Path} } else if err != nil { logger.Error(err) - w.WriteHeader(http.StatusInternalServerError) + http.Error(w, err.Error(), 500) return - } else if err == nil { + } else { // set the endpoint in the context so it can be used to resolve // the request later ctx := context.WithValue(req.Context(), resolver.Endpoint{}, endpoint) - *req = *req.WithContext(ctx) + *req = *req.Clone(ctx) } // construct the resource name, e.g. home => go.micro.web.home @@ -115,14 +115,14 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { // The account is set, but they don't have enough permissions, hence // we return a forbidden error. if len(acc.ID) > 0 { - w.WriteHeader(http.StatusForbidden) + http.Error(w, "Forbidden request", 403) return } // If there is no auth login url set, 401 loginURL := h.auth.Options().LoginURL if loginURL == "" { - w.WriteHeader(http.StatusUnauthorized) + http.Error(w, "unauthorized request", 401) return } @@ -143,7 +143,7 @@ func (h authHandler) namespaceFromRequest(req *http.Request) string { var host string if h, _, err := net.SplitHostPort(req.Host); err == nil { host = h // host does contain a port - } else { + } else if strings.Contains(err.Error(), "missing port in address") { host = req.Host // host does not contain a port } @@ -162,6 +162,7 @@ func (h authHandler) namespaceFromRequest(req *http.Request) string { return auth.DefaultNamespace } + // TODO: this logic needs to be replaced with usage of publicsuffix // if host is not a subdomain, deturn default namespace comps := strings.Split(host, ".") if len(comps) < 3 { diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index 021156b9..34e417dd 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -225,9 +225,14 @@ var ( Usage: "Comma-separated list of store addresses", }, &cli.StringFlag{ - Name: "store_namespace", - EnvVars: []string{"MICRO_STORE_NAMESPACE"}, - Usage: "Namespace for store data", + Name: "store_database", + EnvVars: []string{"MICRO_STORE_DATABASE"}, + Usage: "Database option for the underlying store", + }, + &cli.StringFlag{ + Name: "store_table", + EnvVars: []string{"MICRO_STORE_Table"}, + Usage: "Table option for the underlying store", }, &cli.StringFlag{ Name: "transport", @@ -622,9 +627,15 @@ func (c *cmd) Before(ctx *cli.Context) error { } } - if len(ctx.String("store_namespace")) > 0 { - if err := (*c.opts.Store).Init(store.Namespace(ctx.String("store_namespace"))); err != nil { - logger.Fatalf("Error configuring store: %v", err) + if len(ctx.String("store_database")) > 0 { + if err := (*c.opts.Store).Init(store.Database(ctx.String("store_database"))); err != nil { + logger.Fatalf("Error configuring store database option: %v", err) + } + } + + if len(ctx.String("store_table")) > 0 { + if err := (*c.opts.Store).Init(store.Table(ctx.String("store_table"))); err != nil { + logger.Fatalf("Error configuring store table option: %v", err) } } diff --git a/config/secrets/box/box_test.go b/config/secrets/box/box_test.go index 77a5559a..43b3e141 100644 --- a/config/secrets/box/box_test.go +++ b/config/secrets/box/box_test.go @@ -57,6 +57,9 @@ func TestBox(t *testing.T) { t.Error(err) } dec, err = alice.Decrypt(enc, secrets.SenderPublicKey(bob.Options().PublicKey)) + if err != nil { + t.Error(err) + } if !reflect.DeepEqual(dec, bobSecret) { t.Errorf("Alice's decrypted message didn't match Bob's encrypted message %v != %v", bobSecret, dec) } diff --git a/go.mod b/go.mod index c18607a6..f02d29b5 100644 --- a/go.mod +++ b/go.mod @@ -60,5 +60,3 @@ require ( gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/telegram-bot-api.v4 v4.6.4 ) - -replace github.com/coreos/bbolt => go.etcd.io/bbolt v1.3.4 diff --git a/service.go b/service.go index 36044338..7e16ed11 100644 --- a/service.go +++ b/service.go @@ -106,11 +106,11 @@ func (s *service) Init(opts ...Option) { logger.Fatal(err) } - // If the store has no namespace set, fallback to the + // If the store has no Table set, fallback to the // services name - if len(store.DefaultStore.Options().Namespace) == 0 { + if len(store.DefaultStore.Options().Table) == 0 { name := s.opts.Cmd.App().Name - store.DefaultStore.Init(store.Namespace(name)) + store.DefaultStore.Init(store.Table(name)) } // TODO: replace Cmd.Init with config.Load diff --git a/store/cache/cache_test.go b/store/cache/cache_test.go index 2af10698..e58b2b0b 100644 --- a/store/cache/cache_test.go +++ b/store/cache/cache_test.go @@ -10,7 +10,7 @@ import ( ) func TestCache(t *testing.T) { - l0, l1, l2 := memory.NewStore(store.Namespace("l0")), memory.NewStore(store.Prefix("l1")), memory.NewStore(store.Suffix("l2")) + l0, l1, l2 := memory.NewStore(store.Database("l0")), memory.NewStore(store.Table("l1")), memory.NewStore() _, _, _ = l0.Init(), l1.Init(), l2.Init() assert := assert.New(t) diff --git a/store/cloudflare/cloudflare.go b/store/cloudflare/cloudflare.go index 4b4b82d6..c9099f1b 100644 --- a/store/cloudflare/cloudflare.go +++ b/store/cloudflare/cloudflare.go @@ -105,8 +105,8 @@ func (w *workersKV) Init(opts ...store.Option) error { for _, o := range opts { o(&w.options) } - if len(w.options.Namespace) > 0 { - w.namespace = w.options.Namespace + if len(w.options.Database) > 0 { + w.namespace = w.options.Database } ttl := w.options.Context.Value("STORE_CACHE_TTL") if ttl != nil { @@ -388,7 +388,7 @@ func NewStore(opts ...store.Option) store.Store { } if len(namespace) == 0 { - namespace = options.Namespace + namespace = options.Database } // validate options are not blank or log.Fatal diff --git a/store/cloudflare/options.go b/store/cloudflare/options.go index dd2aee36..a0143dd8 100644 --- a/store/cloudflare/options.go +++ b/store/cloudflare/options.go @@ -49,7 +49,7 @@ func Account(id string) store.Option { // Namespace sets the KV namespace func Namespace(ns string) store.Option { return func(o *store.Options) { - o.Namespace = ns + o.Database = ns } } diff --git a/store/cockroach/cockroach.go b/store/cockroach/cockroach.go index e1d84b1d..e34324f8 100644 --- a/store/cockroach/cockroach.go +++ b/store/cockroach/cockroach.go @@ -299,12 +299,12 @@ func (s *sqlStore) configure() error { s.options.Nodes = []string{"localhost:26257"} } - namespace := s.options.Namespace + namespace := s.options.Database if len(namespace) == 0 { namespace = DefaultNamespace } - prefix := s.options.Prefix + prefix := s.options.Table if len(prefix) == 0 { prefix = DefaultPrefix } diff --git a/store/cockroach/cockroach_test.go b/store/cockroach/cockroach_test.go index 304078c8..f5b0077c 100644 --- a/store/cockroach/cockroach_test.go +++ b/store/cockroach/cockroach_test.go @@ -28,7 +28,7 @@ func TestSQL(t *testing.T) { db.Close() sqlStore := NewStore( - store.Namespace("testsql"), + store.Database("testsql"), store.Nodes(connection), ) diff --git a/store/etcd/etcd.go b/store/etcd/etcd.go index 684366df..a51fd425 100644 --- a/store/etcd/etcd.go +++ b/store/etcd/etcd.go @@ -60,11 +60,11 @@ func (e *etcdStore) init() error { } e.client = client ns := "" - if len(e.options.Prefix) > 0 { - ns = e.options.Prefix + if len(e.options.Table) > 0 { + ns = e.options.Table } - if len(e.options.Namespace) > 0 { - ns = e.options.Namespace + "/" + ns + if len(e.options.Database) > 0 { + ns = e.options.Database + "/" + ns } if len(ns) > 0 { e.client.KV = namespace.NewKV(e.client.KV, ns) diff --git a/store/memory/memory.go b/store/memory/memory.go index 07e73ddc..e2f6d15e 100644 --- a/store/memory/memory.go +++ b/store/memory/memory.go @@ -83,14 +83,11 @@ func (m *memoryStore) Read(key string, opts ...store.ReadOption) ([]*store.Recor } func (m *memoryStore) get(k string) (*store.Record, error) { - if len(m.options.Suffix) > 0 { - k = k + m.options.Suffix + if len(m.options.Table) > 0 { + k = m.options.Table + "/" + k } - if len(m.options.Prefix) > 0 { - k = m.options.Prefix + "/" + k - } - if len(m.options.Namespace) > 0 { - k = m.options.Namespace + "/" + k + if len(m.options.Database) > 0 { + k = m.options.Database + "/" + k } var storedRecord *internalRecord r, found := m.store.Get(k) @@ -142,14 +139,11 @@ func (m *memoryStore) Write(r *store.Record, opts ...store.WriteOption) error { func (m *memoryStore) set(r *store.Record) { key := r.Key - if len(m.options.Suffix) > 0 { - key = key + m.options.Suffix + if len(m.options.Table) > 0 { + key = m.options.Table + "/" + key } - if len(m.options.Prefix) > 0 { - key = m.options.Prefix + "/" + key - } - if len(m.options.Namespace) > 0 { - key = m.options.Namespace + "/" + key + if len(m.options.Database) > 0 { + key = m.options.Database + "/" + key } // copy the incoming record and then @@ -175,14 +169,11 @@ func (m *memoryStore) Delete(key string, opts ...store.DeleteOption) error { } func (m *memoryStore) delete(key string) { - if len(m.options.Suffix) > 0 { - key = key + m.options.Suffix + if len(m.options.Table) > 0 { + key = m.options.Table + "/" + key } - if len(m.options.Prefix) > 0 { - key = m.options.Prefix + "/" + key - } - if len(m.options.Namespace) > 0 { - key = m.options.Namespace + "/" + key + if len(m.options.Database) > 0 { + key = m.options.Database + "/" + key } m.store.Delete(key) } @@ -226,14 +217,11 @@ func (m *memoryStore) list(limit, offset uint) []string { allKeys := make([]string, len(allItems)) i := 0 for k := range allItems { - if len(m.options.Suffix) > 0 { - k = strings.TrimSuffix(k, m.options.Suffix) + if len(m.options.Database) > 0 { + k = strings.TrimPrefix(k, m.options.Database+"/") } - if len(m.options.Namespace) > 0 { - k = strings.TrimPrefix(k, m.options.Namespace+"/") - } - if len(m.options.Prefix) > 0 { - k = strings.TrimPrefix(k, m.options.Prefix+"/") + if len(m.options.Table) > 0 { + k = strings.TrimPrefix(k, m.options.Table+"/") } allKeys[i] = k i++ diff --git a/store/memory/memory_test.go b/store/memory/memory_test.go index 21f6d597..14ac49a6 100644 --- a/store/memory/memory_test.go +++ b/store/memory/memory_test.go @@ -10,9 +10,9 @@ import ( ) func TestMemoryReInit(t *testing.T) { - s := NewStore(store.Prefix("aaa")) - s.Init(store.Prefix("")) - if len(s.Options().Prefix) > 0 { + s := NewStore(store.Table("aaa")) + s.Init(store.Table("")) + if len(s.Options().Table) > 0 { t.Error("Init didn't reinitialise the store") } } @@ -25,31 +25,19 @@ func TestMemoryBasic(t *testing.T) { func TestMemoryPrefix(t *testing.T) { s := NewStore() - s.Init(store.Prefix("some-prefix")) - basictest(s, t) -} - -func TestMemorySuffix(t *testing.T) { - s := NewStore() - s.Init(store.Suffix("some-suffix")) - basictest(s, t) -} - -func TestMemoryPrefixSuffix(t *testing.T) { - s := NewStore() - s.Init(store.Prefix("some-prefix"), store.Prefix("some-suffix")) + s.Init(store.Table("some-prefix")) basictest(s, t) } func TestMemoryNamespace(t *testing.T) { s := NewStore() - s.Init(store.Namespace("some-namespace")) + s.Init(store.Database("some-namespace")) basictest(s, t) } func TestMemoryNamespacePrefix(t *testing.T) { s := NewStore() - s.Init(store.Prefix("some-prefix"), store.Namespace("some-namespace")) + s.Init(store.Table("some-prefix"), store.Database("some-namespace")) basictest(s, t) } diff --git a/store/options.go b/store/options.go index 98b9915a..01d60c80 100644 --- a/store/options.go +++ b/store/options.go @@ -11,13 +11,10 @@ type Options struct { // For example, an etcd implementation would contain the nodes of the cluster. // A SQL implementation could contain one or more connection strings. Nodes []string - // Namespace allows multiple isolated stores to be kept in one backend, if supported. - // For example multiple tables in a SQL store. - Namespace string - // Prefix sets a global prefix on all keys - Prefix string - // Suffix sets a global suffix on all keys - Suffix string + // Database allows multiple isolated stores to be kept in one backend, if supported. + Database string + // Table is analagous to a table in database backends or a key prefix in KV backends + Table string // Context should contain all implementation specific options, using context.WithValue. Context context.Context } @@ -34,25 +31,17 @@ func Nodes(a ...string) Option { } } -// Namespace allows multiple isolated stores to be kept in one backend, if supported. -// For example multiple tables in a SQL store. -func Namespace(ns string) Option { +// Database allows multiple isolated stores to be kept in one backend, if supported. +func Database(db string) Option { return func(o *Options) { - o.Namespace = ns + o.Database = db } } -// Prefix sets a global prefix on all keys -func Prefix(p string) Option { +// Table is analagous to a table in database backends or a key prefix in KV backends +func Table(t string) Option { return func(o *Options) { - o.Prefix = p - } -} - -// Suffix sets a global suffix on all keys -func Suffix(s string) Option { - return func(o *Options) { - o.Suffix = s + o.Table = t } } diff --git a/store/service/service.go b/store/service/service.go index b15340ff..f55bbd04 100644 --- a/store/service/service.go +++ b/store/service/service.go @@ -36,8 +36,8 @@ func (s *serviceStore) Init(opts ...store.Option) error { for _, o := range opts { o(&s.options) } - s.Namespace = s.options.Namespace - s.Prefix = s.options.Prefix + s.Namespace = s.options.Database + s.Prefix = s.options.Table s.Nodes = s.options.Nodes return nil @@ -165,8 +165,8 @@ func NewStore(opts ...store.Option) store.Store { service := &serviceStore{ options: options, - Namespace: options.Namespace, - Prefix: options.Prefix, + Namespace: options.Database, + Prefix: options.Table, Nodes: options.Nodes, Client: pb.NewStoreService("go.micro.store", client.DefaultClient), } diff --git a/store/scope/scope.go b/util/scope/scope.go similarity index 98% rename from store/scope/scope.go rename to util/scope/scope.go index c78e1e1a..cb2344df 100644 --- a/store/scope/scope.go +++ b/util/scope/scope.go @@ -19,7 +19,7 @@ func NewScope(s store.Store, prefix string) Scope { func (s *Scope) Options() store.Options { o := s.Store.Options() - o.Prefix = s.prefix + o.Table = s.prefix return o }