import { FastifyInstance } from 'fastify' import { FromSchema } from 'json-schema-to-ts' import { AuthenticatedRequest, Obj } from '../../types/types' import { isValidKey, transformPostgrestError } from '../../utils' import { getConfig } from '../../utils/config' import { createDefaultSchema, createResponse } from '../../utils/generic-routes' import { S3Backend } from '../../backend/s3' import { FileBackend } from '../../backend/file' import { GenericStorageBackend } from '../../backend/generic' const { region, globalS3Bucket, globalS3Endpoint, storageBackendType } = getConfig() let storageBackend: GenericStorageBackend if (storageBackendType === 'file') { storageBackend = new FileBackend() } else { storageBackend = new S3Backend(region, globalS3Endpoint) } const deleteObjectParamsSchema = { type: 'object', properties: { bucketName: { type: 'string', example: 'avatars' }, '*': { type: 'string', example: 'folder/cat.png' }, }, required: ['bucketName', '*'], } as const const successResponseSchema = { type: 'object', properties: { message: { type: 'string', example: 'Successfully deleted' }, }, } interface deleteObjectRequestInterface extends AuthenticatedRequest { Params: FromSchema<typeof deleteObjectParamsSchema> } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export default async function routes(fastify: FastifyInstance) { const summary = 'Delete an object' const schema = createDefaultSchema(successResponseSchema, { params: deleteObjectParamsSchema, summary, tags: ['object'], }) fastify.delete<deleteObjectRequestInterface>( '/:bucketName/*', { schema, }, async (request, response) => { const { bucketName } = request.params const objectName = request.params['*'] if (!isValidKey(objectName) || !isValidKey(bucketName)) { return response .status(400) .send(createResponse('The key contains invalid characters', '400', 'Invalid key')) } const objectResponse = await request.postgrest .from<Obj>('objects') .delete() .match({ name: objectName, bucket_id: bucketName, }) .single() if (objectResponse.error) { const { error, status } = objectResponse request.log.error({ error }, 'error object') return response.status(400).send(transformPostgrestError(error, status)) } const { data: results } = objectResponse request.log.info({ results }, 'results') // if successfully deleted, delete from s3 too const s3Key = `${request.tenantId}/${bucketName}/${objectName}` await storageBackend.deleteObject(globalS3Bucket, s3Key) return response.status(200).send(createResponse('Successfully deleted')) } ) }