From 51bc4b82d0d025c6c9aa28b0d0fe6db93f10bced Mon Sep 17 00:00:00 2001 From: ekzyis Date: Fri, 20 Oct 2023 00:41:32 +0200 Subject: [PATCH] Also delete objects in S3 --- api/resolvers/item.js | 11 +++++++---- api/resolvers/upload.js | 29 +++-------------------------- api/s3/index.js | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 30 deletions(-) create mode 100644 api/s3/index.js diff --git a/api/resolvers/item.js b/api/resolvers/item.js index a07d2a05..9e20f5e6 100644 --- a/api/resolvers/item.js +++ b/api/resolvers/item.js @@ -19,6 +19,7 @@ import { sendUserNotification } from '../webPush' import { defaultCommentSort, isJob, deleteItemByAuthor, getDeleteCommand, hasDeleteCommand } from '../../lib/item' import { notifyItemParents, notifyUserSubscribers, notifyZapped } from '../../lib/push-notifications' import { datePivot } from '../../lib/time' +import { deleteObject } from '../s3' export async function commentFilterClause (me, models) { let clause = ` AND ("Item"."weightedVotes" - "Item"."weightedDownVotes" > -${ITEM_FILTER_THRESHOLD}` @@ -809,13 +810,15 @@ export default { throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } }) } - id = Number(id) - - const img = await models.upload.findUnique({ where: { id } }) + const img = await models.upload.findUnique({ where: { id: Number(id) } }) if (img.userId !== me.id) { throw new GraphQLError('not your image', { extensions: { code: 'FORBIDDEN' } }) } - await models.upload.delete({ where: { id } }) + if (img.itemId) { + throw new GraphQLError('image already included in an item', { extensions: { code: 'BAD_INPUT' } }) + } + await models.upload.delete({ where: { id: Number(id) } }) + await deleteObject(id) return id } diff --git a/api/resolvers/upload.js b/api/resolvers/upload.js index b8bd1e93..34e86c17 100644 --- a/api/resolvers/upload.js +++ b/api/resolvers/upload.js @@ -1,12 +1,6 @@ import { GraphQLError } from 'graphql' -import AWS from 'aws-sdk' import { IMAGE_PIXELS_MAX, UPLOAD_SIZE_MAX, UPLOAD_TYPES_ALLOW } from '../../lib/constants' - -const bucketRegion = 'us-east-1' - -AWS.config.update({ - region: bucketRegion -}) +import { createPresignedPost } from '../s3' export default { Mutation: { @@ -38,25 +32,8 @@ export default { } }) - // get presigned POST ur - const s3 = new AWS.S3({ apiVersion: '2006-03-01' }) - const res = await new Promise((resolve, reject) => { - s3.createPresignedPost({ - Bucket: process.env.NEXT_PUBLIC_AWS_UPLOAD_BUCKET, - Fields: { - key: String(upload.id) - }, - Expires: 300, - Conditions: [ - { 'Content-Type': type }, - { 'Cache-Control': 'max-age=31536000' }, - { acl: 'public-read' }, - ['content-length-range', size, size] - ] - }, (err, preSigned) => { if (err) { reject(err) } else { resolve(preSigned) } }) - }) - - return res + // get presigned POST url + return createPresignedPost({ key: String(upload.id), type, size }) } } } diff --git a/api/s3/index.js b/api/s3/index.js new file mode 100644 index 00000000..bcaf2331 --- /dev/null +++ b/api/s3/index.js @@ -0,0 +1,35 @@ +import AWS from 'aws-sdk' + +const bucketRegion = 'us-east-1' +const Bucket = process.env.NEXT_PUBLIC_AWS_UPLOAD_BUCKET + +AWS.config.update({ + region: bucketRegion +}) + +export function createPresignedPost ({ key, type, size }) { + const s3 = new AWS.S3({ apiVersion: '2006-03-01' }) + return new Promise((resolve, reject) => { + s3.createPresignedPost({ + Bucket, + Fields: { key }, + Expires: 300, + Conditions: [ + { 'Content-Type': type }, + { 'Cache-Control': 'max-age=31536000' }, + { acl: 'public-read' }, + ['content-length-range', size, size] + ] + }, (err, preSigned) => { err ? reject(err) : resolve(preSigned) }) + }) +} + +export function deleteObject (key) { + const s3 = new AWS.S3({ apiVersion: '2006-03-01' }) + return new Promise((resolve, reject) => { + s3.deleteObject({ + Bucket, + Key: key + }, (err, data) => { err ? reject(err) : resolve(key) }) + }) +}