import { Injectable, BadRequestException, UnauthorizedException, } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { getTempUserId } from '../common/user.util'; import * as bcrypt from 'bcrypt'; @Injectable() export class UsersService { constructor(private prisma: PrismaService) {} async me() { const userId = getTempUserId(); return this.prisma.user.findUnique({ where: { id: userId } }); } async updateProfile(userId: string, data: { name?: string; phone?: string }) { try { const user = await this.prisma.user.update({ where: { id: userId }, data: { ...(data.name !== undefined && { name: data.name }), ...(data.phone !== undefined && { phone: data.phone }), }, select: { id: true, email: true, name: true, phone: true, avatarUrl: true, }, }); return { success: true, message: 'Profile updated successfully', user, }; } catch (error: any) { if (error.code === 'P2002') { throw new BadRequestException('Phone number already in use'); } throw error; } } async getAuthInfo(userId: string) { // Get user with password hash and avatar const user = await this.prisma.user.findUnique({ where: { id: userId }, select: { passwordHash: true, avatarUrl: true, }, }); // Check if user has Google OAuth (avatar from Google or starts with /avatars/) const hasGoogleAuth = user?.avatarUrl?.includes('googleusercontent.com') || user?.avatarUrl?.startsWith('/avatars/') || false; return { hasGoogleAuth, hasPassword: user?.passwordHash !== null, }; } async deleteAccount(userId: string, password: string) { // Get user with password hash const user = await this.prisma.user.findUnique({ where: { id: userId }, select: { passwordHash: true, }, }); if (!user) { throw new BadRequestException('User not found'); } if (!user.passwordHash) { throw new BadRequestException( 'Cannot delete account without password. Please set a password first.', ); } // Verify password const isValid = await bcrypt.compare(password, user.passwordHash); if (!isValid) { throw new UnauthorizedException('Incorrect password'); } // Delete related data first (to avoid foreign key constraint errors) // Delete AuthAccount records await this.prisma.authAccount.deleteMany({ where: { userId: userId }, }); // Delete other related data if any // Add more deleteMany calls here for other tables that reference User // Finally, delete the user await this.prisma.user.delete({ where: { id: userId }, }); return { success: true, message: 'Account deleted successfully', }; } }