import prisma from '../utils/db'; import bcrypt from 'bcryptjs'; import { createAccessToken, createRefreshToken, verifyToken } from '../utils/jwt'; import { catatAudit } from '../utils/audit'; import { APIError } from '../utils/errors'; export class AuthService { static async login(params: { username: string; passwordSecret: string; ip: string; userAgent: string; }) { const { username, passwordSecret, ip, userAgent } = params; // Search for user const user = await prisma.user.findFirst({ where: { username, aktif: 1, }, }); if (!user) { // Log failed audit await catatAudit({ aksi: 'login_gagal', entitas: 'user', ipAddress: ip, userAgent: userAgent, dataBaru: { username }, }); throw new APIError('Username atau password salah', 401); } const isMatch = await bcrypt.compare(passwordSecret, user.password_hash); if (!isMatch) { // Log failed audit await catatAudit({ userId: user.id, aksi: 'login_gagal', entitas: 'user', entitasId: user.id, ipAddress: ip, userAgent: userAgent, dataBaru: { username }, }); throw new APIError('Username atau password salah', 401); } // Log successful login await catatAudit({ userId: user.id, aksi: 'login_sukses', entitas: 'user', entitasId: user.id, ipAddress: ip, userAgent: userAgent, }); // Generate tokens const userData = { sub: user.username, role: user.role }; const accessToken = createAccessToken(userData); const refreshToken = createRefreshToken(userData); return { user, accessToken, refreshToken, }; } static async refresh(refreshToken: string) { const payload = verifyToken(refreshToken); if (!payload || payload.type !== 'refresh') { throw new APIError('Refresh token tidak valid atau kedaluwarsa', 401); } const username = payload.sub; const role = payload.role; const user = await prisma.user.findFirst({ where: { username, aktif: 1, }, }); if (!user) { throw new APIError('Pengguna tidak aktif atau tidak ditemukan', 401); } const userData = { sub: username, role }; const newAccessToken = createAccessToken(userData); const newRefreshToken = createRefreshToken(userData); return { role: user.role, accessToken: newAccessToken, refreshToken: newRefreshToken, }; } static async logout(userId: number, ip: string, userAgent: string) { await catatAudit({ userId, aksi: 'logout', entitas: 'user', entitasId: userId, ipAddress: ip, userAgent, }); return true; } }