forked from BRETT/BRETT
Initial Commit
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { mkdir, unlink, writeFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { isCardBorderEffect } from '../../../shared/utils/cardBorderEffects'
|
||||
import { isCardEffect } from '../../../shared/utils/cardEffects'
|
||||
import { users } from '../../db/schema'
|
||||
|
||||
const AVATAR_MIME_EXT: Record<string, string> = {
|
||||
'image/jpeg': '.jpg',
|
||||
'image/png': '.png',
|
||||
'image/gif': '.gif',
|
||||
'image/webp': '.webp',
|
||||
'image/avif': '.avif',
|
||||
}
|
||||
|
||||
const MAX_AVATAR_SIZE = 5 * 1024 * 1024 // 5 MB
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const user = await requireUser(event)
|
||||
const parts = await readMultipartFormData(event)
|
||||
|
||||
const colorField = parts?.find(p => p.name === 'color')?.data.toString('utf8').trim()
|
||||
const cardEffectField = parts?.find(p => p.name === 'cardEffect')?.data.toString('utf8').trim()
|
||||
const cardEffectColorField = parts?.find(p => p.name === 'cardEffectColor')?.data.toString('utf8').trim()
|
||||
const cardVignetteField = parts?.find(p => p.name === 'cardVignette')?.data.toString('utf8').trim()
|
||||
const cardBorderEffectField = parts?.find(p => p.name === 'cardBorderEffect')?.data.toString('utf8').trim()
|
||||
const cardBorderEffectColorField = parts?.find(p => p.name === 'cardBorderEffectColor')?.data.toString('utf8').trim()
|
||||
const avatarFile = parts?.find(p => p.name === 'avatar')
|
||||
|
||||
let color: string | null | undefined
|
||||
if (colorField !== undefined) {
|
||||
if (colorField === '') {
|
||||
color = null
|
||||
}
|
||||
else if (/^#[0-9a-fA-F]{6}$/.test(colorField)) {
|
||||
color = colorField.toLowerCase()
|
||||
}
|
||||
else {
|
||||
throw createError({ statusCode: 400, statusMessage: 'Ungültige Farbe' })
|
||||
}
|
||||
}
|
||||
|
||||
let cardEffect: string | null | undefined
|
||||
if (cardEffectField !== undefined) {
|
||||
if (cardEffectField === '') {
|
||||
cardEffect = null
|
||||
}
|
||||
else if (isCardEffect(cardEffectField)) {
|
||||
cardEffect = cardEffectField
|
||||
}
|
||||
else {
|
||||
throw createError({ statusCode: 400, statusMessage: 'Ungültiger Effekt' })
|
||||
}
|
||||
}
|
||||
|
||||
let cardBorderEffect: string | null | undefined
|
||||
if (cardBorderEffectField !== undefined) {
|
||||
if (cardBorderEffectField === '') {
|
||||
cardBorderEffect = null
|
||||
}
|
||||
else if (isCardBorderEffect(cardBorderEffectField)) {
|
||||
cardBorderEffect = cardBorderEffectField
|
||||
}
|
||||
else {
|
||||
throw createError({ statusCode: 400, statusMessage: 'Ungültiger Border-Effekt' })
|
||||
}
|
||||
}
|
||||
|
||||
const parseOptionalColor = (field: string | undefined): string | null | undefined => {
|
||||
if (field === undefined) return undefined
|
||||
if (field === '') return null
|
||||
if (/^#[0-9a-fA-F]{6}$/.test(field)) return field.toLowerCase()
|
||||
throw createError({ statusCode: 400, statusMessage: 'Ungültige Effekt-Farbe' })
|
||||
}
|
||||
const cardEffectColor = parseOptionalColor(cardEffectColorField)
|
||||
const cardBorderEffectColor = parseOptionalColor(cardBorderEffectColorField)
|
||||
const cardVignette = cardVignetteField === undefined ? undefined : cardVignetteField === '1'
|
||||
|
||||
let avatarName: string | undefined
|
||||
if (avatarFile?.data?.length && avatarFile.type) {
|
||||
const ext = AVATAR_MIME_EXT[avatarFile.type]
|
||||
if (!ext) {
|
||||
throw createError({ statusCode: 415, statusMessage: 'Nur Bilder sind als Avatar erlaubt' })
|
||||
}
|
||||
if (avatarFile.data.length > MAX_AVATAR_SIZE) {
|
||||
throw createError({ statusCode: 413, statusMessage: 'Avatar ist zu groß (max. 5 MB)' })
|
||||
}
|
||||
avatarName = `${randomUUID()}${ext}`
|
||||
await mkdir(avatarDir(), { recursive: true })
|
||||
await writeFile(join(avatarDir(), avatarName), avatarFile.data)
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
await db.update(users).set({
|
||||
...(color !== undefined && { color }),
|
||||
...(cardEffect !== undefined && { cardEffect }),
|
||||
...(cardEffectColor !== undefined && { cardEffectColor }),
|
||||
...(cardVignette !== undefined && { cardVignette }),
|
||||
...(cardBorderEffect !== undefined && { cardBorderEffect }),
|
||||
...(cardBorderEffectColor !== undefined && { cardBorderEffectColor }),
|
||||
...(avatarName && { avatar: avatarName }),
|
||||
}).where(eq(users.id, user.id))
|
||||
|
||||
if (avatarName && user.avatar) {
|
||||
await unlink(join(avatarDir(), user.avatar)).catch(() => {})
|
||||
}
|
||||
|
||||
const [updated] = await db.select().from(users).where(eq(users.id, user.id)).limit(1)
|
||||
return {
|
||||
user: {
|
||||
id: updated!.id,
|
||||
name: updated!.name,
|
||||
email: updated!.email,
|
||||
color: updated!.color,
|
||||
cardEffect: updated!.cardEffect,
|
||||
cardEffectColor: updated!.cardEffectColor,
|
||||
cardVignette: updated!.cardVignette,
|
||||
cardBorderEffect: updated!.cardBorderEffect,
|
||||
cardBorderEffectColor: updated!.cardBorderEffectColor,
|
||||
avatarUrl: avatarUrl(updated!.avatar),
|
||||
roles: user.roles,
|
||||
},
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user