satellite/accounting/tally: handle well bucket names with escape char

Some of tally queries are not passing bucket name as byte but as string.
If bucket contains some special characters encoding to bytea can fail.
This change makes sure all parts of tally passes bucket name correctly.

Change-Id: I7330d546b44d86a2e4614c814580e9e5262370ed
This commit is contained in:
Michal Niewrzal 2023-06-20 10:53:42 +02:00
parent 28b2384970
commit ac1ff0e7e2
6 changed files with 44 additions and 3 deletions

View File

@ -289,6 +289,12 @@ func TestBatchBuckets(t *testing.T) {
require.False(t, more) require.False(t, more)
} }
} }
// check if invalid bucket name 'a\' won't throw an error
_, err := db.Buckets().IterateBucketLocations(ctx, uuid.UUID{}, "a\\", 1, func(bucketLocations []metabase.BucketLocation) (err error) {
return nil
})
require.NoError(t, err)
}) })
} }

View File

@ -463,7 +463,7 @@ func (db *DB) CollectBucketTallies(ctx context.Context, opts CollectBucketTallie
(expires_at IS NULL OR expires_at > $5) (expires_at IS NULL OR expires_at > $5)
GROUP BY (project_id, bucket_name) GROUP BY (project_id, bucket_name)
ORDER BY (project_id, bucket_name) ASC ORDER BY (project_id, bucket_name) ASC
`, opts.From.ProjectID, opts.From.BucketName, opts.To.ProjectID, opts.To.BucketName, opts.Now))(func(rows tagsql.Rows) error { `, opts.From.ProjectID, []byte(opts.From.BucketName), opts.To.ProjectID, []byte(opts.To.BucketName), opts.Now))(func(rows tagsql.Rows) error {
for rows.Next() { for rows.Next() {
var bucketTally BucketTally var bucketTally BucketTally

View File

@ -819,6 +819,25 @@ func TestCollectBucketTallies(t *testing.T) {
metabasetest.Verify{}.Check(ctx, t, db) metabasetest.Verify{}.Check(ctx, t, db)
}) })
t.Run("invalid bucket name", func(t *testing.T) {
defer metabasetest.DeleteAll{}.Check(ctx, t, db)
metabasetest.CollectBucketTallies{
Opts: metabase.CollectBucketTallies{
From: metabase.BucketLocation{
ProjectID: testrand.UUID(),
BucketName: "a\\",
},
To: metabase.BucketLocation{
ProjectID: testrand.UUID(),
BucketName: "b\\",
},
},
Result: nil,
}.Check(ctx, t, db)
metabasetest.Verify{}.Check(ctx, t, db)
})
t.Run("pending and committed", func(t *testing.T) { t.Run("pending and committed", func(t *testing.T) {
defer metabasetest.DeleteAll{}.Check(ctx, t, db) defer metabasetest.DeleteAll{}.Check(ctx, t, db)

View File

@ -339,7 +339,7 @@ func (db *bucketsDB) IterateBucketLocations(ctx context.Context, projectID uuid.
WHERE (project_id, name) > ($1, $2) WHERE (project_id, name) > ($1, $2)
GROUP BY (project_id, name) GROUP BY (project_id, name)
ORDER BY (project_id, name) ASC LIMIT $3 ORDER BY (project_id, name) ASC LIMIT $3
`, projectID, bucketName, moreLimit) `, projectID, []byte(bucketName), moreLimit)
if err != nil { if err != nil {
return false, buckets.ErrBucket.New("BatchBuckets query error: %s", err) return false, buckets.ErrBucket.New("BatchBuckets query error: %s", err)
} }

View File

@ -160,7 +160,7 @@ func (db *ProjectAccounting) GetNonEmptyTallyBucketsInRange(ctx context.Context,
ORDER BY interval_start DESC ORDER BY interval_start DESC
LIMIT 1 LIMIT 1
) )
`, from.ProjectID, from.BucketName, to.ProjectID, to.BucketName), `, from.ProjectID, []byte(from.BucketName), to.ProjectID, []byte(to.BucketName)),
)(func(r tagsql.Rows) error { )(func(r tagsql.Rows) error {
for r.Next() { for r.Next() {
loc := metabase.BucketLocation{} loc := metabase.BucketLocation{}

View File

@ -15,11 +15,13 @@ import (
"storj.io/common/testrand" "storj.io/common/testrand"
"storj.io/common/uuid" "storj.io/common/uuid"
"storj.io/storj/private/testplanet" "storj.io/storj/private/testplanet"
"storj.io/storj/satellite"
"storj.io/storj/satellite/accounting" "storj.io/storj/satellite/accounting"
"storj.io/storj/satellite/buckets" "storj.io/storj/satellite/buckets"
"storj.io/storj/satellite/console" "storj.io/storj/satellite/console"
"storj.io/storj/satellite/metabase" "storj.io/storj/satellite/metabase"
"storj.io/storj/satellite/orders" "storj.io/storj/satellite/orders"
"storj.io/storj/satellite/satellitedb/satellitedbtest"
) )
func Test_DailyUsage(t *testing.T) { func Test_DailyUsage(t *testing.T) {
@ -498,3 +500,17 @@ func TestProjectUsageGap(t *testing.T) {
require.EqualValues(t, expectedStorage, usage.Storage) require.EqualValues(t, expectedStorage, usage.Storage)
}) })
} }
func TestProjectaccounting_GetNonEmptyTallyBucketsInRange(t *testing.T) {
// test if invalid bucket name will be handled correctly
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
_, err := db.ProjectAccounting().GetNonEmptyTallyBucketsInRange(ctx, metabase.BucketLocation{
ProjectID: testrand.UUID(),
BucketName: "a\\",
}, metabase.BucketLocation{
ProjectID: testrand.UUID(),
BucketName: "b\\",
})
require.NoError(t, err)
})
}