From 5fc493b276982d634b5f5610187167750da7349e Mon Sep 17 00:00:00 2001 From: dlamarmorgan Date: Tue, 18 Apr 2023 15:15:00 -0700 Subject: [PATCH] metainfo: per-project and user-agent eventkit-based usage tracking Add eventkit events for each satellite RPC type, tagged with user agent and public project id. Change-Id: I838401683298d4594495de18563c55031e82f881 --- satellite/console/apikeys.go | 15 +-- satellite/metainfo/endpoint.go | 17 ++- satellite/metainfo/endpoint_bucket.go | 4 + satellite/metainfo/endpoint_object.go | 68 ++++++++++- satellite/metainfo/endpoint_segment.go | 8 +- satellite/satellitedb/apikeys.go | 41 ++++--- satellite/satellitedb/consoledb.go | 2 +- satellite/satellitedb/dbx/project.dbx | 11 +- satellite/satellitedb/dbx/satellitedb.dbx.go | 119 ++++++++++--------- 9 files changed, 195 insertions(+), 90 deletions(-) diff --git a/satellite/console/apikeys.go b/satellite/console/apikeys.go index 1043dc026..b096b4b7d 100644 --- a/satellite/console/apikeys.go +++ b/satellite/console/apikeys.go @@ -51,13 +51,14 @@ type CreateAPIKeyResponse struct { // APIKeyInfo describing api key model in the database. type APIKeyInfo struct { - ID uuid.UUID `json:"id"` - ProjectID uuid.UUID `json:"projectId"` - UserAgent []byte `json:"userAgent"` - Name string `json:"name"` - Head []byte `json:"-"` - Secret []byte `json:"-"` - CreatedAt time.Time `json:"createdAt"` + ID uuid.UUID `json:"id"` + ProjectID uuid.UUID `json:"projectId"` + ProjectPublicID uuid.UUID `json:"projectPublicId"` + UserAgent []byte `json:"userAgent"` + Name string `json:"name"` + Head []byte `json:"-"` + Secret []byte `json:"-"` + CreatedAt time.Time `json:"createdAt"` } // APIKeyCursor holds info for api keys cursor pagination. diff --git a/satellite/metainfo/endpoint.go b/satellite/metainfo/endpoint.go index 81a82ce90..d8ea2a3c7 100644 --- a/satellite/metainfo/endpoint.go +++ b/satellite/metainfo/endpoint.go @@ -5,8 +5,10 @@ package metainfo import ( "context" + "fmt" "time" + "github.com/jtolio/eventkit" "github.com/spacemonkeygo/monkit/v3" "github.com/zeebo/errs" "go.uber.org/zap" @@ -38,6 +40,8 @@ const ( var ( mon = monkit.Package() + evs = eventkit.Package() + // Error general metainfo error. Error = errs.Class("metainfo") // ErrNodeAlreadyExists pointer already has a piece for a node err. @@ -153,6 +157,7 @@ func (endpoint *Endpoint) ProjectInfo(ctx context.Context, req *pb.ProjectInfoRe if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) salt, err := endpoint.projects.GetSalt(ctx, keyInfo.ProjectID) if err != nil { @@ -160,7 +165,8 @@ func (endpoint *Endpoint) ProjectInfo(ctx context.Context, req *pb.ProjectInfoRe } return &pb.ProjectInfoResponse{ - ProjectSalt: salt, + ProjectPublicId: keyInfo.ProjectPublicID.Bytes(), + ProjectSalt: salt, }, nil } @@ -178,6 +184,7 @@ func (endpoint *Endpoint) RevokeAPIKey(ctx context.Context, req *pb.RevokeAPIKey if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.revocations.Revoke(ctx, macToRevoke.Tail(), keyInfo.ID[:]) if err != nil { @@ -312,3 +319,11 @@ func (endpoint *Endpoint) convertMetabaseErr(err error) error { return rpcstatus.Error(rpcstatus.Internal, err.Error()) } } + +func (endpoint *Endpoint) usageTracking(keyInfo *console.APIKeyInfo, header *pb.RequestHeader, name string, tags ...eventkit.Tag) { + evs.Event("usage", append([]eventkit.Tag{ + eventkit.Bytes("project-public-id", keyInfo.ProjectPublicID[:]), + eventkit.String("user-agent", string(header.UserAgent)), + eventkit.String("request", name), + }, tags...)...) +} diff --git a/satellite/metainfo/endpoint_bucket.go b/satellite/metainfo/endpoint_bucket.go index d1267b5d0..f05bbdf24 100644 --- a/satellite/metainfo/endpoint_bucket.go +++ b/satellite/metainfo/endpoint_bucket.go @@ -33,6 +33,7 @@ func (endpoint *Endpoint) GetBucket(ctx context.Context, req *pb.BucketGetReques if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) bucket, err := endpoint.buckets.GetMinimalBucket(ctx, req.GetName(), keyInfo.ProjectID) if err != nil { @@ -68,6 +69,7 @@ func (endpoint *Endpoint) CreateBucket(ctx context.Context, req *pb.BucketCreate if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Name) if err != nil { @@ -175,6 +177,7 @@ func (endpoint *Endpoint) DeleteBucket(ctx context.Context, req *pb.BucketDelete if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Name) if err != nil { @@ -310,6 +313,7 @@ func (endpoint *Endpoint) ListBuckets(ctx context.Context, req *pb.BucketListReq if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) allowedBuckets, err := getAllowedBuckets(ctx, req.Header, action) if err != nil { diff --git a/satellite/metainfo/endpoint_object.go b/satellite/metainfo/endpoint_object.go index 9f95bc0c5..48e27cd1b 100644 --- a/satellite/metainfo/endpoint_object.go +++ b/satellite/metainfo/endpoint_object.go @@ -9,6 +9,7 @@ import ( "fmt" "time" + "github.com/jtolio/eventkit" "github.com/spacemonkeygo/monkit/v3" "go.uber.org/zap" @@ -60,6 +61,7 @@ func (endpoint *Endpoint) BeginObject(ctx context.Context, req *pb.ObjectBeginRe if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) if !req.ExpiresAt.IsZero() && !req.ExpiresAt.After(time.Now()) { return nil, rpcstatus.Error(rpcstatus.InvalidArgument, "Invalid expiration time") @@ -206,6 +208,20 @@ func (endpoint *Endpoint) CommitObject(ctx context.Context, req *pb.ObjectCommit if err != nil { return nil, err } + var committedObject *metabase.Object + defer func() { + var tags []eventkit.Tag + if committedObject != nil { + tags = []eventkit.Tag{ + eventkit.Bool("expires", committedObject.ExpiresAt != nil), + eventkit.Int64("segment_count", int64(committedObject.SegmentCount)), + eventkit.Int64("total_plain_size", committedObject.TotalPlainSize), + eventkit.Int64("total_encrypted_size", committedObject.TotalEncryptedSize), + eventkit.Int64("fixed_segment_size", int64(committedObject.FixedSegmentSize)), + } + } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req), tags...) + }() id, err := uuid.FromBytes(streamID.StreamId) if err != nil { @@ -217,7 +233,9 @@ func (endpoint *Endpoint) CommitObject(ctx context.Context, req *pb.ObjectCommit streamMeta := &pb.StreamMeta{} encryption := storj.EncryptionParameters{} err = pb.Unmarshal(req.EncryptedMetadata, streamMeta) - if err == nil { + if err != nil { + // TODO: what if this is an error we don't expect? + } else { encryption.CipherSuite = storj.CipherSuite(streamMeta.EncryptionType) encryption.BlockSize = streamMeta.EncryptionBlockSize } @@ -259,10 +277,11 @@ func (endpoint *Endpoint) CommitObject(ctx context.Context, req *pb.ObjectCommit return nil, err } - _, err = endpoint.metabase.CommitObject(ctx, request) + object, err := endpoint.metabase.CommitObject(ctx, request) if err != nil { return nil, endpoint.convertMetabaseErr(err) } + committedObject = &object mon.Meter("req_commit_object").Mark(1) @@ -293,6 +312,7 @@ func (endpoint *Endpoint) GetObject(ctx context.Context, req *pb.ObjectGetReques if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Bucket) if err != nil { @@ -310,6 +330,17 @@ func (endpoint *Endpoint) GetObject(ctx context.Context, req *pb.ObjectGetReques return nil, endpoint.convertMetabaseErr(err) } + { + tags := []eventkit.Tag{ + eventkit.Bool("expires", mbObject.ExpiresAt != nil), + eventkit.Int64("segment_count", int64(mbObject.SegmentCount)), + eventkit.Int64("total_plain_size", mbObject.TotalPlainSize), + eventkit.Int64("total_encrypted_size", mbObject.TotalEncryptedSize), + eventkit.Int64("fixed_segment_size", int64(mbObject.FixedSegmentSize)), + } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req), tags...) + } + var segmentRS *pb.RedundancyScheme // TODO this code is triggered only by very old uplink library and we will remove it eventually. if !req.RedundancySchemePerSegment && mbObject.SegmentCount > 0 { @@ -423,6 +454,22 @@ func (endpoint *Endpoint) DownloadObject(ctx context.Context, req *pb.ObjectDown return nil, rpcstatus.Error(rpcstatus.InvalidArgument, err.Error()) } + { + tags := []eventkit.Tag{ + eventkit.Bool("expires", object.ExpiresAt != nil), + eventkit.Int64("segment_count", int64(object.SegmentCount)), + eventkit.Int64("total_plain_size", object.TotalPlainSize), + eventkit.Int64("total_encrypted_size", object.TotalEncryptedSize), + eventkit.Int64("fixed_segment_size", int64(object.FixedSegmentSize)), + } + if streamRange != nil { + tags = append(tags, + eventkit.Int64("range_start", streamRange.PlainStart), + eventkit.Int64("range_end", streamRange.PlainLimit)) + } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req), tags...) + } + segments, err := endpoint.metabase.ListSegments(ctx, metabase.ListSegments{ StreamID: object.StreamID, Range: streamRange, @@ -759,6 +806,7 @@ func (endpoint *Endpoint) ListObjects(ctx context.Context, req *pb.ObjectListReq if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Bucket) if err != nil { @@ -898,6 +946,7 @@ func (endpoint *Endpoint) ListPendingObjectStreams(ctx context.Context, req *pb. if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Bucket) if err != nil { @@ -1010,6 +1059,7 @@ func (endpoint *Endpoint) BeginDeleteObject(ctx context.Context, req *pb.ObjectB if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Bucket) if err != nil { @@ -1098,6 +1148,7 @@ func (endpoint *Endpoint) GetObjectIPs(ctx context.Context, req *pb.ObjectGetIPs if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Bucket) if err != nil { @@ -1174,6 +1225,7 @@ func (endpoint *Endpoint) UpdateObjectMetadata(ctx context.Context, req *pb.Obje if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.Bucket) if err != nil { @@ -1399,6 +1451,7 @@ func (endpoint *Endpoint) objectEntryToProtoListItem(ctx context.Context, bucket // // NOTE: this method is exported for being able to individually test it without // having import cycles. +// TODO: see note on DeleteObjectAnyStatus. func (endpoint *Endpoint) DeleteCommittedObject( ctx context.Context, projectID uuid.UUID, bucket string, object metabase.ObjectKey, ) (deletedObjects []*pb.Object, err error) { @@ -1441,6 +1494,12 @@ func (endpoint *Endpoint) DeleteCommittedObject( // // NOTE: this method is exported for being able to individually test it without // having import cycles. +// TODO regarding the above note: exporting for testing is fine, but we should name +// it something that will definitely never ever be added to the rpc set in DRPC +// definitions. If we ever decide to add an RPC method called "DeleteObjectAnyStatus", +// DRPC interface definitions is all that is standing in the way from someone +// remotely calling this. We should name this InternalDeleteObjectAnyStatus or +// something. func (endpoint *Endpoint) DeleteObjectAnyStatus(ctx context.Context, location metabase.ObjectLocation, ) (deletedObjects []*pb.Object, err error) { defer mon.Task()(&ctx, location.ProjectID.String(), location.BucketName, location.ObjectKey)(&err) @@ -1479,6 +1538,7 @@ func (endpoint *Endpoint) DeleteObjectAnyStatus(ctx context.Context, location me // // NOTE: this method is exported for being able to individually test it without // having import cycles. +// TODO: see note on DeleteObjectAnyStatus. func (endpoint *Endpoint) DeletePendingObject(ctx context.Context, stream metabase.ObjectStream) (deletedObjects []*pb.Object, err error) { req := metabase.DeletePendingObject{ ObjectStream: stream, @@ -1586,6 +1646,7 @@ func (endpoint *Endpoint) BeginMoveObject(ctx context.Context, req *pb.ObjectBeg if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) for _, bucket := range [][]byte{req.Bucket, req.NewBucket} { err = endpoint.validateBucket(ctx, bucket) @@ -1732,6 +1793,7 @@ func (endpoint *Endpoint) FinishMoveObject(ctx context.Context, req *pb.ObjectFi if err != nil { return nil, rpcstatus.Error(rpcstatus.Unauthenticated, err.Error()) } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.NewBucket) if err != nil { @@ -1809,6 +1871,7 @@ func (endpoint *Endpoint) BeginCopyObject(ctx context.Context, req *pb.ObjectBeg if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) for _, bucket := range [][]byte{req.Bucket, req.NewBucket} { err = endpoint.validateBucket(ctx, bucket) @@ -1921,6 +1984,7 @@ func (endpoint *Endpoint) FinishCopyObject(ctx context.Context, req *pb.ObjectFi if err != nil { return nil, rpcstatus.Error(rpcstatus.Unauthenticated, err.Error()) } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) err = endpoint.validateBucket(ctx, req.NewBucket) if err != nil { diff --git a/satellite/metainfo/endpoint_segment.go b/satellite/metainfo/endpoint_segment.go index 9ed0e3277..56861c399 100644 --- a/satellite/metainfo/endpoint_segment.go +++ b/satellite/metainfo/endpoint_segment.go @@ -48,6 +48,7 @@ func (endpoint *Endpoint) BeginSegment(ctx context.Context, req *pb.SegmentBegin if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) // no need to validate streamID fields because it was validated during BeginObject @@ -168,6 +169,7 @@ func (endpoint *Endpoint) RetryBeginSegmentPieces(ctx context.Context, req *pb.R if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) if len(req.RetryPieceNumbers) == 0 { return nil, rpcstatus.Error(rpcstatus.InvalidArgument, "piece numbers to exchange cannot be empty") @@ -258,6 +260,7 @@ func (endpoint *Endpoint) CommitSegment(ctx context.Context, req *pb.SegmentComm if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) // cheap basic verification if numResults := len(req.UploadResult); numResults < int(endpoint.defaultRS.GetSuccessThreshold()) { @@ -436,6 +439,7 @@ func (endpoint *Endpoint) MakeInlineSegment(ctx context.Context, req *pb.Segment if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) if req.Position.Index < 0 { return nil, rpcstatus.Error(rpcstatus.InvalidArgument, "segment index must be greater then 0") @@ -517,7 +521,7 @@ func (endpoint *Endpoint) ListSegments(ctx context.Context, req *pb.SegmentListR return nil, rpcstatus.Error(rpcstatus.InvalidArgument, err.Error()) } - _, err = endpoint.validateAuth(ctx, req.Header, macaroon.Action{ + keyInfo, err := endpoint.validateAuth(ctx, req.Header, macaroon.Action{ Op: macaroon.ActionRead, Bucket: streamID.Bucket, EncryptedPath: streamID.EncryptedObjectKey, @@ -526,6 +530,7 @@ func (endpoint *Endpoint) ListSegments(ctx context.Context, req *pb.SegmentListR if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) cursor := req.CursorPosition if cursor == nil { @@ -614,6 +619,7 @@ func (endpoint *Endpoint) DownloadSegment(ctx context.Context, req *pb.SegmentDo if err != nil { return nil, err } + endpoint.usageTracking(keyInfo, req.Header, fmt.Sprintf("%T", req)) bucket := metabase.BucketLocation{ProjectID: keyInfo.ProjectID, BucketName: string(streamID.Bucket)} diff --git a/satellite/satellitedb/apikeys.go b/satellite/satellitedb/apikeys.go index 3f6b6f3ec..38c9433dc 100644 --- a/satellite/satellitedb/apikeys.go +++ b/satellite/satellitedb/apikeys.go @@ -21,7 +21,7 @@ var _ console.APIKeys = (*apikeys)(nil) // apikeys is an implementation of satellite.APIKeys. type apikeys struct { methods dbx.Methods - lru *lrucache.ExpiringLRUOf[*dbx.ApiKey] + lru *lrucache.ExpiringLRUOf[*dbx.ApiKey_Project_PublicId_Row] db *satelliteDB } @@ -74,9 +74,10 @@ func (keys *apikeys) GetPagedByProjectID(ctx context.Context, projectID uuid.UUI } repoundQuery := keys.db.Rebind(` - SELECT ak.id, ak.project_id, ak.name, ak.user_agent, ak.created_at - FROM api_keys ak + SELECT ak.id, ak.project_id, ak.name, ak.user_agent, ak.created_at, p.public_id + FROM api_keys ak, projects p WHERE ak.project_id = ? + AND ak.project_id = p.id AND lower(ak.name) LIKE ? ORDER BY ` + sanitizedAPIKeyOrderColumnName(cursor.Order) + ` ` + sanitizeOrderDirectionName(page.OrderDirection) + ` @@ -98,7 +99,7 @@ func (keys *apikeys) GetPagedByProjectID(ctx context.Context, projectID uuid.UUI for rows.Next() { ak := console.APIKeyInfo{} - err = rows.Scan(&ak.ID, &ak.ProjectID, &ak.Name, &ak.UserAgent, &ak.CreatedAt) + err = rows.Scan(&ak.ID, &ak.ProjectID, &ak.Name, &ak.UserAgent, &ak.CreatedAt, &ak.ProjectPublicID) if err != nil { return nil, err } @@ -127,7 +128,7 @@ func (keys *apikeys) GetPagedByProjectID(ctx context.Context, projectID uuid.UUI // Get implements satellite.APIKeys. func (keys *apikeys) Get(ctx context.Context, id uuid.UUID) (_ *console.APIKeyInfo, err error) { defer mon.Task()(&ctx)(&err) - dbKey, err := keys.methods.Get_ApiKey_By_Id(ctx, dbx.ApiKey_Id(id[:])) + dbKey, err := keys.methods.Get_ApiKey_Project_PublicId_By_ApiKey_Id(ctx, dbx.ApiKey_Id(id[:])) if err != nil { return nil, err } @@ -139,8 +140,8 @@ func (keys *apikeys) Get(ctx context.Context, id uuid.UUID) (_ *console.APIKeyIn func (keys *apikeys) GetByHead(ctx context.Context, head []byte) (_ *console.APIKeyInfo, err error) { defer mon.Task()(&ctx)(&err) - dbKey, err := keys.lru.Get(ctx, string(head), func() (*dbx.ApiKey, error) { - return keys.methods.Get_ApiKey_By_Head(ctx, dbx.ApiKey_Head(head)) + dbKey, err := keys.lru.Get(ctx, string(head), func() (*dbx.ApiKey_Project_PublicId_Row, error) { + return keys.methods.Get_ApiKey_Project_PublicId_By_ApiKey_Head(ctx, dbx.ApiKey_Head(head)) }) if err != nil { return nil, err @@ -151,7 +152,7 @@ func (keys *apikeys) GetByHead(ctx context.Context, head []byte) (_ *console.API // GetByNameAndProjectID implements satellite.APIKeys. func (keys *apikeys) GetByNameAndProjectID(ctx context.Context, name string, projectID uuid.UUID) (_ *console.APIKeyInfo, err error) { defer mon.Task()(&ctx)(&err) - dbKey, err := keys.methods.Get_ApiKey_By_Name_And_ProjectId(ctx, + dbKey, err := keys.methods.Get_ApiKey_Project_PublicId_By_ApiKey_Name_And_ApiKey_ProjectId(ctx, dbx.ApiKey_Name(name), dbx.ApiKey_ProjectId(projectID[:])) if err != nil { @@ -174,7 +175,7 @@ func (keys *apikeys) Create(ctx context.Context, head []byte, info console.APIKe optional.UserAgent = dbx.ApiKey_UserAgent(info.UserAgent) } - dbKey, err := keys.methods.Create_ApiKey( + _, err = keys.methods.Create_ApiKey( ctx, dbx.ApiKey_Id(id[:]), dbx.ApiKey_ProjectId(info.ProjectID[:]), @@ -188,7 +189,7 @@ func (keys *apikeys) Create(ctx context.Context, head []byte, info console.APIKe return nil, err } - return fromDBXAPIKey(ctx, dbKey) + return keys.Get(ctx, id) } // Update implements satellite.APIKeys. @@ -211,8 +212,9 @@ func (keys *apikeys) Delete(ctx context.Context, id uuid.UUID) (err error) { } // fromDBXAPIKey converts dbx.ApiKey to satellite.APIKeyInfo. -func fromDBXAPIKey(ctx context.Context, key *dbx.ApiKey) (_ *console.APIKeyInfo, err error) { +func fromDBXAPIKey(ctx context.Context, row *dbx.ApiKey_Project_PublicId_Row) (_ *console.APIKeyInfo, err error) { defer mon.Task()(&ctx)(&err) + key := &row.ApiKey id, err := uuid.FromBytes(key.Id) if err != nil { return nil, err @@ -222,14 +224,19 @@ func fromDBXAPIKey(ctx context.Context, key *dbx.ApiKey) (_ *console.APIKeyInfo, if err != nil { return nil, err } + projectPublicID, err := uuid.FromBytes(row.Project_PublicId) + if err != nil { + return nil, err + } result := &console.APIKeyInfo{ - ID: id, - ProjectID: projectID, - Name: key.Name, - CreatedAt: key.CreatedAt, - Head: key.Head, - Secret: key.Secret, + ID: id, + ProjectID: projectID, + ProjectPublicID: projectPublicID, + Name: key.Name, + CreatedAt: key.CreatedAt, + Head: key.Head, + Secret: key.Secret, } if key.UserAgent != nil { diff --git a/satellite/satellitedb/consoledb.go b/satellite/satellitedb/consoledb.go index 1885a0c79..b2e523ee5 100644 --- a/satellite/satellitedb/consoledb.go +++ b/satellite/satellitedb/consoledb.go @@ -53,7 +53,7 @@ func (db *ConsoleDB) APIKeys() console.APIKeys { options.Name = "satellitedb-apikeys" db.apikeys = &apikeys{ methods: db.methods, - lru: lrucache.NewOf[*dbx.ApiKey](options), + lru: lrucache.NewOf[*dbx.ApiKey_Project_PublicId_Row](options), db: db.db, } }) diff --git a/satellite/satellitedb/dbx/project.dbx b/satellite/satellitedb/dbx/project.dbx index 9037c49d3..f84d1c7e7 100644 --- a/satellite/satellitedb/dbx/project.dbx +++ b/satellite/satellitedb/dbx/project.dbx @@ -177,15 +177,18 @@ update api_key ( delete api_key ( where api_key.id = ? ) read one ( - select api_key + select api_key project.public_id + join project.id = api_key.project_id where api_key.id = ? ) read one ( - select api_key + select api_key project.public_id + join project.id = api_key.project_id where api_key.head = ? ) read one ( - select api_key + select api_key project.public_id + join project.id = api_key.project_id where api_key.name = ? where api_key.project_id = ? -) +) \ No newline at end of file diff --git a/satellite/satellitedb/dbx/satellitedb.dbx.go b/satellite/satellitedb/dbx/satellitedb.dbx.go index 3c2698f28..c29dceb38 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx.go +++ b/satellite/satellitedb/dbx/satellitedb.dbx.go @@ -11817,6 +11817,11 @@ func (h *__sqlbundle_Hole) Render() string { // end runtime support for building sql statements // +type ApiKey_Project_PublicId_Row struct { + ApiKey ApiKey + Project_PublicId []byte +} + type Balance_Row struct { Balance int64 } @@ -15829,12 +15834,12 @@ func (obj *pgxImpl) All_ProjectMember_By_MemberId(ctx context.Context, } -func (obj *pgxImpl) Get_ApiKey_By_Id(ctx context.Context, +func (obj *pgxImpl) Get_ApiKey_Project_PublicId_By_ApiKey_Id(ctx context.Context, api_key_id ApiKey_Id_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { defer mon.Task()(&ctx)(&err) - var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at FROM api_keys WHERE api_keys.id = ?") + var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at, projects.public_id FROM projects JOIN api_keys ON projects.id = api_keys.project_id WHERE api_keys.id = ?") var __values []interface{} __values = append(__values, api_key_id.value()) @@ -15842,21 +15847,21 @@ func (obj *pgxImpl) Get_ApiKey_By_Id(ctx context.Context, var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) obj.logStmt(__stmt, __values...) - api_key = &ApiKey{} - err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&api_key.Id, &api_key.ProjectId, &api_key.Head, &api_key.Name, &api_key.Secret, &api_key.PartnerId, &api_key.UserAgent, &api_key.CreatedAt) + row = &ApiKey_Project_PublicId_Row{} + err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&row.ApiKey.Id, &row.ApiKey.ProjectId, &row.ApiKey.Head, &row.ApiKey.Name, &row.ApiKey.Secret, &row.ApiKey.PartnerId, &row.ApiKey.UserAgent, &row.ApiKey.CreatedAt, &row.Project_PublicId) if err != nil { - return (*ApiKey)(nil), obj.makeErr(err) + return (*ApiKey_Project_PublicId_Row)(nil), obj.makeErr(err) } - return api_key, nil + return row, nil } -func (obj *pgxImpl) Get_ApiKey_By_Head(ctx context.Context, +func (obj *pgxImpl) Get_ApiKey_Project_PublicId_By_ApiKey_Head(ctx context.Context, api_key_head ApiKey_Head_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { defer mon.Task()(&ctx)(&err) - var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at FROM api_keys WHERE api_keys.head = ?") + var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at, projects.public_id FROM projects JOIN api_keys ON projects.id = api_keys.project_id WHERE api_keys.head = ?") var __values []interface{} __values = append(__values, api_key_head.value()) @@ -15864,22 +15869,22 @@ func (obj *pgxImpl) Get_ApiKey_By_Head(ctx context.Context, var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) obj.logStmt(__stmt, __values...) - api_key = &ApiKey{} - err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&api_key.Id, &api_key.ProjectId, &api_key.Head, &api_key.Name, &api_key.Secret, &api_key.PartnerId, &api_key.UserAgent, &api_key.CreatedAt) + row = &ApiKey_Project_PublicId_Row{} + err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&row.ApiKey.Id, &row.ApiKey.ProjectId, &row.ApiKey.Head, &row.ApiKey.Name, &row.ApiKey.Secret, &row.ApiKey.PartnerId, &row.ApiKey.UserAgent, &row.ApiKey.CreatedAt, &row.Project_PublicId) if err != nil { - return (*ApiKey)(nil), obj.makeErr(err) + return (*ApiKey_Project_PublicId_Row)(nil), obj.makeErr(err) } - return api_key, nil + return row, nil } -func (obj *pgxImpl) Get_ApiKey_By_Name_And_ProjectId(ctx context.Context, +func (obj *pgxImpl) Get_ApiKey_Project_PublicId_By_ApiKey_Name_And_ApiKey_ProjectId(ctx context.Context, api_key_name ApiKey_Name_Field, api_key_project_id ApiKey_ProjectId_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { defer mon.Task()(&ctx)(&err) - var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at FROM api_keys WHERE api_keys.name = ? AND api_keys.project_id = ?") + var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at, projects.public_id FROM projects JOIN api_keys ON projects.id = api_keys.project_id WHERE api_keys.name = ? AND api_keys.project_id = ?") var __values []interface{} __values = append(__values, api_key_name.value(), api_key_project_id.value()) @@ -15887,12 +15892,12 @@ func (obj *pgxImpl) Get_ApiKey_By_Name_And_ProjectId(ctx context.Context, var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) obj.logStmt(__stmt, __values...) - api_key = &ApiKey{} - err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&api_key.Id, &api_key.ProjectId, &api_key.Head, &api_key.Name, &api_key.Secret, &api_key.PartnerId, &api_key.UserAgent, &api_key.CreatedAt) + row = &ApiKey_Project_PublicId_Row{} + err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&row.ApiKey.Id, &row.ApiKey.ProjectId, &row.ApiKey.Head, &row.ApiKey.Name, &row.ApiKey.Secret, &row.ApiKey.PartnerId, &row.ApiKey.UserAgent, &row.ApiKey.CreatedAt, &row.Project_PublicId) if err != nil { - return (*ApiKey)(nil), obj.makeErr(err) + return (*ApiKey_Project_PublicId_Row)(nil), obj.makeErr(err) } - return api_key, nil + return row, nil } @@ -23523,12 +23528,12 @@ func (obj *pgxcockroachImpl) All_ProjectMember_By_MemberId(ctx context.Context, } -func (obj *pgxcockroachImpl) Get_ApiKey_By_Id(ctx context.Context, +func (obj *pgxcockroachImpl) Get_ApiKey_Project_PublicId_By_ApiKey_Id(ctx context.Context, api_key_id ApiKey_Id_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { defer mon.Task()(&ctx)(&err) - var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at FROM api_keys WHERE api_keys.id = ?") + var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at, projects.public_id FROM projects JOIN api_keys ON projects.id = api_keys.project_id WHERE api_keys.id = ?") var __values []interface{} __values = append(__values, api_key_id.value()) @@ -23536,21 +23541,21 @@ func (obj *pgxcockroachImpl) Get_ApiKey_By_Id(ctx context.Context, var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) obj.logStmt(__stmt, __values...) - api_key = &ApiKey{} - err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&api_key.Id, &api_key.ProjectId, &api_key.Head, &api_key.Name, &api_key.Secret, &api_key.PartnerId, &api_key.UserAgent, &api_key.CreatedAt) + row = &ApiKey_Project_PublicId_Row{} + err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&row.ApiKey.Id, &row.ApiKey.ProjectId, &row.ApiKey.Head, &row.ApiKey.Name, &row.ApiKey.Secret, &row.ApiKey.PartnerId, &row.ApiKey.UserAgent, &row.ApiKey.CreatedAt, &row.Project_PublicId) if err != nil { - return (*ApiKey)(nil), obj.makeErr(err) + return (*ApiKey_Project_PublicId_Row)(nil), obj.makeErr(err) } - return api_key, nil + return row, nil } -func (obj *pgxcockroachImpl) Get_ApiKey_By_Head(ctx context.Context, +func (obj *pgxcockroachImpl) Get_ApiKey_Project_PublicId_By_ApiKey_Head(ctx context.Context, api_key_head ApiKey_Head_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { defer mon.Task()(&ctx)(&err) - var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at FROM api_keys WHERE api_keys.head = ?") + var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at, projects.public_id FROM projects JOIN api_keys ON projects.id = api_keys.project_id WHERE api_keys.head = ?") var __values []interface{} __values = append(__values, api_key_head.value()) @@ -23558,22 +23563,22 @@ func (obj *pgxcockroachImpl) Get_ApiKey_By_Head(ctx context.Context, var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) obj.logStmt(__stmt, __values...) - api_key = &ApiKey{} - err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&api_key.Id, &api_key.ProjectId, &api_key.Head, &api_key.Name, &api_key.Secret, &api_key.PartnerId, &api_key.UserAgent, &api_key.CreatedAt) + row = &ApiKey_Project_PublicId_Row{} + err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&row.ApiKey.Id, &row.ApiKey.ProjectId, &row.ApiKey.Head, &row.ApiKey.Name, &row.ApiKey.Secret, &row.ApiKey.PartnerId, &row.ApiKey.UserAgent, &row.ApiKey.CreatedAt, &row.Project_PublicId) if err != nil { - return (*ApiKey)(nil), obj.makeErr(err) + return (*ApiKey_Project_PublicId_Row)(nil), obj.makeErr(err) } - return api_key, nil + return row, nil } -func (obj *pgxcockroachImpl) Get_ApiKey_By_Name_And_ProjectId(ctx context.Context, +func (obj *pgxcockroachImpl) Get_ApiKey_Project_PublicId_By_ApiKey_Name_And_ApiKey_ProjectId(ctx context.Context, api_key_name ApiKey_Name_Field, api_key_project_id ApiKey_ProjectId_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { defer mon.Task()(&ctx)(&err) - var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at FROM api_keys WHERE api_keys.name = ? AND api_keys.project_id = ?") + var __embed_stmt = __sqlbundle_Literal("SELECT api_keys.id, api_keys.project_id, api_keys.head, api_keys.name, api_keys.secret, api_keys.partner_id, api_keys.user_agent, api_keys.created_at, projects.public_id FROM projects JOIN api_keys ON projects.id = api_keys.project_id WHERE api_keys.name = ? AND api_keys.project_id = ?") var __values []interface{} __values = append(__values, api_key_name.value(), api_key_project_id.value()) @@ -23581,12 +23586,12 @@ func (obj *pgxcockroachImpl) Get_ApiKey_By_Name_And_ProjectId(ctx context.Contex var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) obj.logStmt(__stmt, __values...) - api_key = &ApiKey{} - err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&api_key.Id, &api_key.ProjectId, &api_key.Head, &api_key.Name, &api_key.Secret, &api_key.PartnerId, &api_key.UserAgent, &api_key.CreatedAt) + row = &ApiKey_Project_PublicId_Row{} + err = obj.queryRowContext(ctx, __stmt, __values...).Scan(&row.ApiKey.Id, &row.ApiKey.ProjectId, &row.ApiKey.Head, &row.ApiKey.Name, &row.ApiKey.Secret, &row.ApiKey.PartnerId, &row.ApiKey.UserAgent, &row.ApiKey.CreatedAt, &row.Project_PublicId) if err != nil { - return (*ApiKey)(nil), obj.makeErr(err) + return (*ApiKey_Project_PublicId_Row)(nil), obj.makeErr(err) } - return api_key, nil + return row, nil } @@ -28314,35 +28319,35 @@ func (rx *Rx) Get_AccountFreezeEvent_By_UserId_And_Event(ctx context.Context, return tx.Get_AccountFreezeEvent_By_UserId_And_Event(ctx, account_freeze_event_user_id, account_freeze_event_event) } -func (rx *Rx) Get_ApiKey_By_Head(ctx context.Context, +func (rx *Rx) Get_ApiKey_Project_PublicId_By_ApiKey_Head(ctx context.Context, api_key_head ApiKey_Head_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { var tx *Tx if tx, err = rx.getTx(ctx); err != nil { return } - return tx.Get_ApiKey_By_Head(ctx, api_key_head) + return tx.Get_ApiKey_Project_PublicId_By_ApiKey_Head(ctx, api_key_head) } -func (rx *Rx) Get_ApiKey_By_Id(ctx context.Context, +func (rx *Rx) Get_ApiKey_Project_PublicId_By_ApiKey_Id(ctx context.Context, api_key_id ApiKey_Id_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { var tx *Tx if tx, err = rx.getTx(ctx); err != nil { return } - return tx.Get_ApiKey_By_Id(ctx, api_key_id) + return tx.Get_ApiKey_Project_PublicId_By_ApiKey_Id(ctx, api_key_id) } -func (rx *Rx) Get_ApiKey_By_Name_And_ProjectId(ctx context.Context, +func (rx *Rx) Get_ApiKey_Project_PublicId_By_ApiKey_Name_And_ApiKey_ProjectId(ctx context.Context, api_key_name ApiKey_Name_Field, api_key_project_id ApiKey_ProjectId_Field) ( - api_key *ApiKey, err error) { + row *ApiKey_Project_PublicId_Row, err error) { var tx *Tx if tx, err = rx.getTx(ctx); err != nil { return } - return tx.Get_ApiKey_By_Name_And_ProjectId(ctx, api_key_name, api_key_project_id) + return tx.Get_ApiKey_Project_PublicId_By_ApiKey_Name_And_ApiKey_ProjectId(ctx, api_key_name, api_key_project_id) } func (rx *Rx) Get_BillingBalance_Balance_By_UserId(ctx context.Context, @@ -29788,18 +29793,18 @@ type Methods interface { account_freeze_event_event AccountFreezeEvent_Event_Field) ( account_freeze_event *AccountFreezeEvent, err error) - Get_ApiKey_By_Head(ctx context.Context, + Get_ApiKey_Project_PublicId_By_ApiKey_Head(ctx context.Context, api_key_head ApiKey_Head_Field) ( - api_key *ApiKey, err error) + row *ApiKey_Project_PublicId_Row, err error) - Get_ApiKey_By_Id(ctx context.Context, + Get_ApiKey_Project_PublicId_By_ApiKey_Id(ctx context.Context, api_key_id ApiKey_Id_Field) ( - api_key *ApiKey, err error) + row *ApiKey_Project_PublicId_Row, err error) - Get_ApiKey_By_Name_And_ProjectId(ctx context.Context, + Get_ApiKey_Project_PublicId_By_ApiKey_Name_And_ApiKey_ProjectId(ctx context.Context, api_key_name ApiKey_Name_Field, api_key_project_id ApiKey_ProjectId_Field) ( - api_key *ApiKey, err error) + row *ApiKey_Project_PublicId_Row, err error) Get_BillingBalance_Balance_By_UserId(ctx context.Context, billing_balance_user_id BillingBalance_UserId_Field) (