enable aws s3 support for file upload

main
TZGyn 12 months ago
parent 7eae6141c3
commit d350e00b79
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

@ -1,10 +1,21 @@
import { db } from '$lib/db' import { db } from '$lib/db'
import { shortener } from '$lib/db/schema' import { file, shortener, user } from '$lib/db/schema'
import type { RequestHandler } from './$types' import type { RequestHandler } from './$types'
import util from 'util' import util from 'util'
import { generateId } from 'lucia' import { generateId } from 'lucia'
import { nanoid } from 'nanoid' import { nanoid } from 'nanoid'
import { and, eq, isNull } from 'drizzle-orm' import { and, eq, isNull } from 'drizzle-orm'
import { env } from '$env/dynamic/private'
import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3'
const client = new S3Client({
region: 'auto',
endpoint: `https://fly.storage.tigris.dev`,
credentials: {
accessKeyId: env.PRIVATE_AWS_ACCESS_KEY_ID,
secretAccessKey: env.PRIVATE_AWS_SECRET_ACCESS_KEY,
},
})
type S3WebhookStructure = { type S3WebhookStructure = {
Records: { Records: {
@ -51,6 +62,18 @@ type S3WebhookStructure = {
} }
export const POST: RequestHandler = async (event) => { export const POST: RequestHandler = async (event) => {
const authHeader = event.request.headers.get('Authorization')
console.log('auth header:', authHeader)
if (
!authHeader ||
(env.PRIVATE_AWS_WEBHOOK_TOKEN &&
authHeader !== `Bearer ${env.PRIVATE_AWS_WEBHOOK_TOKEN}`)
) {
console.log('Unauthorized')
return new Response('', { status: 401 })
}
const body = (await event.request.json()) as S3WebhookStructure const body = (await event.request.json()) as S3WebhookStructure
const eventHandlers = body.Records.map(async (event) => { const eventHandlers = body.Records.map(async (event) => {
@ -58,9 +81,16 @@ export const POST: RequestHandler = async (event) => {
util.inspect(event, false, null, true /* enable colors */), util.inspect(event, false, null, true /* enable colors */),
) )
if (event.eventName === 'ObjectCreated:Put') {
const key = event.s3.object.key const key = event.s3.object.key
const [userId, projectId, filename] = key.split('/') const [userId, projectId, filename] = key.split('/')
const objectOwner = await db.query.user.findFirst({
where: (user, { eq }) => eq(user.id, userId),
})
if (!objectOwner) return
if (event.eventName === 's3:ObjectCreated:Put') {
const existingShortener = await db.query.shortener.findFirst({ const existingShortener = await db.query.shortener.findFirst({
where: (shortener, { eq, and, isNull }) => where: (shortener, { eq, and, isNull }) =>
and( and(
@ -73,10 +103,7 @@ export const POST: RequestHandler = async (event) => {
), ),
}) })
if (existingShortener) { if (!existingShortener) {
return
}
await db.insert(shortener).values({ await db.insert(shortener).values({
id: generateId(8), id: generateId(8),
link: '', link: '',
@ -86,21 +113,60 @@ export const POST: RequestHandler = async (event) => {
is_file_upload: true, is_file_upload: true,
file_path: key, file_path: key,
}) })
} else if (event.eventName === 's3:ObjectRemoved:Delete') { }
const key = event.s3.object.key
const [userId, projectId, filename] = key.split('/') const object = await client.send(
await db new GetObjectCommand({
.delete(shortener) Bucket: env.PRIVATE_AWS_BUCKET_NAME,
.where( Key: key,
and( }),
eq(shortener.userId, userId),
projectId !== 'personal'
? eq(shortener.projectId, projectId)
: isNull(shortener.projectId),
eq(shortener.is_file_upload, true),
eq(shortener.file_path, key),
),
) )
const existingFile = await db.query.file.findFirst({
where: (file, { eq }) => eq(file.key, key),
})
if (existingFile) {
await db
.update(file)
.set({
size: object.ContentLength,
eTag: object.ETag,
updatedAt: Date.now(),
})
.where(eq(file.id, existingFile.id))
await db
.update(user)
.set({
fileStorageUsageInByte:
objectOwner.fileStorageUsageInByte +
(object.ContentLength! - existingFile.size),
})
.where(eq(user.id, userId))
} else {
await db.insert(file).values({
id: generateId(8),
userId: userId,
projectId: projectId !== 'personal' ? projectId : undefined,
key: key,
name: filename,
size: object.ContentLength!,
eTag: object.ETag!,
createdAt: Date.now(),
updatedAt: Date.now(),
})
await db
.update(user)
.set({
fileStorageUsageInByte:
objectOwner.fileStorageUsageInByte +
(object.ContentLength || 0),
})
.where(eq(user.id, userId))
}
} else if (event.eventName === 's3:ObjectRemoved:Delete') {
} }
}) })

Loading…
Cancel
Save