File size: 2,821 Bytes
ef874e6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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;
  }
}