import { auth } from '@/auth'; import { NextResponse } from 'next/server'; import { prisma } from '@/prisma'; import { userEmailSchema, userFirstNameSchema, userNameSchema, userLastNameSchema, disallowedUsernames, } from '@/lib/validation/user'; /** * @swagger * /api/user/me: * get: * description: Retrieve the information of the currently authenticated user. * responses: * 200: * description: User information retrieved successfully. * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * default: true * user: * $ref: '#/components/schemas/User' * 401: * description: User is not authenticated. * content: * application/json: * schema: * $ref: '#/components/schemas/ErrorResponse' * example: * success: false * message: 'Not authenticated' * 404: * description: User not found. * content: * application/json: * schema: * $ref: '#/components/schemas/ErrorResponse' * example: * success: false * message: 'User not found' */ export const GET = auth(async function GET(req) { if (!req.auth) return NextResponse.json( { success: false, message: 'Not authenticated' }, { status: 401 }, ); if (!req.auth.user || !req.auth.user.id) return NextResponse.json( { success: false, message: 'User not found' }, { status: 404 }, ); const dbUser = await prisma.user.findUnique({ where: { id: req.auth.user.id, }, }); if (!dbUser) return NextResponse.json( { success: false, message: 'User not found' }, { status: 404 }, ); return NextResponse.json( { success: true, user: { ...dbUser, password_hash: undefined, // Exclude sensitive information email_verified: undefined, // Exclude sensitive information }, }, { status: 200 }, ); }); /** * @swagger * /api/user/me: * patch: * description: Update the information of the currently authenticated user. * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * name: * type: string * description: Username of the user. * first_name: * type: string * description: First name of the user. * last_name: * type: string * description: Last name of the user. * email: * type: string * description: Email address of the user. * image: * type: string * description: URL of the user's profile image. * timezone: * type: string * description: Timezone of the user. * responses: * 200: * description: User information updated successfully. * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * default: true * user: * $ref: '#/components/schemas/User' * 401: * description: User is not authenticated. * content: * application/json: * schema: * $ref: '#/components/schemas/ErrorResponse' * example: * success: false * message: 'Not authenticated' * 404: * description: User not found. * content: * application/json: * schema: * $ref: '#/components/schemas/ErrorResponse' * example: * success: false * message: 'User not found' * 400: * description: Bad request due to invalid input data. * content: * application/json: * schema: * $ref: '#/components/schemas/ErrorResponse' * example: * success: false * message: 'Invalid input data' */ export const PATCH = auth(async function PATCH(req) { if (!req.auth) return NextResponse.json( { success: false, message: 'Not authenticated' }, { status: 401 }, ); if (!req.auth.user) return NextResponse.json( { success: false, message: 'User not found' }, { status: 404 }, ); const body = await req.json(); const { name, first_name, last_name, email, image, timezone } = body; if (!name && !first_name && !last_name && !email && !image && !timezone) return NextResponse.json( { success: false, message: 'No fields to update' }, { status: 400 }, ); const updateData: Record = {}; if (name) { const nameValidation = userNameSchema.safeParse(name); if (!nameValidation.success) { return NextResponse.json( { success: false, message: nameValidation.error.errors[0].message }, { status: 400 }, ); } // Check if the name already exists for another user const existingUser = await prisma.user.findUnique({ where: { name }, }); if ( (existingUser && existingUser.id !== req.auth.user.id) || disallowedUsernames.includes(name.toLowerCase()) ) { return NextResponse.json( { success: false, message: 'Username in use by another account' }, { status: 400 }, ); } updateData.name = name; } if (first_name) { const firstNameValidation = userFirstNameSchema.safeParse(first_name); if (!firstNameValidation.success) { return NextResponse.json( { success: false, message: firstNameValidation.error.errors[0].message, }, { status: 400 }, ); } updateData.first_name = first_name; } if (last_name) { const lastNameValidation = userLastNameSchema.safeParse(last_name); if (!lastNameValidation.success) { return NextResponse.json( { success: false, message: lastNameValidation.error.errors[0].message }, { status: 400 }, ); } updateData.last_name = last_name; } if (email) { const emailValidation = userEmailSchema.safeParse(email); if (!emailValidation.success) { return NextResponse.json( { success: false, message: emailValidation.error.errors[0].message }, { status: 400 }, ); } // Check if the email already exists for another user const existingUser = await prisma.user.findUnique({ where: { email }, }); if (existingUser && existingUser.id !== req.auth.user.id) { return NextResponse.json( { success: false, message: 'Email in use by another account' }, { status: 400 }, ); } updateData.email = email; } if (image) { updateData.image = image; } if (timezone) { updateData.timezone = timezone; } const updatedUser = await prisma.user.update({ where: { id: req.auth.user.id, }, data: updateData, }); if (!updatedUser) return NextResponse.json( { success: false, message: 'User not found' }, { status: 404 }, ); return NextResponse.json( { success: true, user: { ...updatedUser, password_hash: undefined, // Exclude sensitive information email_verified: undefined, // Exclude sensitive information }, }, { status: 200 }, ); });