Spaces:
Sleeping
Sleeping
| 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; | |
| } | |
| } | |