diff --git a/api/resolvers/upload.js b/api/resolvers/upload.js index ed19b8a0..8d5835b4 100644 --- a/api/resolvers/upload.js +++ b/api/resolvers/upload.js @@ -1,6 +1,35 @@ import { GraphQLError } from 'graphql' import { IMAGE_PIXELS_MAX, UPLOAD_SIZE_MAX, UPLOAD_TYPES_ALLOW } from '../../lib/constants' import { createPresignedPost } from '../s3' +import { datePivot } from '../../lib/time' +import serialize from './serial' + +// factor for bytes to megabyte +const MB = 1024 * 1024 +// factor for msats to sats +const SATS = 1000 + +async function uploadCosts (models, userId, photoId, size) { + let { _sum: { size: sumSize } } = await models.upload.aggregate({ + _sum: { size: true }, + where: { userId, createdAt: { gt: datePivot(new Date(), { days: -1 }) }, id: photoId ? { not: photoId } : undefined } + }) + // assume the image was already uploaded in the calculation + sumSize += size + if (sumSize <= 5 * MB) { + return 0 * SATS + } + if (sumSize <= 10 * MB) { + return 10 * SATS + } + if (sumSize <= 25 * MB) { + return 100 * SATS + } + if (sumSize <= 100 * MB) { + return 1000 * SATS + } + return -1 +} export default { Mutation: { @@ -21,6 +50,14 @@ export default { throw new GraphQLError(`image must be less than ${IMAGE_PIXELS_MAX} pixels`, { extensions: { code: 'BAD_INPUT' } }) } + const { photoId } = await models.user.findUnique({ where: { id: me.id } }) + + const costs = avatar ? 0 : await uploadCosts(models, me.id, photoId, size) + if (costs < 0) { + throw new GraphQLError('image quota of 100 MB exceeded', { extensions: { code: 'BAD_INPUT' } }) + } + const feeTx = models.user.update({ data: { msats: { decrement: costs } }, where: { id: me.id } }) + const data = { type, size, @@ -30,16 +67,13 @@ export default { } let uploadId - if (avatar) { - const { photoId } = await models.user.findUnique({ where: { id: me.id } }) - if (photoId) uploadId = photoId - } + if (avatar && photoId) uploadId = photoId if (uploadId) { // update upload record - await models.upload.update({ data, where: { id: uploadId } }) + await serialize(models, models.upload.update({ data, where: { id: uploadId } }), feeTx) } else { // create upload record - const upload = await models.upload.create({ data }) + const [upload] = await serialize(models, models.upload.create({ data }), feeTx) uploadId = upload.id }