diff --git a/migrations/tenant/0037-add-bucket-name-length-trigger.sql b/migrations/tenant/0037-add-bucket-name-length-trigger.sql new file mode 100644 index 00000000..95e1cc08 --- /dev/null +++ b/migrations/tenant/0037-add-bucket-name-length-trigger.sql @@ -0,0 +1,15 @@ +create or replace function storage.enforce_bucket_name_length() +returns trigger as $$ +begin + if length(new.name) > 100 then + raise exception 'bucket name "%" is too long (% characters). Max is 100.', new.name, length(new.name); + end if; + return new; +end; +$$ language plpgsql; + + +drop trigger if exists enforce_bucket_name_length_trigger on storage.buckets; +create trigger enforce_bucket_name_length_trigger +before insert or update of name on storage.buckets +for each row execute function storage.enforce_bucket_name_length(); diff --git a/src/internal/database/migrations/types.ts b/src/internal/database/migrations/types.ts index 224a6f28..c109e5be 100644 --- a/src/internal/database/migrations/types.ts +++ b/src/internal/database/migrations/types.ts @@ -35,4 +35,5 @@ export const DBMigration = { 'optimize-search-function-v1': 34, 'add-insert-trigger-prefixes': 35, 'optimise-existing-functions': 36, + 'add-bucket-name-length-trigger': 37, } diff --git a/src/storage/limits.ts b/src/storage/limits.ts index cff8627d..5f1157c7 100644 --- a/src/storage/limits.ts +++ b/src/storage/limits.ts @@ -58,10 +58,14 @@ export function isValidKey(key: string): boolean { */ export function isValidBucketName(bucketName: string): boolean { // only allow s3 safe characters and characters which require special handling for now + // the slash restriction come from bucket naming rules + // and the rest of the validation rules are based on S3 object key validation. // https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html - // excluding / for bucketName + // https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html return ( - bucketName.length > 0 && /^(\w|!|-|\.|\*|'|\(|\)| |&|\$|@|=|;|:|\+|,|\?)*$/.test(bucketName) + bucketName.length > 0 && + bucketName.length < 101 && + /^(\w|!|-|\.|\*|'|\(|\)| |&|\$|@|=|;|:|\+|,|\?)*$/.test(bucketName) ) } diff --git a/src/test/bucket.test.ts b/src/test/bucket.test.ts index e8111c63..f49feef0 100644 --- a/src/test/bucket.test.ts +++ b/src/test/bucket.test.ts @@ -211,6 +211,21 @@ describe('testing POST bucket', () => { }) expect(response.statusCode).toBe(400) }) + + test('user is not able to create a bucket with a name longer than 100 characters', async () => { + const longBucketName = 'a'.repeat(101) + const response = await app().inject({ + method: 'POST', + url: `/bucket`, + headers: { + authorization: `Bearer ${process.env.AUTHENTICATED_KEY}`, + }, + payload: { + name: longBucketName, + }, + }) + expect(response.statusCode).toBe(400) + }) }) /*