import { FastifyInstance } from "fastify"; import { JwtPayload, User } from "@library/shared-types"; import { prisma } from "../lib/prisma"; export class AuthService { private prisma = prisma; constructor(private readonly app: FastifyInstance) {} /** * Generate JWT token for user. */ async generateToken(user: User): Promise { const payload: JwtPayload = { sub: user.id, email: user.email, username: user.username, isAdmin: user.isAdmin, }; return this.app.jwt.sign(payload, { expiresIn: "7d", }); } /** * Verify JWT token. */ async verifyToken(token: string): Promise { return this.app.jwt.verify(token) as JwtPayload; } /** * Get user by ID from database. */ async getUserById(id: string): Promise { const dbUser = await this.prisma.user.findUnique({ where: { id }, }); if (!dbUser) { return null; } return { id: dbUser.id, discordId: dbUser.discordId, username: dbUser.username, email: dbUser.email, avatarUrl: dbUser.avatar || undefined, isAdmin: dbUser.isAdmin, isBanned: dbUser.isBanned, inDiscord: dbUser.inDiscord, isVip: dbUser.isVip, isMod: dbUser.isMod, isStaff: dbUser.isStaff, }; } /** * Create or update user from Discord OAuth data. */ async createOrUpdateUserFromDiscord(discordData: DiscordUser, inDiscord: boolean, isVip: boolean, isMod: boolean, isStaff: boolean): Promise { const avatarUrl = discordData.avatar ? `https://cdn.discordapp.com/avatars/${discordData.id}/${discordData.avatar}.png` : undefined; // Upsert user in database const dbUser = await this.prisma.user.upsert({ where: { discordId: discordData.id, }, create: { discordId: discordData.id, username: discordData.username, email: discordData.email, avatar: avatarUrl, isAdmin: discordData.id === process.env.ADMIN_DISCORD_ID, inDiscord, isVip, isMod, isStaff, }, update: { username: discordData.username, email: discordData.email, avatar: avatarUrl, inDiscord, isVip, isMod, isStaff, }, }); return { id: dbUser.id, discordId: dbUser.discordId, username: dbUser.username, email: dbUser.email, avatarUrl: dbUser.avatar || undefined, isAdmin: dbUser.isAdmin, isBanned: dbUser.isBanned, inDiscord: dbUser.inDiscord, isVip: dbUser.isVip, isMod: dbUser.isMod, isStaff: dbUser.isStaff, }; } } interface DiscordUser { id: string; username: string; email: string; avatar?: string; }