diff --git a/src/http/routes/object/createObject.ts b/src/http/routes/object/createObject.ts index 7572714d..529dd571 100644 --- a/src/http/routes/object/createObject.ts +++ b/src/http/routes/object/createObject.ts @@ -13,6 +13,9 @@ const createObjectParamsSchema = { const successResponseSchema = { type: 'object', properties: { + Id: { + type: 'string', + }, Key: { type: 'string', examples: ['avatars/folder/cat.png'], @@ -61,7 +64,7 @@ export default async function routes(fastify: FastifyInstance) { const isUpsert = request.headers['x-upsert'] === 'true' const owner = request.owner as string - const { objectMetadata, path } = await request.storage + const { objectMetadata, path, id } = await request.storage .from(bucketName) .uploadNewObject(request, { objectName, @@ -70,6 +73,7 @@ export default async function routes(fastify: FastifyInstance) { }) return response.status(objectMetadata?.httpStatusCode ?? 200).send({ + Id: id, Key: path, }) } diff --git a/src/http/routes/object/updateObject.ts b/src/http/routes/object/updateObject.ts index 8995707c..23d3b96b 100644 --- a/src/http/routes/object/updateObject.ts +++ b/src/http/routes/object/updateObject.ts @@ -13,6 +13,9 @@ const updateObjectParamsSchema = { const successResponseSchema = { type: 'object', properties: { + Id: { + type: 'string', + }, Key: { type: 'string', examples: ['avatars/folder/cat.png'] }, }, required: ['Key'], @@ -56,7 +59,7 @@ export default async function routes(fastify: FastifyInstance) { const objectName = request.params['*'] const owner = request.owner as string - const { objectMetadata, path } = await request.storage + const { objectMetadata, path, id } = await request.storage .from(bucketName) .uploadOverridingObject(request, { owner, @@ -64,6 +67,7 @@ export default async function routes(fastify: FastifyInstance) { }) return response.status(objectMetadata?.httpStatusCode ?? 200).send({ + Id: id, Key: path, }) } diff --git a/src/storage/database/adapter.ts b/src/storage/database/adapter.ts index b304d8ce..ade8e549 100644 --- a/src/storage/database/adapter.ts +++ b/src/storage/database/adapter.ts @@ -87,7 +87,7 @@ export interface Database { upsertObject( data: Pick - ): Promise> + ): Promise updateObject( bucketId: string, name: string, diff --git a/src/storage/database/knex.ts b/src/storage/database/knex.ts index 24893cb8..7bf5e6e5 100644 --- a/src/storage/database/knex.ts +++ b/src/storage/database/knex.ts @@ -235,15 +235,20 @@ export class StorageKnexDB implements Database { metadata: data.metadata, version: data.version, } - await this.runQuery('UpsertObject', (knex) => { - return knex.from('objects').insert(objectData).onConflict(['name', 'bucket_id']).merge({ - metadata: data.metadata, - version: data.version, - owner: data.owner, - }) + const [object] = await this.runQuery('UpsertObject', (knex) => { + return knex + .from('objects') + .insert(objectData) + .onConflict(['name', 'bucket_id']) + .merge({ + metadata: data.metadata, + version: data.version, + owner: data.owner, + }) + .returning('*') }) - return objectData + return object } async updateObject( diff --git a/src/storage/object.ts b/src/storage/object.ts index ffd6548c..ea400681 100644 --- a/src/storage/object.ts +++ b/src/storage/object.ts @@ -64,14 +64,14 @@ export class ObjectStorage { const uploader = new Uploader(this.backend, this.db) - const { metadata } = await uploader.upload(request, { + const { metadata, obj } = await uploader.upload(request, { ...options, bucketId: this.bucketId, fileSizeLimit: bucket.file_size_limit, allowedMimeTypes: bucket.allowed_mime_types, }) - return { objectMetadata: metadata, path } + return { objectMetadata: metadata, path, id: obj.id } } public async uploadOverridingObject(request: FastifyRequest, options: UploadObjectOptions) { @@ -93,7 +93,7 @@ export class ObjectStorage { const uploader = new Uploader(this.backend, this.db) - const { metadata } = await uploader.upload(request, { + const { metadata, obj } = await uploader.upload(request, { ...options, bucketId: this.bucketId, fileSizeLimit: bucket.file_size_limit, @@ -101,7 +101,7 @@ export class ObjectStorage { isUpsert: true, }) - return { objectMetadata: metadata, path } + return { objectMetadata: metadata, path, id: obj.id } } /** diff --git a/src/test/object.test.ts b/src/test/object.test.ts index 6c3470bc..4b54c480 100644 --- a/src/test/object.test.ts +++ b/src/test/object.test.ts @@ -206,7 +206,12 @@ describe('testing POST object via multipart upload', () => { }) expect(response.statusCode).toBe(200) expect(S3Backend.prototype.uploadObject).toBeCalled() - expect(response.body).toBe(`{"Key":"bucket2/authenticated/casestudy1.png"}`) + expect(await response.json()).toEqual( + expect.objectContaining({ + Id: expect.any(String), + Key: 'bucket2/authenticated/casestudy1.png', + }) + ) }) test('check if RLS policies are respected: anon user is not able to upload authenticated resource', async () => { @@ -500,7 +505,12 @@ describe('testing POST object via binary upload', () => { }) expect(response.statusCode).toBe(200) expect(S3Backend.prototype.uploadObject).toBeCalled() - expect(response.body).toBe(`{"Key":"bucket2/authenticated/binary-casestudy1.png"}`) + expect(await response.json()).toEqual( + expect.objectContaining({ + Id: expect.any(String), + Key: 'bucket2/authenticated/binary-casestudy1.png', + }) + ) }) test('check if RLS policies are respected: anon user is not able to upload authenticated resource', async () => { @@ -731,7 +741,12 @@ describe('testing PUT object', () => { }) expect(response.statusCode).toBe(200) expect(S3Backend.prototype.uploadObject).toBeCalled() - expect(response.body).toBe(`{"Key":"bucket2/authenticated/cat.jpg"}`) + expect(await response.json()).toEqual( + expect.objectContaining({ + Id: expect.any(String), + Key: 'bucket2/authenticated/cat.jpg', + }) + ) }) test('check if RLS policies are respected: anon user is not able to update authenticated resource', async () => { @@ -826,7 +841,12 @@ describe('testing PUT object via binary upload', () => { }) expect(response.statusCode).toBe(200) expect(S3Backend.prototype.uploadObject).toBeCalled() - expect(response.body).toBe(`{"Key":"bucket2/authenticated/cat.jpg"}`) + expect(await response.json()).toEqual( + expect.objectContaining({ + Id: expect.any(String), + Key: 'bucket2/authenticated/cat.jpg', + }) + ) }) test('check if RLS policies are respected: anon user is not able to update authenticated resource', async () => {