38 lines
1.9 KiB
TypeScript
38 lines
1.9 KiB
TypeScript
import { z } from 'zod'
|
|
import { requireStageTwoSafeText, requireStageTwoUser, stageTwoApiError, stageTwoDatabase } from '~/server/utils/stage-two-supabase'
|
|
import { visibleProfile, type ProfileRecord } from '~/server/utils/profile'
|
|
|
|
const ProfileUpdateSchema = z.object({
|
|
displayName: z.string().trim().min(1).max(80).optional(),
|
|
description: z.string().trim().max(500).optional(),
|
|
avatarPath: z.string().nullable().optional(),
|
|
}).strict().refine(value => Object.keys(value).length > 0, 'At least one profile field is required.')
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
try {
|
|
const user = await requireStageTwoUser(event)
|
|
const update = ProfileUpdateSchema.parse(await readBody(event))
|
|
const expectedAvatarPath = `${user.id}/avatar`
|
|
if (update.avatarPath !== undefined && update.avatarPath !== null && update.avatarPath !== expectedAvatarPath) {
|
|
throw createError({ statusCode: 400, statusMessage: 'Invalid profile picture path.' })
|
|
}
|
|
if (update.displayName !== undefined) requireStageTwoSafeText(update.displayName)
|
|
if (update.description !== undefined) requireStageTwoSafeText(update.description)
|
|
|
|
const changes: Record<string, unknown> = { updated_at: new Date().toISOString() }
|
|
if (update.displayName !== undefined) changes.display_name = update.displayName
|
|
if (update.description !== undefined) changes.description = update.description
|
|
if (update.avatarPath !== undefined) changes.avatar_path = update.avatarPath
|
|
|
|
const profiles = await stageTwoDatabase<ProfileRecord[]>(`profiles?id=eq.${user.id}`, {
|
|
method: 'PATCH',
|
|
body: JSON.stringify(changes),
|
|
prefer: 'return=representation',
|
|
})
|
|
if (!profiles[0]) throw createError({ statusCode: 404, statusMessage: 'Profile not found.' })
|
|
return { profile: visibleProfile(profiles[0], useRuntimeConfig().supabaseUrl) }
|
|
} catch (error) {
|
|
stageTwoApiError(error)
|
|
}
|
|
})
|