From 2ff0d9d435d21cf444c6a24bd17a0a2883c32f57 Mon Sep 17 00:00:00 2001 From: Yaroslav Vorobiov Date: Tue, 5 Feb 2019 19:22:17 +0200 Subject: [PATCH] Add bucket to project relationship on satellite (#1143) * integrate console api keys with buckets in pointerdb * fix test * fix tests kvmetainfo * linter fix * disable account activation * fix test * review fixes * fix comments * little refactoring * remove debug println * fix typo * disable activation in a propper way * fix test * fix imports * fix uplink count in testplanet * move key creation to planet.newUplink --- cmd/storj-sim/console.go | 165 ++++++++ cmd/storj-sim/network.go | 24 ++ internal/testplanet/planet.go | 2 +- internal/testplanet/uplink.go | 40 +- pkg/metainfo/kvmetainfo/buckets_test.go | 30 +- pkg/miniogw/gateway_test.go | 29 +- pkg/miniogw/integration_test.go | 20 +- pkg/pointerdb/pointerdb.go | 75 ++-- pkg/pointerdb/pointerdb_test.go | 65 ++- satellite/console/apikeys.go | 17 +- satellite/console/buckets.go | 32 -- .../consoleweb/consoleql/mutation_test.go | 71 ++-- .../consoleweb/consoleql/query_test.go | 104 +++-- satellite/console/database.go | 2 - satellite/console/projects_test.go | 2 +- satellite/console/service.go | 4 + satellite/peer.go | 8 +- satellite/satellitedb/buckets.go | 92 ----- satellite/satellitedb/consoledb.go | 5 - satellite/satellitedb/dbx/satellitedb.dbx | 24 -- satellite/satellitedb/dbx/satellitedb.dbx.go | 391 +----------------- .../dbx/satellitedb.dbx.postgres.sql | 6 - .../dbx/satellitedb.dbx.sqlite3.sql | 6 - satellite/satellitedb/locked.go | 41 -- 24 files changed, 537 insertions(+), 718 deletions(-) create mode 100644 cmd/storj-sim/console.go delete mode 100644 satellite/console/buckets.go delete mode 100644 satellite/satellitedb/buckets.go diff --git a/cmd/storj-sim/console.go b/cmd/storj-sim/console.go new file mode 100644 index 000000000..8e6ee648e --- /dev/null +++ b/cmd/storj-sim/console.go @@ -0,0 +1,165 @@ +// Copyright (C) 2019 Storj Labs, Inc. +// See LICENSE for copying information. + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + "github.com/zeebo/errs" +) + +func graphqlDo(client *http.Client, request *http.Request, jsonResponse interface{}) error { + resp, err := client.Do(request) + if err != nil { + return err + } + defer func() { + err = resp.Body.Close() + }() + + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + var response struct { + Data json.RawMessage + Errors []interface{} + } + + if err = json.NewDecoder(bytes.NewReader(b)).Decode(&response); err != nil { + return err + } + + if response.Errors != nil { + return errs.New("inner graphql error") + } + + if jsonResponse == nil { + return nil + } + + return json.NewDecoder(bytes.NewReader(response.Data)).Decode(jsonResponse) +} + +func addExampleProjectWithKey(key *string, address string) error { + client := http.Client{} + + // create user + { + createUserQuery := fmt.Sprintf( + "mutation {createUser(input:{email:\"%s\",password:\"%s\",firstName:\"%s\",lastName:\"\"})}", + "example@mail.com", + "123a123", + "Alice") + + request, err := http.NewRequest( + http.MethodPost, + address, + bytes.NewReader([]byte(createUserQuery))) + + if err != nil { + return err + } + + request.Header.Add("Content-Type", "application/graphql") + + if err := graphqlDo(&client, request, nil); err != nil { + return err + } + } + + // get token + var token struct { + Token struct { + Token string + } + } + { + tokenQuery := fmt.Sprintf( + "query {token(email:\"%s\",password:\"%s\"){token}}", + "example@mail.com", + "123a123") + + request, err := http.NewRequest( + http.MethodPost, + address, + bytes.NewReader([]byte(tokenQuery))) + + if err != nil { + return err + } + + request.Header.Add("Content-Type", "application/graphql") + + if err := graphqlDo(&client, request, &token); err != nil { + return err + } + } + + // create project + var createProject struct { + CreateProject struct { + ID string + } + } + { + createProjectQuery := fmt.Sprintf( + "mutation {createProject(input:{name:\"%s\",description:\"\"}){id}}", + "TestProject") + + request, err := http.NewRequest( + http.MethodPost, + address, + bytes.NewReader([]byte(createProjectQuery))) + + if err != nil { + return err + } + + request.Header.Add("Content-Type", "application/graphql") + request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token.Token.Token)) + + if err := graphqlDo(&client, request, &createProject); err != nil { + return err + } + } + + // create api key + var createAPIKey struct { + CreateAPIKey struct { + Key string + } + } + { + createAPIKeyQuery := fmt.Sprintf( + "mutation {createAPIKey(projectID:\"%s\",name:\"%s\"){key}}", + createProject.CreateProject.ID, + "testKey") + + request, err := http.NewRequest( + http.MethodPost, + address, + bytes.NewReader([]byte(createAPIKeyQuery))) + + if err != nil { + return err + } + + request.Header.Add("Content-Type", "application/graphql") + request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token.Token.Token)) + + if err := graphqlDo(&client, request, &createAPIKey); err != nil { + return err + } + } + + // return key to the caller + *key = createAPIKey.CreateAPIKey.Key + return nil +} diff --git a/cmd/storj-sim/network.go b/cmd/storj-sim/network.go index 15f007c27..e3a5914dc 100644 --- a/cmd/storj-sim/network.go +++ b/cmd/storj-sim/network.go @@ -14,6 +14,7 @@ import ( "sort" "strconv" "strings" + "time" "github.com/spf13/viper" "github.com/zeebo/errs" @@ -206,6 +207,29 @@ func newNetwork(flags *Flags) (*Processes, error) { // TODO: maybe all the config flags should be exposed for all processes? + // check if gateway config has an api key, if it's not + // create example project with key and add it to the config + // so that gateway can have access to the satellite + apiKey := vip.GetString("client.api-key") + if apiKey == "" { + consoleAddress := fmt.Sprintf( + "http://%s/api/graphql/v0", + net.JoinHostPort(host, strconv.Itoa(consolePort+i))) + + // wait for console server to start + time.Sleep(3 * time.Second) + + if err := addExampleProjectWithKey(&apiKey, consoleAddress); err != nil { + return err + } + + vip.Set("client.api-key", apiKey) + + if err := vip.WriteConfig(); err != nil { + return err + } + } + accessKey := vip.GetString("minio.access-key") secretKey := vip.GetString("minio.secret-key") diff --git a/internal/testplanet/planet.go b/internal/testplanet/planet.go index 4e98cb948..a3ed77254 100644 --- a/internal/testplanet/planet.go +++ b/internal/testplanet/planet.go @@ -267,7 +267,7 @@ func (planet *Planet) Shutdown() error { return errlist.Err() } -// newUplinks creates initializes uplinks +// newUplinks creates initializes uplinks, requires peer to have at least one satellite func (planet *Planet) newUplinks(prefix string, count, storageNodeCount int) ([]*Uplink, error) { var xs []*Uplink for i := 0; i < count; i++ { diff --git a/internal/testplanet/uplink.go b/internal/testplanet/uplink.go index b87858703..2fc0296dc 100644 --- a/internal/testplanet/uplink.go +++ b/internal/testplanet/uplink.go @@ -30,6 +30,7 @@ import ( "storj.io/storj/pkg/stream" "storj.io/storj/pkg/transport" "storj.io/storj/satellite" + "storj.io/storj/satellite/console" ) // Uplink is a general purpose @@ -39,6 +40,7 @@ type Uplink struct { Identity *identity.FullIdentity Transport transport.Client StorageNodeCount int + APIKey map[storj.NodeID]string } // newUplink creates a new uplink @@ -67,6 +69,42 @@ func (planet *Planet) newUplink(name string, storageNodeCount int) (*Uplink, err }, } + apiKeys := make(map[storj.NodeID]string) + for j, satellite := range planet.Satellites { + // TODO: find a nicer way to do this + // populate satellites console with example + // project and API key and pass that to uplinks + consoleDB := satellite.DB.Console() + + projectName := fmt.Sprintf("%s_%d", name, j) + key := console.APIKeyFromBytes([]byte(projectName)) + + project, err := consoleDB.Projects().Insert( + context.Background(), + &console.Project{ + Name: projectName, + }, + ) + if err != nil { + return nil, err + } + + _, err = consoleDB.APIKeys().Create( + context.Background(), + *key, + console.APIKeyInfo{ + Name: "root", + ProjectID: project.ID, + }, + ) + if err != nil { + return nil, err + } + + apiKeys[satellite.ID()] = key.String() + } + + uplink.APIKey = apiKeys planet.uplinks = append(planet.uplinks, uplink) return uplink, nil @@ -208,7 +246,7 @@ func (uplink *Uplink) getMetainfo(satellite *satellite.Peer) (db storj.Metainfo, return nil, nil, err } - pdb, err := uplink.DialPointerDB(satellite, "") // TODO pass api key? + pdb, err := uplink.DialPointerDB(satellite, uplink.APIKey[satellite.ID()]) // TODO pass api key? if err != nil { return nil, nil, err } diff --git a/pkg/metainfo/kvmetainfo/buckets_test.go b/pkg/metainfo/kvmetainfo/buckets_test.go index 221df1959..90a219422 100644 --- a/pkg/metainfo/kvmetainfo/buckets_test.go +++ b/pkg/metainfo/kvmetainfo/buckets_test.go @@ -9,6 +9,8 @@ import ( "fmt" "testing" + "storj.io/storj/satellite/console" + "github.com/stretchr/testify/assert" "github.com/vivint/infectious" @@ -25,11 +27,12 @@ import ( ) const ( - TestAPIKey = "test-api-key" TestEncKey = "test-encryption-key" TestBucket = "test-bucket" ) +var TestAPIKey = "test-api-key" + func TestBucketsBasic(t *testing.T) { runTest(t, func(ctx context.Context, db *kvmetainfo.DB, buckets buckets.Store, streams streams.Store) { // Create new bucket @@ -331,7 +334,30 @@ func runTest(t *testing.T, test func(context.Context, *kvmetainfo.DB, buckets.St func newMetainfoParts(planet *testplanet.Planet) (*kvmetainfo.DB, buckets.Store, streams.Store, error) { // TODO(kaloyan): We should have a better way for configuring the Satellite's API Key - err := flag.Set("pointer-db.auth.api-key", TestAPIKey) + // add project to satisfy constraint + project, err := planet.Satellites[0].DB.Console().Projects().Insert(context.Background(), &console.Project{ + Name: "testProject", + }) + + if err != nil { + return nil, nil, nil, err + } + + apiKey := console.APIKey{} + apiKeyInfo := console.APIKeyInfo{ + ProjectID: project.ID, + Name: "testKey", + } + + // add api key to db + _, err = planet.Satellites[0].DB.Console().APIKeys().Create(context.Background(), apiKey, apiKeyInfo) + if err != nil { + return nil, nil, nil, err + } + + TestAPIKey = apiKey.String() + + err = flag.Set("pointer-db.auth.api-key", TestAPIKey) if err != nil { return nil, nil, nil, err } diff --git a/pkg/miniogw/gateway_test.go b/pkg/miniogw/gateway_test.go index 49d4fd2f5..d3cab039f 100644 --- a/pkg/miniogw/gateway_test.go +++ b/pkg/miniogw/gateway_test.go @@ -30,10 +30,10 @@ import ( "storj.io/storj/pkg/storage/segments" "storj.io/storj/pkg/storage/streams" "storj.io/storj/pkg/storj" + "storj.io/storj/satellite/console" ) const ( - TestAPIKey = "test-api-key" TestEncKey = "test-encryption-key" TestBucket = "test-bucket" TestFile = "test-file" @@ -41,6 +41,8 @@ const ( DestFile = "dest-file" ) +var TestAPIKey = "test-api-key" + func TestMakeBucketWithLocation(t *testing.T) { runTest(t, func(ctx context.Context, layer minio.ObjectLayer, metainfo storj.Metainfo, streams streams.Store) { // Check the error when creating bucket with empty name @@ -656,7 +658,30 @@ func runTest(t *testing.T, test func(context.Context, minio.ObjectLayer, storj.M func initEnv(planet *testplanet.Planet) (minio.ObjectLayer, storj.Metainfo, streams.Store, error) { // TODO(kaloyan): We should have a better way for configuring the Satellite's API Key - err := flag.Set("pointer-db.auth.api-key", TestAPIKey) + // add project to satisfy constraint + project, err := planet.Satellites[0].DB.Console().Projects().Insert(context.Background(), &console.Project{ + Name: "testProject", + }) + + if err != nil { + return nil, nil, nil, err + } + + apiKey := console.APIKey{} + apiKeyInfo := console.APIKeyInfo{ + ProjectID: project.ID, + Name: "testKey", + } + + // add api key to db + _, err = planet.Satellites[0].DB.Console().APIKeys().Create(context.Background(), apiKey, apiKeyInfo) + if err != nil { + return nil, nil, nil, err + } + + TestAPIKey = apiKey.String() + + err = flag.Set("pointer-db.auth.api-key", TestAPIKey) if err != nil { return nil, nil, nil, err } diff --git a/pkg/miniogw/integration_test.go b/pkg/miniogw/integration_test.go index 7d3e30ee4..77f2ce6f9 100644 --- a/pkg/miniogw/integration_test.go +++ b/pkg/miniogw/integration_test.go @@ -25,6 +25,7 @@ import ( "storj.io/storj/pkg/cfgstruct" "storj.io/storj/pkg/identity" "storj.io/storj/pkg/miniogw" + "storj.io/storj/satellite/console" ) func TestUploadDownload(t *testing.T) { @@ -38,7 +39,24 @@ func TestUploadDownload(t *testing.T) { defer ctx.Check(planet.Shutdown) - err = flag.Set("pointer-db.auth.api-key", "apiKey") + // add project to satisfy constraint + project, err := planet.Satellites[0].DB.Console().Projects().Insert(context.Background(), &console.Project{ + Name: "testProject", + }) + + assert.NoError(t, err) + + apiKey := console.APIKey{} + apiKeyInfo := console.APIKeyInfo{ + ProjectID: project.ID, + Name: "testKey", + } + + // add api key to db + _, err = planet.Satellites[0].DB.Console().APIKeys().Create(context.Background(), apiKey, apiKeyInfo) + assert.NoError(t, err) + + err = flag.Set("pointer-db.auth.api-key", apiKey.String()) assert.NoError(t, err) // bind default values to config diff --git a/pkg/pointerdb/pointerdb.go b/pkg/pointerdb/pointerdb.go index 3b4de349e..16d5e5173 100644 --- a/pkg/pointerdb/pointerdb.go +++ b/pkg/pointerdb/pointerdb.go @@ -16,7 +16,9 @@ import ( "storj.io/storj/pkg/identity" "storj.io/storj/pkg/overlay" "storj.io/storj/pkg/pb" - pointerdbAuth "storj.io/storj/pkg/pointerdb/auth" + _ "storj.io/storj/pkg/pointerdb/auth" // ensures that we add api key flag to current executable + "storj.io/storj/pkg/storj" + "storj.io/storj/satellite/console" "storj.io/storj/storage" ) @@ -25,6 +27,11 @@ var ( segmentError = errs.Class("segment error") ) +// APIKeys is api keys store methods used by pointerdb +type APIKeys interface { + GetByKey(ctx context.Context, key console.APIKey) (*console.APIKeyInfo, error) +} + // Server implements the network state RPC service type Server struct { logger *zap.Logger @@ -33,10 +40,11 @@ type Server struct { cache *overlay.Cache config Config identity *identity.FullIdentity + apiKeys APIKeys } // NewServer creates instance of Server -func NewServer(logger *zap.Logger, service *Service, allocation *AllocationSigner, cache *overlay.Cache, config Config, identity *identity.FullIdentity) *Server { +func NewServer(logger *zap.Logger, service *Service, allocation *AllocationSigner, cache *overlay.Cache, config Config, identity *identity.FullIdentity, apiKeys APIKeys) *Server { return &Server{ logger: logger, service: service, @@ -44,27 +52,33 @@ func NewServer(logger *zap.Logger, service *Service, allocation *AllocationSigne cache: cache, config: config, identity: identity, + apiKeys: apiKeys, } } // Close closes resources func (s *Server) Close() error { return nil } -// TODO: ZZZ temporarily disabled until endpoint and service split -const disableAuth = true - -func (s *Server) validateAuth(ctx context.Context) error { - // TODO: ZZZ temporarily disabled until endpoint and service split - if disableAuth { - return nil - } - +func (s *Server) validateAuth(ctx context.Context) (*console.APIKeyInfo, error) { APIKey, ok := auth.GetAPIKey(ctx) - if !ok || !pointerdbAuth.ValidateAPIKey(string(APIKey)) { + if !ok { s.logger.Error("unauthorized request: ", zap.Error(status.Errorf(codes.Unauthenticated, "Invalid API credential"))) - return status.Errorf(codes.Unauthenticated, "Invalid API credential") + return nil, status.Errorf(codes.Unauthenticated, "Invalid API credential") } - return nil + + key, err := console.APIKeyFromBase64(string(APIKey)) + if err != nil { + s.logger.Error("unauthorized request: ", zap.Error(status.Errorf(codes.Unauthenticated, "Invalid API credential"))) + return nil, status.Errorf(codes.Unauthenticated, "Invalid API credential") + } + + keyInfo, err := s.apiKeys.GetByKey(ctx, *key) + if err != nil { + s.logger.Error("unauthorized request: ", zap.Error(status.Errorf(codes.Unauthenticated, err.Error()))) + return nil, status.Errorf(codes.Unauthenticated, "Invalid API credential") + } + + return keyInfo, nil } func (s *Server) validateSegment(req *pb.PutRequest) error { @@ -95,11 +109,13 @@ func (s *Server) Put(ctx context.Context, req *pb.PutRequest) (resp *pb.PutRespo return nil, status.Errorf(codes.InvalidArgument, err.Error()) } - if err = s.validateAuth(ctx); err != nil { + keyInfo, err := s.validateAuth(ctx) + if err != nil { return nil, err } - if err = s.service.Put(req.GetPath(), req.GetPointer()); err != nil { + path := storj.JoinPaths(keyInfo.ProjectID.String(), req.GetPath()) + if err = s.service.Put(path, req.GetPointer()); err != nil { s.logger.Error("err putting pointer", zap.Error(err)) return nil, status.Errorf(codes.Internal, err.Error()) } @@ -111,11 +127,13 @@ func (s *Server) Put(ctx context.Context, req *pb.PutRequest) (resp *pb.PutRespo func (s *Server) Get(ctx context.Context, req *pb.GetRequest) (resp *pb.GetResponse, err error) { defer mon.Task()(&ctx)(&err) - if err = s.validateAuth(ctx); err != nil { + keyInfo, err := s.validateAuth(ctx) + if err != nil { return nil, err } - pointer, err := s.service.Get(req.GetPath()) + path := storj.JoinPaths(keyInfo.ProjectID.String(), req.GetPath()) + pointer, err := s.service.Get(path) if err != nil { if storage.ErrKeyNotFound.Has(err) { return nil, status.Errorf(codes.NotFound, err.Error()) @@ -176,11 +194,13 @@ func (s *Server) Get(ctx context.Context, req *pb.GetRequest) (resp *pb.GetRespo func (s *Server) List(ctx context.Context, req *pb.ListRequest) (resp *pb.ListResponse, err error) { defer mon.Task()(&ctx)(&err) - if err = s.validateAuth(ctx); err != nil { + keyInfo, err := s.validateAuth(ctx) + if err != nil { return nil, err } - items, more, err := s.service.List(req.Prefix, req.StartAfter, req.EndBefore, req.Recursive, req.Limit, req.MetaFlags) + prefix := storj.JoinPaths(keyInfo.ProjectID.String(), req.Prefix) + items, more, err := s.service.List(prefix, req.StartAfter, req.EndBefore, req.Recursive, req.Limit, req.MetaFlags) if err != nil { return nil, status.Errorf(codes.Internal, "ListV2: %v", err) } @@ -192,11 +212,13 @@ func (s *Server) List(ctx context.Context, req *pb.ListRequest) (resp *pb.ListRe func (s *Server) Delete(ctx context.Context, req *pb.DeleteRequest) (resp *pb.DeleteResponse, err error) { defer mon.Task()(&ctx)(&err) - if err = s.validateAuth(ctx); err != nil { + keyInfo, err := s.validateAuth(ctx) + if err != nil { return nil, err } - err = s.service.Delete(req.GetPath()) + path := storj.JoinPaths(keyInfo.ProjectID.String(), req.GetPath()) + err = s.service.Delete(path) if err != nil { s.logger.Error("err deleting path and pointer", zap.Error(err)) return nil, status.Errorf(codes.Internal, err.Error()) @@ -209,18 +231,21 @@ func (s *Server) Delete(ctx context.Context, req *pb.DeleteRequest) (resp *pb.De func (s *Server) Iterate(ctx context.Context, req *pb.IterateRequest, f func(it storage.Iterator) error) (err error) { defer mon.Task()(&ctx)(&err) - if err = s.validateAuth(ctx); err != nil { + keyInfo, err := s.validateAuth(ctx) + if err != nil { return err } - return s.service.Iterate(req.Prefix, req.First, req.Recurse, req.Reverse, f) + prefix := storj.JoinPaths(keyInfo.ProjectID.String(), req.Prefix) + return s.service.Iterate(prefix, req.First, req.Recurse, req.Reverse, f) } // PayerBandwidthAllocation returns PayerBandwidthAllocation struct, signed and with given action type func (s *Server) PayerBandwidthAllocation(ctx context.Context, req *pb.PayerBandwidthAllocationRequest) (res *pb.PayerBandwidthAllocationResponse, err error) { defer mon.Task()(&ctx)(&err) - if err = s.validateAuth(ctx); err != nil { + _, err = s.validateAuth(ctx) + if err != nil { return nil, err } diff --git a/pkg/pointerdb/pointerdb_test.go b/pkg/pointerdb/pointerdb_test.go index 0b69c728a..96312b400 100644 --- a/pkg/pointerdb/pointerdb_test.go +++ b/pkg/pointerdb/pointerdb_test.go @@ -25,17 +25,33 @@ import ( "storj.io/storj/pkg/auth" "storj.io/storj/pkg/pb" "storj.io/storj/pkg/storage/meta" + "storj.io/storj/pkg/storj" + "storj.io/storj/satellite/console" "storj.io/storj/storage" "storj.io/storj/storage/teststore" ) +// mockAPIKeys is mock for api keys store of pointerdb +type mockAPIKeys struct { + info console.APIKeyInfo + err error +} + +// GetByKey return api key info for given key +func (keys *mockAPIKeys) GetByKey(ctx context.Context, key console.APIKey) (*console.APIKeyInfo, error) { + return &keys.info, keys.err +} + func TestServicePut(t *testing.T) { + validAPIKey := console.APIKey{} + apiKeys := &mockAPIKeys{} + for i, tt := range []struct { apiKey []byte err error errString string }{ - {nil, nil, ""}, + {[]byte(validAPIKey.String()), nil, ""}, {[]byte("wrong key"), nil, status.Errorf(codes.Unauthenticated, "Invalid API credential").Error()}, {nil, errors.New("put error"), status.Errorf(codes.Internal, "internal error").Error()}, } { @@ -46,7 +62,7 @@ func TestServicePut(t *testing.T) { db := teststore.New() service := NewService(zap.NewNop(), db) - s := Server{service: service, logger: zap.NewNop()} + s := Server{service: service, logger: zap.NewNop(), apiKeys: apiKeys} path := "a/b/c" pr := pb.Pointer{} @@ -79,12 +95,15 @@ func TestServiceGet(t *testing.T) { info := credentials.TLSInfo{State: tls.ConnectionState{PeerCertificates: peerCertificates}} + validAPIKey := console.APIKey{} + apiKeys := &mockAPIKeys{} + for i, tt := range []struct { apiKey []byte err error errString string }{ - {nil, nil, ""}, + {[]byte(validAPIKey.String()), nil, ""}, {[]byte("wrong key"), nil, status.Errorf(codes.Unauthenticated, "Invalid API credential").Error()}, {nil, errors.New("get error"), status.Errorf(codes.Internal, "internal error").Error()}, } { @@ -96,7 +115,8 @@ func TestServiceGet(t *testing.T) { db := teststore.New() service := NewService(zap.NewNop(), db) allocation := NewAllocationSigner(identity, 45) - s := NewServer(zap.NewNop(), service, allocation, nil, Config{}, identity) + + s := NewServer(zap.NewNop(), service, allocation, nil, Config{}, identity, apiKeys) path := "a/b/c" @@ -104,7 +124,7 @@ func TestServiceGet(t *testing.T) { prBytes, err := proto.Marshal(pr) assert.NoError(t, err, errTag) - _ = db.Put(storage.Key(path), storage.Value(prBytes)) + _ = db.Put(storage.Key(storj.JoinPaths(apiKeys.info.ProjectID.String(), path)), storage.Value(prBytes)) if tt.err != nil { db.ForceError++ @@ -127,12 +147,15 @@ func TestServiceGet(t *testing.T) { } func TestServiceDelete(t *testing.T) { + validAPIKey := console.APIKey{} + apiKeys := &mockAPIKeys{} + for i, tt := range []struct { apiKey []byte err error errString string }{ - {nil, nil, ""}, + {[]byte(validAPIKey.String()), nil, ""}, {[]byte("wrong key"), nil, status.Errorf(codes.Unauthenticated, "Invalid API credential").Error()}, {nil, errors.New("delete error"), status.Errorf(codes.Internal, "internal error").Error()}, } { @@ -144,9 +167,9 @@ func TestServiceDelete(t *testing.T) { path := "a/b/c" db := teststore.New() - _ = db.Put(storage.Key(path), storage.Value("hello")) + _ = db.Put(storage.Key(storj.JoinPaths(apiKeys.info.ProjectID.String(), path)), storage.Value("hello")) service := NewService(zap.NewNop(), db) - s := Server{service: service, logger: zap.NewNop()} + s := Server{service: service, logger: zap.NewNop(), apiKeys: apiKeys} if tt.err != nil { db.ForceError++ @@ -164,9 +187,12 @@ func TestServiceDelete(t *testing.T) { } func TestServiceList(t *testing.T) { + validAPIKey := console.APIKey{} + apiKeys := &mockAPIKeys{} + db := teststore.New() service := NewService(zap.NewNop(), db) - server := Server{service: service, logger: zap.NewNop()} + server := Server{service: service, logger: zap.NewNop(), apiKeys: apiKeys} pointer := &pb.Pointer{} pointer.CreationDate = ptypes.TimestampNow() @@ -177,7 +203,7 @@ func TestServiceList(t *testing.T) { } pointerValue := storage.Value(pointerBytes) - err = storage.PutAll(db, []storage.ListItem{ + items := []storage.ListItem{ {Key: storage.Key("sample.😶"), Value: pointerValue}, {Key: storage.Key("müsic"), Value: pointerValue}, {Key: storage.Key("müsic/söng1.mp3"), Value: pointerValue}, @@ -185,7 +211,13 @@ func TestServiceList(t *testing.T) { {Key: storage.Key("müsic/album/söng3.mp3"), Value: pointerValue}, {Key: storage.Key("müsic/söng4.mp3"), Value: pointerValue}, {Key: storage.Key("ビデオ/movie.mkv"), Value: pointerValue}, - }...) + } + + for i := range items { + items[i].Key = storage.Key(storj.JoinPaths(apiKeys.info.ProjectID.String(), items[i].Key.String())) + } + + err = storage.PutAll(db, items...) if err != nil { t.Fatal(err) } @@ -210,6 +242,7 @@ func TestServiceList(t *testing.T) { tests := []Test{ { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Recursive: true}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -223,6 +256,7 @@ func TestServiceList(t *testing.T) { }, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Recursive: true, MetaFlags: meta.All}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -242,6 +276,7 @@ func TestServiceList(t *testing.T) { // Error: errorWithCode(codes.Unauthenticated), // }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Recursive: true, Limit: 3}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -252,6 +287,7 @@ func TestServiceList(t *testing.T) { More: true, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{MetaFlags: meta.All}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -263,6 +299,7 @@ func TestServiceList(t *testing.T) { More: false, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{EndBefore: "ビデオ"}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -273,6 +310,7 @@ func TestServiceList(t *testing.T) { More: false, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Recursive: true, Prefix: "müsic/"}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -283,6 +321,7 @@ func TestServiceList(t *testing.T) { }, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Recursive: true, Prefix: "müsic/", StartAfter: "album/söng3.mp3"}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -292,6 +331,7 @@ func TestServiceList(t *testing.T) { }, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Prefix: "müsic/"}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -302,6 +342,7 @@ func TestServiceList(t *testing.T) { }, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Prefix: "müsic/", StartAfter: "söng1.mp3"}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -310,6 +351,7 @@ func TestServiceList(t *testing.T) { }, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Prefix: "müsic/", EndBefore: "söng4.mp3"}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ @@ -319,6 +361,7 @@ func TestServiceList(t *testing.T) { }, }, }, { + APIKey: validAPIKey.String(), Request: pb.ListRequest{Prefix: "müs", Recursive: true, EndBefore: "ic/söng4.mp3", Limit: 1}, Expected: &pb.ListResponse{ Items: []*pb.ListResponse_Item{ diff --git a/satellite/console/apikeys.go b/satellite/console/apikeys.go index f1c867b60..45d045e52 100644 --- a/satellite/console/apikeys.go +++ b/satellite/console/apikeys.go @@ -4,7 +4,6 @@ package console import ( - "bytes" "context" "crypto/rand" "encoding/base64" @@ -48,11 +47,6 @@ type APIKey [24]byte // String implements Stringer func (key APIKey) String() string { - emptyKey := APIKey{} - if bytes.Equal(key[:], emptyKey[:]) { - return "" - } - return base64.URLEncoding.EncodeToString(key[:]) } @@ -63,6 +57,17 @@ func APIKeyFromBytes(b []byte) *APIKey { return key } +// APIKeyFromBase64 creates new key from base64 string +func APIKeyFromBase64(s string) (*APIKey, error) { + b, err := base64.URLEncoding.DecodeString(s) + if err != nil { + return nil, err + } + key := new(APIKey) + copy(key[:], b) + return key, nil +} + // CreateAPIKey creates new api key func CreateAPIKey() (*APIKey, error) { key := new(APIKey) diff --git a/satellite/console/buckets.go b/satellite/console/buckets.go deleted file mode 100644 index e15bb5de9..000000000 --- a/satellite/console/buckets.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package console - -import ( - "context" - "time" - - "github.com/skyrings/skyring-common/tools/uuid" -) - -// Buckets is interface for working with bucket to project relations -type Buckets interface { - // ListBuckets returns bucket list of a given project - ListBuckets(ctx context.Context, projectID uuid.UUID) ([]Bucket, error) - // GetBucket retrieves bucket info of bucket with given name - GetBucket(ctx context.Context, name string) (*Bucket, error) - // AttachBucket attaches a bucket to a project - AttachBucket(ctx context.Context, name string, projectID uuid.UUID) (*Bucket, error) - // DeattachBucket deletes bucket info for a bucket by name - DeattachBucket(ctx context.Context, name string) error -} - -// Bucket represents bucket to project relationship -type Bucket struct { - Name string - - ProjectID uuid.UUID - - CreatedAt time.Time -} diff --git a/satellite/console/consoleweb/consoleql/mutation_test.go b/satellite/console/consoleweb/consoleql/mutation_test.go index 457dbf3ac..a646d90d4 100644 --- a/satellite/console/consoleweb/consoleql/mutation_test.go +++ b/satellite/console/consoleweb/consoleql/mutation_test.go @@ -69,6 +69,9 @@ func TestGrapqhlMutation(t *testing.T) { } t.Run("Activate account mutation", func(t *testing.T) { + t.Skip("skip it until we will have activation flow ready") + + //TODO(yar): skip it until we will have activation flow ready activationToken, err := service.GenerateActivationToken( ctx, rootUser.ID, @@ -374,20 +377,25 @@ func TestGrapqhlMutation(t *testing.T) { t.Fatal(err, project) } - activationToken1, err := service.GenerateActivationToken( - ctx, - user1.ID, - "u1@email.net", - user1.CreatedAt.Add(time.Hour*24), - ) - if err != nil { - t.Fatal(err, project) - } - _, err = service.ActivateAccount(ctx, activationToken1) - if err != nil { - t.Fatal(err, project) - } - user1.Email = "u1@email.net" + t.Run("Activation", func(t *testing.T) { + t.Skip("skip it until we will have activation flow ready") + + //TODO(yar): skip it until we will have activation flow ready + activationToken1, err := service.GenerateActivationToken( + ctx, + user1.ID, + "u1@email.net", + user1.CreatedAt.Add(time.Hour*24), + ) + if err != nil { + t.Fatal(err, project) + } + _, err = service.ActivateAccount(ctx, activationToken1) + if err != nil { + t.Fatal(err, project) + } + user1.Email = "u1@email.net" + }) user2, err := service.CreateUser(authCtx, console.CreateUser{ UserInfo: console.UserInfo{ @@ -396,23 +404,30 @@ func TestGrapqhlMutation(t *testing.T) { }, Password: "123a123", }) + if err != nil { t.Fatal(err, project) } - activationToken2, err := service.GenerateActivationToken( - ctx, - user2.ID, - "u2@email.net", - user2.CreatedAt.Add(time.Hour*24), - ) - if err != nil { - t.Fatal(err, project) - } - _, err = service.ActivateAccount(ctx, activationToken2) - if err != nil { - t.Fatal(err, project) - } - user2.Email = "u2@email.net" + + t.Run("Activation", func(t *testing.T) { + t.Skip("skip it until we will have activation flow ready") + + //TODO(yar): skip it until we will have activation flow ready + activationToken2, err := service.GenerateActivationToken( + ctx, + user2.ID, + "u2@email.net", + user2.CreatedAt.Add(time.Hour*24), + ) + if err != nil { + t.Fatal(err, project) + } + _, err = service.ActivateAccount(ctx, activationToken2) + if err != nil { + t.Fatal(err, project) + } + user2.Email = "u2@email.net" + }) t.Run("Add project members mutation", func(t *testing.T) { query := fmt.Sprintf( diff --git a/satellite/console/consoleweb/consoleql/query_test.go b/satellite/console/consoleweb/consoleql/query_test.go index 647462f99..83a685b21 100644 --- a/satellite/console/consoleweb/consoleql/query_test.go +++ b/satellite/console/consoleweb/consoleql/query_test.go @@ -66,20 +66,25 @@ func TestGraphqlQuery(t *testing.T) { t.Fatal(err) } - activationToken, err := service.GenerateActivationToken( - ctx, - rootUser.ID, - "mtest@email.com", - rootUser.CreatedAt.Add(time.Hour*24), - ) - if err != nil { - t.Fatal(err) - } - _, err = service.ActivateAccount(ctx, activationToken) - if err != nil { - t.Fatal(err) - } - rootUser.Email = "mtest@email.com" + t.Run("Activation", func(t *testing.T) { + t.Skip("skip it until we will have activation flow ready") + + //TODO(yar): skip it until we will have activation flow ready + activationToken, err := service.GenerateActivationToken( + ctx, + rootUser.ID, + "mtest@email.com", + rootUser.CreatedAt.Add(time.Hour*24), + ) + if err != nil { + t.Fatal(err) + } + _, err = service.ActivateAccount(ctx, activationToken) + if err != nil { + t.Fatal(err) + } + rootUser.Email = "mtest@email.com" + }) token, err := service.Token(ctx, createUser.Email, createUser.Password) if err != nil { @@ -191,23 +196,31 @@ func TestGraphqlQuery(t *testing.T) { }, Password: "123a123", }) + if err != nil { t.Fatal(err) } - activationToken1, err := service.GenerateActivationToken( - ctx, - user1.ID, - "muu1@email.com", - user1.CreatedAt.Add(time.Hour*24), - ) - if err != nil { - t.Fatal(err) - } - _, err = service.ActivateAccount(ctx, activationToken1) - if err != nil { - t.Fatal(err) - } - user1.Email = "muu1@email.com" + + t.Run("Activation", func(t *testing.T) { + t.Skip("skip it until we will have activation flow ready") + + //TODO(yar): skip it until we will have activation flow ready + activationToken1, err := service.GenerateActivationToken( + ctx, + user1.ID, + "muu1@email.com", + user1.CreatedAt.Add(time.Hour*24), + ) + if err != nil { + t.Fatal(err) + } + _, err = service.ActivateAccount(ctx, activationToken1) + if err != nil { + t.Fatal(err) + } + user1.Email = "muu1@email.com" + + }) user2, err := service.CreateUser(authCtx, console.CreateUser{ UserInfo: console.UserInfo{ @@ -217,23 +230,30 @@ func TestGraphqlQuery(t *testing.T) { }, Password: "123a123", }) + if err != nil { t.Fatal(err) } - activationToken2, err := service.GenerateActivationToken( - ctx, - user2.ID, - "muu2@email.com", - user2.CreatedAt.Add(time.Hour*24), - ) - if err != nil { - t.Fatal(err) - } - _, err = service.ActivateAccount(ctx, activationToken2) - if err != nil { - t.Fatal(err) - } - user2.Email = "muu2@email.com" + + t.Run("Activation", func(t *testing.T) { + t.Skip("skip it until we will have activation flow ready") + + //TODO(yar): skip it until we will have activation flow ready + activationToken2, err := service.GenerateActivationToken( + ctx, + user2.ID, + "muu2@email.com", + user2.CreatedAt.Add(time.Hour*24), + ) + if err != nil { + t.Fatal(err) + } + _, err = service.ActivateAccount(ctx, activationToken2) + if err != nil { + t.Fatal(err) + } + user2.Email = "muu2@email.com" + }) err = service.AddProjectMembers(authCtx, createdProject.ID, []string{ user1.Email, diff --git a/satellite/console/database.go b/satellite/console/database.go index 69e792c8d..47f20f551 100644 --- a/satellite/console/database.go +++ b/satellite/console/database.go @@ -15,8 +15,6 @@ type DB interface { ProjectMembers() ProjectMembers // APIKeys is a getter for APIKeys repository APIKeys() APIKeys - // Buckets is a getter for Buckets repository - Buckets() Buckets // CreateTables is a method for creating all tables for satellitedb CreateTables() error diff --git a/satellite/console/projects_test.go b/satellite/console/projects_test.go index 3d582fb36..5aebec545 100644 --- a/satellite/console/projects_test.go +++ b/satellite/console/projects_test.go @@ -130,7 +130,7 @@ func TestProjectsRepository(t *testing.T) { newProject2 := &console.Project{ Description: description, - Name: name, + Name: name + "2", } _, err = projects.Insert(ctx, newProject2) diff --git a/satellite/console/service.go b/satellite/console/service.go index b938b3d8c..0da02ec76 100644 --- a/satellite/console/service.go +++ b/satellite/console/service.go @@ -76,6 +76,7 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser) (u *User, err } u, err = s.store.Users().Insert(ctx, &User{ + Email: user.Email, FirstName: user.FirstName, LastName: user.LastName, PasswordHash: hash, @@ -83,6 +84,9 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser) (u *User, err // TODO: send "finish registration email" when email service will be ready //activationToken, err := s.GenerateActivationToken(ctx, u.ID, email, u.CreatedAt.Add(tokenExpirationTime)) + //if err != nil { + // return nil, err + //} return u, err } diff --git a/satellite/peer.go b/satellite/peer.go index 8aa4128f2..3d72c4710 100644 --- a/satellite/peer.go +++ b/satellite/peer.go @@ -286,7 +286,13 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, config *Config) (* peer.Metainfo.Database = storelogger.New(peer.Log.Named("pdb"), db) peer.Metainfo.Service = pointerdb.NewService(peer.Log.Named("pointerdb"), peer.Metainfo.Database) peer.Metainfo.Allocation = pointerdb.NewAllocationSigner(peer.Identity, config.PointerDB.BwExpiration) - peer.Metainfo.Endpoint = pointerdb.NewServer(peer.Log.Named("pointerdb:endpoint"), peer.Metainfo.Service, peer.Metainfo.Allocation, peer.Overlay.Service, config.PointerDB, peer.Identity) + peer.Metainfo.Endpoint = pointerdb.NewServer(peer.Log.Named("pointerdb:endpoint"), + peer.Metainfo.Service, + peer.Metainfo.Allocation, + peer.Overlay.Service, + config.PointerDB, + peer.Identity, peer.DB.Console().APIKeys()) + pb.RegisterPointerDBServer(peer.Public.Server.GRPC(), peer.Metainfo.Endpoint) } diff --git a/satellite/satellitedb/buckets.go b/satellite/satellitedb/buckets.go deleted file mode 100644 index 13a4146a5..000000000 --- a/satellite/satellitedb/buckets.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2019 Storj Labs, Inc. -// See LICENSE for copying information. - -package satellitedb - -import ( - "context" - - "github.com/skyrings/skyring-common/tools/uuid" - "github.com/zeebo/errs" - - "storj.io/storj/satellite/console" - dbx "storj.io/storj/satellite/satellitedb/dbx" -) - -type buckets struct { - db dbx.Methods -} - -// ListBuckets returns bucket list of a given project -func (buck *buckets) ListBuckets(ctx context.Context, projectID uuid.UUID) ([]console.Bucket, error) { - buckets, err := buck.db.All_BucketInfo_By_ProjectId_OrderBy_Asc_Name( - ctx, - dbx.BucketInfo_ProjectId(projectID[:]), - ) - - if err != nil { - return nil, err - } - - var consoleBuckets []console.Bucket - for _, bucket := range buckets { - consoleBucket, bucketErr := fromDBXBucket(bucket) - if err != nil { - err = errs.Combine(err, bucketErr) - continue - } - - consoleBuckets = append(consoleBuckets, *consoleBucket) - } - - if err != nil { - return nil, err - } - - return consoleBuckets, nil -} - -// GetBucket retrieves bucket info of bucket with given name -func (buck *buckets) GetBucket(ctx context.Context, name string) (*console.Bucket, error) { - bucket, err := buck.db.Get_BucketInfo_By_Name(ctx, dbx.BucketInfo_Name(name)) - if err != nil { - return nil, err - } - - return fromDBXBucket(bucket) -} - -// AttachBucket attaches a bucket to a project -func (buck *buckets) AttachBucket(ctx context.Context, name string, projectID uuid.UUID) (*console.Bucket, error) { - bucket, err := buck.db.Create_BucketInfo( - ctx, - dbx.BucketInfo_ProjectId(projectID[:]), - dbx.BucketInfo_Name(name), - ) - - if err != nil { - return nil, err - } - - return fromDBXBucket(bucket) -} - -// DeattachBucket deletes bucket info for a bucket by name -func (buck *buckets) DeattachBucket(ctx context.Context, name string) error { - _, err := buck.db.Delete_BucketInfo_By_Name(ctx, dbx.BucketInfo_Name(name)) - return err -} - -// fromDBXBucket creates console.Bucket from dbx.Bucket -func fromDBXBucket(bucket *dbx.BucketInfo) (*console.Bucket, error) { - projectID, err := bytesToUUID(bucket.ProjectId) - if err != nil { - return nil, err - } - - return &console.Bucket{ - ProjectID: projectID, - Name: bucket.Name, - CreatedAt: bucket.CreatedAt, - }, nil -} diff --git a/satellite/satellitedb/consoledb.go b/satellite/satellitedb/consoledb.go index 1628e1c1a..7db911aef 100644 --- a/satellite/satellitedb/consoledb.go +++ b/satellite/satellitedb/consoledb.go @@ -57,11 +57,6 @@ func (db *ConsoleDB) APIKeys() console.APIKeys { return &apikeys{db.methods} } -// Buckets is a getter for Buckets repository -func (db *ConsoleDB) Buckets() console.Buckets { - return &buckets{db.methods} -} - // CreateTables is a method for creating all tables for satellitedb func (db *ConsoleDB) CreateTables() error { if db.db == nil { diff --git a/satellite/satellitedb/dbx/satellitedb.dbx b/satellite/satellitedb/dbx/satellitedb.dbx index b674f8387..754cfec71 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx +++ b/satellite/satellitedb/dbx/satellitedb.dbx @@ -333,28 +333,4 @@ read all ( select api_key where api_key.project_id = ? orderby asc api_key.name -) - -model bucket_info ( - key name - - field project_id project.id cascade - - field name text - - field created_at timestamp ( autoinsert ) -) - -create bucket_info () -delete bucket_info ( where bucket_info.name = ? ) - -read one ( - select bucket_info - where bucket_info.name = ? -) - -read all ( - select bucket_info - where bucket_info.project_id = ? - orderby asc bucket_info.name ) \ No newline at end of file diff --git a/satellite/satellitedb/dbx/satellitedb.dbx.go b/satellite/satellitedb/dbx/satellitedb.dbx.go index 15dc43b9d..5df5cb59d 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx.go +++ b/satellite/satellitedb/dbx/satellitedb.dbx.go @@ -9,7 +9,6 @@ import ( "database/sql" "errors" "fmt" - "math/rand" "reflect" "regexp" "strconv" @@ -19,7 +18,9 @@ import ( "unicode" "github.com/lib/pq" + "github.com/mattn/go-sqlite3" + "math/rand" ) // Prevent conditional imports from causing build failures @@ -379,12 +380,6 @@ CREATE TABLE api_keys ( UNIQUE ( key ), UNIQUE ( name, project_id ) ); -CREATE TABLE bucket_infos ( - project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, - name text NOT NULL, - created_at timestamp with time zone NOT NULL, - PRIMARY KEY ( name ) -); CREATE TABLE project_members ( member_id bytea NOT NULL REFERENCES users( id ) ON DELETE CASCADE, project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, @@ -561,12 +556,6 @@ CREATE TABLE api_keys ( UNIQUE ( key ), UNIQUE ( name, project_id ) ); -CREATE TABLE bucket_infos ( - project_id BLOB NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, - name TEXT NOT NULL, - created_at TIMESTAMP NOT NULL, - PRIMARY KEY ( name ) -); CREATE TABLE project_members ( member_id BLOB NOT NULL REFERENCES users( id ) ON DELETE CASCADE, project_id BLOB NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, @@ -2170,74 +2159,6 @@ func (f ApiKey_CreatedAt_Field) value() interface{} { func (ApiKey_CreatedAt_Field) _Column() string { return "created_at" } -type BucketInfo struct { - ProjectId []byte - Name string - CreatedAt time.Time -} - -func (BucketInfo) _Table() string { return "bucket_infos" } - -type BucketInfo_Update_Fields struct { -} - -type BucketInfo_ProjectId_Field struct { - _set bool - _null bool - _value []byte -} - -func BucketInfo_ProjectId(v []byte) BucketInfo_ProjectId_Field { - return BucketInfo_ProjectId_Field{_set: true, _value: v} -} - -func (f BucketInfo_ProjectId_Field) value() interface{} { - if !f._set || f._null { - return nil - } - return f._value -} - -func (BucketInfo_ProjectId_Field) _Column() string { return "project_id" } - -type BucketInfo_Name_Field struct { - _set bool - _null bool - _value string -} - -func BucketInfo_Name(v string) BucketInfo_Name_Field { - return BucketInfo_Name_Field{_set: true, _value: v} -} - -func (f BucketInfo_Name_Field) value() interface{} { - if !f._set || f._null { - return nil - } - return f._value -} - -func (BucketInfo_Name_Field) _Column() string { return "name" } - -type BucketInfo_CreatedAt_Field struct { - _set bool - _null bool - _value time.Time -} - -func BucketInfo_CreatedAt(v time.Time) BucketInfo_CreatedAt_Field { - return BucketInfo_CreatedAt_Field{_set: true, _value: v} -} - -func (f BucketInfo_CreatedAt_Field) value() interface{} { - if !f._set || f._null { - return nil - } - return f._value -} - -func (BucketInfo_CreatedAt_Field) _Column() string { return "created_at" } - type ProjectMember struct { MemberId []byte ProjectId []byte @@ -2849,30 +2770,6 @@ func (obj *postgresImpl) Create_ApiKey(ctx context.Context, } -func (obj *postgresImpl) Create_BucketInfo(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) { - - __now := obj.db.Hooks.Now().UTC() - __project_id_val := bucket_info_project_id.value() - __name_val := bucket_info_name.value() - __created_at_val := __now - - var __embed_stmt = __sqlbundle_Literal("INSERT INTO bucket_infos ( project_id, name, created_at ) VALUES ( ?, ?, ? ) RETURNING bucket_infos.project_id, bucket_infos.name, bucket_infos.created_at") - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __project_id_val, __name_val, __created_at_val) - - bucket_info = &BucketInfo{} - err = obj.driver.QueryRow(__stmt, __project_id_val, __name_val, __created_at_val).Scan(&bucket_info.ProjectId, &bucket_info.Name, &bucket_info.CreatedAt) - if err != nil { - return nil, obj.makeErr(err) - } - return bucket_info, nil - -} - func (obj *postgresImpl) Limited_Bwagreement(ctx context.Context, limit int, offset int64) ( rows []*Bwagreement, err error) { @@ -3671,60 +3568,6 @@ func (obj *postgresImpl) All_ApiKey_By_ProjectId_OrderBy_Asc_Name(ctx context.Co } -func (obj *postgresImpl) Get_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) { - - var __embed_stmt = __sqlbundle_Literal("SELECT bucket_infos.project_id, bucket_infos.name, bucket_infos.created_at FROM bucket_infos WHERE bucket_infos.name = ?") - - var __values []interface{} - __values = append(__values, bucket_info_name.value()) - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __values...) - - bucket_info = &BucketInfo{} - err = obj.driver.QueryRow(__stmt, __values...).Scan(&bucket_info.ProjectId, &bucket_info.Name, &bucket_info.CreatedAt) - if err != nil { - return nil, obj.makeErr(err) - } - return bucket_info, nil - -} - -func (obj *postgresImpl) All_BucketInfo_By_ProjectId_OrderBy_Asc_Name(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field) ( - rows []*BucketInfo, err error) { - - var __embed_stmt = __sqlbundle_Literal("SELECT bucket_infos.project_id, bucket_infos.name, bucket_infos.created_at FROM bucket_infos WHERE bucket_infos.project_id = ? ORDER BY bucket_infos.name") - - var __values []interface{} - __values = append(__values, bucket_info_project_id.value()) - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __values...) - - __rows, err := obj.driver.Query(__stmt, __values...) - if err != nil { - return nil, obj.makeErr(err) - } - defer __rows.Close() - - for __rows.Next() { - bucket_info := &BucketInfo{} - err = __rows.Scan(&bucket_info.ProjectId, &bucket_info.Name, &bucket_info.CreatedAt) - if err != nil { - return nil, obj.makeErr(err) - } - rows = append(rows, bucket_info) - } - if err := __rows.Err(); err != nil { - return nil, obj.makeErr(err) - } - return rows, nil - -} - func (obj *postgresImpl) Update_Irreparabledb_By_Segmentpath(ctx context.Context, irreparabledb_segmentpath Irreparabledb_Segmentpath_Field, update Irreparabledb_Update_Fields) ( @@ -4382,32 +4225,6 @@ func (obj *postgresImpl) Delete_ApiKey_By_Id(ctx context.Context, } -func (obj *postgresImpl) Delete_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - deleted bool, err error) { - - var __embed_stmt = __sqlbundle_Literal("DELETE FROM bucket_infos WHERE bucket_infos.name = ?") - - var __values []interface{} - __values = append(__values, bucket_info_name.value()) - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __values...) - - __res, err := obj.driver.Exec(__stmt, __values...) - if err != nil { - return false, obj.makeErr(err) - } - - __count, err := __res.RowsAffected() - if err != nil { - return false, obj.makeErr(err) - } - - return __count > 0, nil - -} - func (impl postgresImpl) isConstraintError(err error) ( constraint string, ok bool) { if e, ok := err.(*pq.Error); ok { @@ -4426,16 +4243,6 @@ func (obj *postgresImpl) deleteAll(ctx context.Context) (count int64, err error) return 0, obj.makeErr(err) } - __count, err = __res.RowsAffected() - if err != nil { - return 0, obj.makeErr(err) - } - count += __count - __res, err = obj.driver.Exec("DELETE FROM bucket_infos;") - if err != nil { - return 0, obj.makeErr(err) - } - __count, err = __res.RowsAffected() if err != nil { return 0, obj.makeErr(err) @@ -4942,33 +4749,6 @@ func (obj *sqlite3Impl) Create_ApiKey(ctx context.Context, } -func (obj *sqlite3Impl) Create_BucketInfo(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) { - - __now := obj.db.Hooks.Now().UTC() - __project_id_val := bucket_info_project_id.value() - __name_val := bucket_info_name.value() - __created_at_val := __now - - var __embed_stmt = __sqlbundle_Literal("INSERT INTO bucket_infos ( project_id, name, created_at ) VALUES ( ?, ?, ? )") - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __project_id_val, __name_val, __created_at_val) - - __res, err := obj.driver.Exec(__stmt, __project_id_val, __name_val, __created_at_val) - if err != nil { - return nil, obj.makeErr(err) - } - __pk, err := __res.LastInsertId() - if err != nil { - return nil, obj.makeErr(err) - } - return obj.getLastBucketInfo(ctx, __pk) - -} - func (obj *sqlite3Impl) Limited_Bwagreement(ctx context.Context, limit int, offset int64) ( rows []*Bwagreement, err error) { @@ -5767,60 +5547,6 @@ func (obj *sqlite3Impl) All_ApiKey_By_ProjectId_OrderBy_Asc_Name(ctx context.Con } -func (obj *sqlite3Impl) Get_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) { - - var __embed_stmt = __sqlbundle_Literal("SELECT bucket_infos.project_id, bucket_infos.name, bucket_infos.created_at FROM bucket_infos WHERE bucket_infos.name = ?") - - var __values []interface{} - __values = append(__values, bucket_info_name.value()) - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __values...) - - bucket_info = &BucketInfo{} - err = obj.driver.QueryRow(__stmt, __values...).Scan(&bucket_info.ProjectId, &bucket_info.Name, &bucket_info.CreatedAt) - if err != nil { - return nil, obj.makeErr(err) - } - return bucket_info, nil - -} - -func (obj *sqlite3Impl) All_BucketInfo_By_ProjectId_OrderBy_Asc_Name(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field) ( - rows []*BucketInfo, err error) { - - var __embed_stmt = __sqlbundle_Literal("SELECT bucket_infos.project_id, bucket_infos.name, bucket_infos.created_at FROM bucket_infos WHERE bucket_infos.project_id = ? ORDER BY bucket_infos.name") - - var __values []interface{} - __values = append(__values, bucket_info_project_id.value()) - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __values...) - - __rows, err := obj.driver.Query(__stmt, __values...) - if err != nil { - return nil, obj.makeErr(err) - } - defer __rows.Close() - - for __rows.Next() { - bucket_info := &BucketInfo{} - err = __rows.Scan(&bucket_info.ProjectId, &bucket_info.Name, &bucket_info.CreatedAt) - if err != nil { - return nil, obj.makeErr(err) - } - rows = append(rows, bucket_info) - } - if err := __rows.Err(); err != nil { - return nil, obj.makeErr(err) - } - return rows, nil - -} - func (obj *sqlite3Impl) Update_Irreparabledb_By_Segmentpath(ctx context.Context, irreparabledb_segmentpath Irreparabledb_Segmentpath_Field, update Irreparabledb_Update_Fields) ( @@ -6548,32 +6274,6 @@ func (obj *sqlite3Impl) Delete_ApiKey_By_Id(ctx context.Context, } -func (obj *sqlite3Impl) Delete_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - deleted bool, err error) { - - var __embed_stmt = __sqlbundle_Literal("DELETE FROM bucket_infos WHERE bucket_infos.name = ?") - - var __values []interface{} - __values = append(__values, bucket_info_name.value()) - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, __values...) - - __res, err := obj.driver.Exec(__stmt, __values...) - if err != nil { - return false, obj.makeErr(err) - } - - __count, err := __res.RowsAffected() - if err != nil { - return false, obj.makeErr(err) - } - - return __count > 0, nil - -} - func (obj *sqlite3Impl) getLastBwagreement(ctx context.Context, pk int64) ( bwagreement *Bwagreement, err error) { @@ -6790,24 +6490,6 @@ func (obj *sqlite3Impl) getLastApiKey(ctx context.Context, } -func (obj *sqlite3Impl) getLastBucketInfo(ctx context.Context, - pk int64) ( - bucket_info *BucketInfo, err error) { - - var __embed_stmt = __sqlbundle_Literal("SELECT bucket_infos.project_id, bucket_infos.name, bucket_infos.created_at FROM bucket_infos WHERE _rowid_ = ?") - - var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) - obj.logStmt(__stmt, pk) - - bucket_info = &BucketInfo{} - err = obj.driver.QueryRow(__stmt, pk).Scan(&bucket_info.ProjectId, &bucket_info.Name, &bucket_info.CreatedAt) - if err != nil { - return nil, obj.makeErr(err) - } - return bucket_info, nil - -} - func (impl sqlite3Impl) isConstraintError(err error) ( constraint string, ok bool) { if e, ok := err.(sqlite3.Error); ok { @@ -6831,16 +6513,6 @@ func (obj *sqlite3Impl) deleteAll(ctx context.Context) (count int64, err error) return 0, obj.makeErr(err) } - __count, err = __res.RowsAffected() - if err != nil { - return 0, obj.makeErr(err) - } - count += __count - __res, err = obj.driver.Exec("DELETE FROM bucket_infos;") - if err != nil { - return 0, obj.makeErr(err) - } - __count, err = __res.RowsAffected() if err != nil { return 0, obj.makeErr(err) @@ -7042,16 +6714,6 @@ func (rx *Rx) All_ApiKey_By_ProjectId_OrderBy_Asc_Name(ctx context.Context, return tx.All_ApiKey_By_ProjectId_OrderBy_Asc_Name(ctx, api_key_project_id) } -func (rx *Rx) All_BucketInfo_By_ProjectId_OrderBy_Asc_Name(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field) ( - rows []*BucketInfo, err error) { - var tx *Tx - if tx, err = rx.getTx(ctx); err != nil { - return - } - return tx.All_BucketInfo_By_ProjectId_OrderBy_Asc_Name(ctx, bucket_info_project_id) -} - func (rx *Rx) All_Bwagreement(ctx context.Context) ( rows []*Bwagreement, err error) { var tx *Tx @@ -7178,18 +6840,6 @@ func (rx *Rx) Create_ApiKey(ctx context.Context, } -func (rx *Rx) Create_BucketInfo(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) { - var tx *Tx - if tx, err = rx.getTx(ctx); err != nil { - return - } - return tx.Create_BucketInfo(ctx, bucket_info_project_id, bucket_info_name) - -} - func (rx *Rx) Create_Bwagreement(ctx context.Context, bwagreement_serialnum Bwagreement_Serialnum_Field, bwagreement_storage_node_id Bwagreement_StorageNodeId_Field, @@ -7344,16 +6994,6 @@ func (rx *Rx) Delete_ApiKey_By_Id(ctx context.Context, return tx.Delete_ApiKey_By_Id(ctx, api_key_id) } -func (rx *Rx) Delete_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - deleted bool, err error) { - var tx *Tx - if tx, err = rx.getTx(ctx); err != nil { - return - } - return tx.Delete_BucketInfo_By_Name(ctx, bucket_info_name) -} - func (rx *Rx) Delete_Injuredsegment_By_Id(ctx context.Context, injuredsegment_id Injuredsegment_Id_Field) ( deleted bool, err error) { @@ -7484,16 +7124,6 @@ func (rx *Rx) Get_ApiKey_By_Key(ctx context.Context, return tx.Get_ApiKey_By_Key(ctx, api_key_key) } -func (rx *Rx) Get_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) { - var tx *Tx - if tx, err = rx.getTx(ctx); err != nil { - return - } - return tx.Get_BucketInfo_By_Name(ctx, bucket_info_name) -} - func (rx *Rx) Get_Irreparabledb_By_Segmentpath(ctx context.Context, irreparabledb_segmentpath Irreparabledb_Segmentpath_Field) ( irreparabledb *Irreparabledb, err error) { @@ -7699,10 +7329,6 @@ type Methods interface { api_key_project_id ApiKey_ProjectId_Field) ( rows []*ApiKey, err error) - All_BucketInfo_By_ProjectId_OrderBy_Asc_Name(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field) ( - rows []*BucketInfo, err error) - All_Bwagreement(ctx context.Context) ( rows []*Bwagreement, err error) @@ -7759,11 +7385,6 @@ type Methods interface { api_key_name ApiKey_Name_Field) ( api_key *ApiKey, err error) - Create_BucketInfo(ctx context.Context, - bucket_info_project_id BucketInfo_ProjectId_Field, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) - Create_Bwagreement(ctx context.Context, bwagreement_serialnum Bwagreement_Serialnum_Field, bwagreement_storage_node_id Bwagreement_StorageNodeId_Field, @@ -7844,10 +7465,6 @@ type Methods interface { api_key_id ApiKey_Id_Field) ( deleted bool, err error) - Delete_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - deleted bool, err error) - Delete_Injuredsegment_By_Id(ctx context.Context, injuredsegment_id Injuredsegment_Id_Field) ( deleted bool, err error) @@ -7900,10 +7517,6 @@ type Methods interface { api_key_key ApiKey_Key_Field) ( api_key *ApiKey, err error) - Get_BucketInfo_By_Name(ctx context.Context, - bucket_info_name BucketInfo_Name_Field) ( - bucket_info *BucketInfo, err error) - Get_Irreparabledb_By_Segmentpath(ctx context.Context, irreparabledb_segmentpath Irreparabledb_Segmentpath_Field) ( irreparabledb *Irreparabledb, err error) diff --git a/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql b/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql index 1b81f005b..3186b7fd9 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql +++ b/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql @@ -107,12 +107,6 @@ CREATE TABLE api_keys ( UNIQUE ( key ), UNIQUE ( name, project_id ) ); -CREATE TABLE bucket_infos ( - project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, - name text NOT NULL, - created_at timestamp with time zone NOT NULL, - PRIMARY KEY ( name ) -); CREATE TABLE project_members ( member_id bytea NOT NULL REFERENCES users( id ) ON DELETE CASCADE, project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, diff --git a/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql b/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql index d6e3787cd..31515b408 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql +++ b/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql @@ -107,12 +107,6 @@ CREATE TABLE api_keys ( UNIQUE ( key ), UNIQUE ( name, project_id ) ); -CREATE TABLE bucket_infos ( - project_id BLOB NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, - name TEXT NOT NULL, - created_at TIMESTAMP NOT NULL, - PRIMARY KEY ( name ) -); CREATE TABLE project_members ( member_id BLOB NOT NULL REFERENCES users( id ) ON DELETE CASCADE, project_id BLOB NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, diff --git a/satellite/satellitedb/locked.go b/satellite/satellitedb/locked.go index 8a421cf5c..6a04c3ee9 100644 --- a/satellite/satellitedb/locked.go +++ b/satellite/satellitedb/locked.go @@ -206,47 +206,6 @@ func (m *lockedAPIKeys) Update(ctx context.Context, key console.APIKeyInfo) erro return m.db.Update(ctx, key) } -// Buckets is a getter for Buckets repository -func (m *lockedConsole) Buckets() console.Buckets { - m.Lock() - defer m.Unlock() - return &lockedBuckets{m.Locker, m.db.Buckets()} -} - -// lockedBuckets implements locking wrapper for console.Buckets -type lockedBuckets struct { - sync.Locker - db console.Buckets -} - -// AttachBucket attaches a bucket to a project -func (m *lockedBuckets) AttachBucket(ctx context.Context, name string, projectID uuid.UUID) (*console.Bucket, error) { - m.Lock() - defer m.Unlock() - return m.db.AttachBucket(ctx, name, projectID) -} - -// DeattachBucket deletes bucket info for a bucket by name -func (m *lockedBuckets) DeattachBucket(ctx context.Context, name string) error { - m.Lock() - defer m.Unlock() - return m.db.DeattachBucket(ctx, name) -} - -// GetBucket retrieves bucket info of bucket with given name -func (m *lockedBuckets) GetBucket(ctx context.Context, name string) (*console.Bucket, error) { - m.Lock() - defer m.Unlock() - return m.db.GetBucket(ctx, name) -} - -// ListBuckets returns bucket list of a given project -func (m *lockedBuckets) ListBuckets(ctx context.Context, projectID uuid.UUID) ([]console.Bucket, error) { - m.Lock() - defer m.Unlock() - return m.db.ListBuckets(ctx, projectID) -} - // Close is used to close db connection func (m *lockedConsole) Close() error { m.Lock()