najm-auth 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of najm-auth might be problematic. Click here for more details.
- package/dist/index.mjs +1894 -1518
- package/package.json +5 -4
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
-
var
|
|
3
|
-
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
-
if (decorator = decorators[i])
|
|
7
|
-
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
-
if (kind && result) __defProp(target, key, result);
|
|
9
|
-
return result;
|
|
10
|
-
};
|
|
11
|
-
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
12
3
|
|
|
13
4
|
// src/auth/EncryptionService.ts
|
|
14
5
|
import { Injectable } from "najm-api";
|
|
15
6
|
import bcrypt from "bcrypt";
|
|
16
|
-
var
|
|
7
|
+
var __decorate = function(decorators, target, key, desc) {
|
|
8
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
11
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
12
|
+
};
|
|
13
|
+
var __metadata = function(k, v) {
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
15
|
+
};
|
|
16
|
+
var _a;
|
|
17
|
+
var EncryptionService = (_a = class {
|
|
17
18
|
constructor() {
|
|
18
19
|
}
|
|
19
20
|
async hashPassword(password) {
|
|
20
|
-
if (!password)
|
|
21
|
+
if (!password)
|
|
22
|
+
return null;
|
|
21
23
|
if (typeof password !== "string" || password.trim().length === 0) {
|
|
22
24
|
return null;
|
|
23
25
|
}
|
|
@@ -26,15 +28,23 @@ var EncryptionService = class {
|
|
|
26
28
|
async comparePassword(password, hashedPassword) {
|
|
27
29
|
return bcrypt.compare(password, hashedPassword);
|
|
28
30
|
}
|
|
29
|
-
};
|
|
30
|
-
EncryptionService =
|
|
31
|
-
Injectable()
|
|
31
|
+
}, __name(_a, "EncryptionService"), _a);
|
|
32
|
+
EncryptionService = __decorate([
|
|
33
|
+
Injectable(),
|
|
34
|
+
__metadata("design:paramtypes", [])
|
|
32
35
|
], EncryptionService);
|
|
33
36
|
|
|
34
37
|
// src/auth/CookieService.ts
|
|
35
38
|
import { setCookie, Injectable as Injectable2, deleteCookie } from "najm-api";
|
|
36
39
|
import timestring from "timestring";
|
|
37
|
-
var
|
|
40
|
+
var __decorate2 = function(decorators, target, key, desc) {
|
|
41
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
43
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
44
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
45
|
+
};
|
|
46
|
+
var _a2;
|
|
47
|
+
var CookieService = (_a2 = class {
|
|
38
48
|
setRefreshCookie(refreshToken) {
|
|
39
49
|
const maxAge = timestring(process.env.REFRESH_EXPIRES_IN, "s");
|
|
40
50
|
setCookie("refreshToken", refreshToken, {
|
|
@@ -52,229 +62,22 @@ var CookieService = class {
|
|
|
52
62
|
maxAge: 0
|
|
53
63
|
});
|
|
54
64
|
}
|
|
55
|
-
};
|
|
56
|
-
CookieService =
|
|
65
|
+
}, __name(_a2, "CookieService"), _a2);
|
|
66
|
+
CookieService = __decorate2([
|
|
57
67
|
Injectable2()
|
|
58
68
|
], CookieService);
|
|
59
69
|
|
|
60
70
|
// src/auth/AuthController.ts
|
|
61
|
-
import { Controller, Get, Post, Params, Body, User, t } from "najm-api";
|
|
62
|
-
|
|
63
|
-
// src/roles/RoleGuards.ts
|
|
64
|
-
import { Injectable as Injectable3, Headers, createGuard, GuardParams, Ctx } from "najm-api";
|
|
65
|
-
var ROLES = {
|
|
66
|
-
ADMIN: "admin",
|
|
67
|
-
PRINCIPAL: "principal",
|
|
68
|
-
ACCOUNTING: "accounting",
|
|
69
|
-
SECRETARY: "secretary",
|
|
70
|
-
TEACHER: "teacher",
|
|
71
|
-
STUDENT: "student",
|
|
72
|
-
PARENT: "parent"
|
|
73
|
-
};
|
|
74
|
-
var ROLE_GROUPS = {
|
|
75
|
-
ADMINISTRATORS: [ROLES.ADMIN, ROLES.PRINCIPAL],
|
|
76
|
-
FINANCIAL: [ROLES.ADMIN, ROLES.ACCOUNTING],
|
|
77
|
-
STAFF: [ROLES.ADMIN, ROLES.PRINCIPAL, ROLES.ACCOUNTING, ROLES.SECRETARY, ROLES.TEACHER],
|
|
78
|
-
END_USERS: [ROLES.STUDENT, ROLES.PARENT],
|
|
79
|
-
ALL: [ROLES.ADMIN, ROLES.PRINCIPAL, ROLES.ACCOUNTING, ROLES.SECRETARY, ROLES.TEACHER, ROLES.STUDENT, ROLES.PARENT]
|
|
80
|
-
};
|
|
81
|
-
var RoleChecker = class {
|
|
82
|
-
isInGroup(userRole, group) {
|
|
83
|
-
return group.includes(userRole?.toLowerCase());
|
|
84
|
-
}
|
|
85
|
-
isAdministrator(userRole) {
|
|
86
|
-
return this.isInGroup(userRole, ROLE_GROUPS.ADMINISTRATORS);
|
|
87
|
-
}
|
|
88
|
-
isStaff(userRole) {
|
|
89
|
-
return this.isInGroup(userRole, ROLE_GROUPS.STAFF);
|
|
90
|
-
}
|
|
91
|
-
hasAnyRole(userRole, roles) {
|
|
92
|
-
return roles.includes(userRole?.toLowerCase());
|
|
93
|
-
}
|
|
94
|
-
hasExactRole(userRole, requiredRole) {
|
|
95
|
-
return userRole?.toLowerCase() === requiredRole?.toLowerCase();
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
RoleChecker = __decorateClass([
|
|
99
|
-
Injectable3()
|
|
100
|
-
], RoleChecker);
|
|
101
|
-
var RoleGuards = class {
|
|
102
|
-
constructor(roleChecker, tokenService) {
|
|
103
|
-
this.roleChecker = roleChecker;
|
|
104
|
-
this.tokenService = tokenService;
|
|
105
|
-
}
|
|
106
|
-
async isAuth(auth, ctx) {
|
|
107
|
-
const user = await this.tokenService.storeUserInCache(auth, ctx);
|
|
108
|
-
return !!user;
|
|
109
|
-
}
|
|
110
|
-
async hasRoles(auth, ctx, roles) {
|
|
111
|
-
try {
|
|
112
|
-
const user = await this.tokenService.storeUserInCache(auth, ctx);
|
|
113
|
-
if (!user?.role) return false;
|
|
114
|
-
const roleArray = Array.isArray(roles) ? roles : [roles];
|
|
115
|
-
return this.roleChecker.hasAnyRole(user.role, roleArray);
|
|
116
|
-
} catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
__decorateClass([
|
|
122
|
-
__decorateParam(0, Headers("authorization")),
|
|
123
|
-
__decorateParam(1, Ctx())
|
|
124
|
-
], RoleGuards.prototype, "isAuth", 1);
|
|
125
|
-
__decorateClass([
|
|
126
|
-
__decorateParam(0, Headers("authorization")),
|
|
127
|
-
__decorateParam(1, Ctx()),
|
|
128
|
-
__decorateParam(2, GuardParams())
|
|
129
|
-
], RoleGuards.prototype, "hasRoles", 1);
|
|
130
|
-
RoleGuards = __decorateClass([
|
|
131
|
-
Injectable3()
|
|
132
|
-
], RoleGuards);
|
|
133
|
-
var isAdmin = () => Role("admin");
|
|
134
|
-
var isPrincipal = () => Role("principal");
|
|
135
|
-
var isAccounting = () => Role("accounting");
|
|
136
|
-
var isSecretary = () => Role("secretary");
|
|
137
|
-
var isTeacher = () => Role("teacher");
|
|
138
|
-
var isParent = () => Role("parent");
|
|
139
|
-
var isStudent = () => Role("student");
|
|
140
|
-
var isAdministrator = () => Role("admin", "principal");
|
|
141
|
-
var isFinancial = () => Role("admin", "accounting");
|
|
142
|
-
var isStaff = () => Role("admin", "principal", "accounting", "secretary", "teacher");
|
|
143
|
-
var isAuth = createGuard(RoleGuards, "isAuth");
|
|
144
|
-
var Role = (...roles) => createGuard(RoleGuards, "hasRoles")(...roles);
|
|
145
|
-
|
|
146
|
-
// src/auth/AuthController.ts
|
|
147
|
-
var AuthController = class {
|
|
148
|
-
constructor(authService) {
|
|
149
|
-
this.authService = authService;
|
|
150
|
-
}
|
|
151
|
-
async registerUser(body) {
|
|
152
|
-
const data = await this.authService.registerUser(body);
|
|
153
|
-
return {
|
|
154
|
-
data,
|
|
155
|
-
message: t("auth.success.register"),
|
|
156
|
-
status: "success"
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
async loginUser(body) {
|
|
160
|
-
const data = await this.authService.loginUser(body);
|
|
161
|
-
return {
|
|
162
|
-
data,
|
|
163
|
-
message: t("auth.success.login"),
|
|
164
|
-
status: "success"
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
async refreshTokens() {
|
|
168
|
-
const data = await this.authService.refreshTokens();
|
|
169
|
-
return {
|
|
170
|
-
data,
|
|
171
|
-
message: t("auth.success.tokenRefreshed"),
|
|
172
|
-
status: "success"
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
async logoutUser(id) {
|
|
176
|
-
const data = await this.authService.logoutUser(id);
|
|
177
|
-
return {
|
|
178
|
-
data,
|
|
179
|
-
message: t("auth.success.logout"),
|
|
180
|
-
status: "success"
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
async userProfile(user) {
|
|
184
|
-
const data = await this.authService.getUserProfile(user);
|
|
185
|
-
return {
|
|
186
|
-
data,
|
|
187
|
-
message: t("users.success.retrieved"),
|
|
188
|
-
status: "success"
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
async forgotPassword(body) {
|
|
192
|
-
const data = await this.authService.forgotPassword(body.email);
|
|
193
|
-
return {
|
|
194
|
-
data,
|
|
195
|
-
message: t("auth.success.passwordReset"),
|
|
196
|
-
status: "success"
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
__decorateClass([
|
|
201
|
-
Post("/register"),
|
|
202
|
-
__decorateParam(0, Body())
|
|
203
|
-
], AuthController.prototype, "registerUser", 1);
|
|
204
|
-
__decorateClass([
|
|
205
|
-
Post("/login"),
|
|
206
|
-
__decorateParam(0, Body())
|
|
207
|
-
], AuthController.prototype, "loginUser", 1);
|
|
208
|
-
__decorateClass([
|
|
209
|
-
Get("/refresh")
|
|
210
|
-
], AuthController.prototype, "refreshTokens", 1);
|
|
211
|
-
__decorateClass([
|
|
212
|
-
Get("/logout/:id"),
|
|
213
|
-
__decorateParam(0, Params("id"))
|
|
214
|
-
], AuthController.prototype, "logoutUser", 1);
|
|
215
|
-
__decorateClass([
|
|
216
|
-
Get("/me"),
|
|
217
|
-
isAuth(),
|
|
218
|
-
__decorateParam(0, User())
|
|
219
|
-
], AuthController.prototype, "userProfile", 1);
|
|
220
|
-
__decorateClass([
|
|
221
|
-
Post("/forgot-password"),
|
|
222
|
-
isAuth(),
|
|
223
|
-
__decorateParam(0, Body())
|
|
224
|
-
], AuthController.prototype, "forgotPassword", 1);
|
|
225
|
-
AuthController = __decorateClass([
|
|
226
|
-
Controller("/auth")
|
|
227
|
-
], AuthController);
|
|
71
|
+
import { Controller as Controller3, Get as Get3, Post as Post3, Params as Params3, Body as Body3, User, t as t7 } from "najm-api";
|
|
228
72
|
|
|
229
73
|
// src/auth/AuthService.ts
|
|
230
|
-
import { t as
|
|
231
|
-
import { Injectable as
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
this.cookieService = cookieService;
|
|
238
|
-
}
|
|
239
|
-
async registerUser(body) {
|
|
240
|
-
return await this.userService.create(body);
|
|
241
|
-
}
|
|
242
|
-
async loginUser(body) {
|
|
243
|
-
const { email, password } = body;
|
|
244
|
-
if (!email || !password) {
|
|
245
|
-
throw new Error(t2("auth.errors.invalidCredentials"));
|
|
246
|
-
}
|
|
247
|
-
const existingPassword = await this.userService.getPassword(email);
|
|
248
|
-
const { id } = await this.userService.getByEmail(email);
|
|
249
|
-
await this.userValidator.checkPasswordValid(password, existingPassword);
|
|
250
|
-
const data = await this.tokenService.generateTokens(id);
|
|
251
|
-
this.cookieService.setRefreshCookie(data.refreshToken);
|
|
252
|
-
return data;
|
|
253
|
-
}
|
|
254
|
-
async refreshTokens() {
|
|
255
|
-
const data = await this.tokenService.refreshTokens();
|
|
256
|
-
this.cookieService.setRefreshCookie(data.refreshToken);
|
|
257
|
-
return data;
|
|
258
|
-
}
|
|
259
|
-
async logoutUser(userId) {
|
|
260
|
-
await this.userValidator.checkUserExists(userId);
|
|
261
|
-
await this.tokenService.revokeToken(userId);
|
|
262
|
-
this.cookieService.clearRefreshCookie();
|
|
263
|
-
return { data: null, message: t2("auth.success.logout") };
|
|
264
|
-
}
|
|
265
|
-
async getUserProfile(userData) {
|
|
266
|
-
const lang = getCurrentLanguage();
|
|
267
|
-
return {
|
|
268
|
-
...userData,
|
|
269
|
-
language: lang
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
async forgotPassword(email) {
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
AuthService = __decorateClass([
|
|
276
|
-
Injectable4()
|
|
277
|
-
], AuthService);
|
|
74
|
+
import { t as t6 } from "najm-api";
|
|
75
|
+
import { Injectable as Injectable9, getCurrentLanguage as getCurrentLanguage2 } from "najm-api";
|
|
76
|
+
|
|
77
|
+
// src/database/schema/index.ts
|
|
78
|
+
import { pgTable, text, boolean, timestamp } from "drizzle-orm/pg-core";
|
|
79
|
+
import { nanoid } from "nanoid";
|
|
80
|
+
import { sql } from "drizzle-orm";
|
|
278
81
|
|
|
279
82
|
// src/lib/ENUMS.ts
|
|
280
83
|
var ENUMS = {
|
|
@@ -509,128 +312,374 @@ var ENUMS = {
|
|
|
509
312
|
translationKey: "parents.maritalStatus"
|
|
510
313
|
}
|
|
511
314
|
};
|
|
512
|
-
var getEnumConfig = (enumKey) => ENUMS[enumKey];
|
|
513
|
-
var getEnumValues = (enumKey) => ENUMS[enumKey]?.values || [];
|
|
514
|
-
|
|
515
|
-
// src/lib/validations.ts
|
|
516
|
-
import { z as z2 } from "zod";
|
|
315
|
+
var getEnumConfig = /* @__PURE__ */ __name((enumKey) => ENUMS[enumKey], "getEnumConfig");
|
|
316
|
+
var getEnumValues = /* @__PURE__ */ __name((enumKey) => ENUMS[enumKey]?.values || [], "getEnumValues");
|
|
517
317
|
|
|
518
|
-
// src/
|
|
519
|
-
import {
|
|
520
|
-
var
|
|
521
|
-
const
|
|
522
|
-
if (!
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
var
|
|
528
|
-
var
|
|
529
|
-
var
|
|
530
|
-
var
|
|
531
|
-
var studentStatusEnum = createZodEnum("studentStatus");
|
|
532
|
-
var teacherStatusEnum = createZodEnum("teacherStatus");
|
|
533
|
-
var employmentTypeEnum = createZodEnum("employmentType");
|
|
534
|
-
var relationshipTypeEnum = createZodEnum("relationshipType");
|
|
535
|
-
var semesterEnum = createZodEnum("semester");
|
|
536
|
-
var classStatusEnum = createZodEnum("classStatus");
|
|
537
|
-
var sectionStatusEnum = createZodEnum("sectionStatus");
|
|
538
|
-
var languageEnum = createZodEnum("language");
|
|
539
|
-
var enrollmentStatusEnum = createZodEnum("enrollmentStatus");
|
|
540
|
-
var assignmentStatusEnum = createZodEnum("assignmentStatus");
|
|
541
|
-
var calendarSystemEnum = createZodEnum("calendarSystem");
|
|
542
|
-
var assessmentTypeEnum = createZodEnum("assessmentType");
|
|
543
|
-
var assessmentStatusEnum = createZodEnum("assessmentStatus");
|
|
544
|
-
var submissionTypeEnum = createZodEnum("submissionType");
|
|
545
|
-
var examTypeEnum = createZodEnum("examType");
|
|
546
|
-
var examSecurityEnum = createZodEnum("examSecurity");
|
|
547
|
-
var examStatusEnum = createZodEnum("examStatus");
|
|
548
|
-
var gradeStatusEnum = createZodEnum("gradeStatus");
|
|
549
|
-
var attendanceStatusEnum = createZodEnum("attendanceStatus");
|
|
550
|
-
var proficiencyLevelEnum = createZodEnum("proficiencyLevel");
|
|
551
|
-
var dayOfWeekEnum = createZodEnum("dayOfWeek");
|
|
552
|
-
var alertTypeEnum = createZodEnum("alertType");
|
|
553
|
-
var alertPriorityEnum = createZodEnum("alertPriority");
|
|
554
|
-
var alertStatusEnum = createZodEnum("alertStatus");
|
|
555
|
-
var feeTypeStatusEnum = createZodEnum("feeTypeStatus");
|
|
556
|
-
var paymentTypeEnum = createZodEnum("paymentType");
|
|
557
|
-
var scheduleEnum = createZodEnum("schedule");
|
|
558
|
-
var feeStatusEnum = createZodEnum("feeStatus");
|
|
559
|
-
var feeInstallmentStatusEnum = createZodEnum("feeInstallmentStatus");
|
|
560
|
-
var paymentMethodEnum = createZodEnum("paymentMethod");
|
|
561
|
-
var paymentStatusEnum = createZodEnum("paymentStatus");
|
|
562
|
-
var eventTypeEnum = createZodEnum("eventType");
|
|
563
|
-
var eventStatusEnum = createZodEnum("eventStatus");
|
|
564
|
-
var eventVisibilityEnum = createZodEnum("eventVisibility");
|
|
565
|
-
var participantTypeEnum = createZodEnum("participantType");
|
|
566
|
-
var expenseCategoryEnum = createZodEnum("expenseCategory");
|
|
567
|
-
var expenseStatusEnum = createZodEnum("expenseStatus");
|
|
568
|
-
var trackerModeEnum = createZodEnum("trackerMode");
|
|
569
|
-
var driverStatusEnum = createZodEnum("driverStatus");
|
|
570
|
-
var vehicleStatusEnum = createZodEnum("vehicleStatus");
|
|
571
|
-
var vehicleTypeEnum = createZodEnum("vehicleType");
|
|
572
|
-
var vehicleDocumentTypeEnum = createZodEnum("vehicleDocumentType");
|
|
573
|
-
var busStatusEnum = createZodEnum("busStatus");
|
|
574
|
-
var refuelStatusEnum = createZodEnum("refuelStatus");
|
|
575
|
-
var fuelTypeEnum = createZodEnum("fuelType");
|
|
576
|
-
var maintenanceTypeEnum = createZodEnum("maintenanceType");
|
|
577
|
-
var maintenanceStatusEnum = createZodEnum("maintenanceStatus");
|
|
578
|
-
var maritalStatusEnum = createZodEnum("maritalStatus");
|
|
318
|
+
// src/database/schema/PgEnum.ts
|
|
319
|
+
import { pgEnum } from "drizzle-orm/pg-core";
|
|
320
|
+
var createPgEnum = /* @__PURE__ */ __name((enumKey) => {
|
|
321
|
+
const config = getEnumConfig(enumKey);
|
|
322
|
+
if (!config)
|
|
323
|
+
throw new Error(`Enum ${enumKey} not found`);
|
|
324
|
+
const enumName = config.name || enumKey;
|
|
325
|
+
return pgEnum(enumName, config.values);
|
|
326
|
+
}, "createPgEnum");
|
|
327
|
+
var userStatusEnum = createPgEnum("userStatus");
|
|
328
|
+
var tokenStatusEnum = createPgEnum("tokenStatus");
|
|
329
|
+
var tokenTypeEnum = createPgEnum("tokenType");
|
|
330
|
+
var studentStatusEnum = createPgEnum("studentStatus");
|
|
579
331
|
|
|
580
|
-
// src/
|
|
581
|
-
var
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
var phoneField = z2.string().regex(/^[\+]?[1-9][\d]{0,15}$/, "Invalid phone number");
|
|
585
|
-
var nameField = z2.string().min(2, "Name must be at least 2 characters").max(100, "Name too long");
|
|
586
|
-
var dateField = z2.string().regex(/^(\d{4}-\d{2}-\d{2}|\d{2}\/\d{2}\/\d{4}|\d{2}-\d{2}-\d{2}|\d{2}-\d{2}-\d{4})$/, "Date must be in YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MM-YY, or DD-MM-YYYY format");
|
|
587
|
-
var optionalDateField = z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").nullable().optional();
|
|
588
|
-
var timeField = z2.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, "Time must be in HH:MM format").optional().nullable();
|
|
589
|
-
var cinField = z2.string().min(8, "CIN must be at least 8 characters").max(20, "CIN too long");
|
|
590
|
-
var addressField = z2.string().max(500, "Address too long").optional();
|
|
591
|
-
var academicYearField = z2.string().min(9, "Academic year is required").regex(/^\d{4}-\d{4}$/, "Academic year must be in YYYY-YYYY format");
|
|
592
|
-
var num = () => {
|
|
593
|
-
const createChainable = (currentSchema) => {
|
|
594
|
-
const methods = {
|
|
595
|
-
positive: (msg = "Must be positive") => createChainable(currentSchema.refine((val) => val > 0, { message: msg })),
|
|
596
|
-
min: (value, msg) => createChainable(currentSchema.refine(
|
|
597
|
-
(val) => val >= value,
|
|
598
|
-
{ message: msg || `Must be at least ${value}` }
|
|
599
|
-
)),
|
|
600
|
-
max: (value, msg) => createChainable(currentSchema.refine(
|
|
601
|
-
(val) => val <= value,
|
|
602
|
-
{ message: msg || `Cannot exceed ${value}` }
|
|
603
|
-
)),
|
|
604
|
-
int: (msg = "Must be an integer") => createChainable(currentSchema.refine(
|
|
605
|
-
(val) => Number.isInteger(val),
|
|
606
|
-
{ message: msg }
|
|
607
|
-
))
|
|
608
|
-
};
|
|
609
|
-
return Object.assign(currentSchema, methods);
|
|
610
|
-
};
|
|
611
|
-
const isValidNumber = (val) => {
|
|
612
|
-
if (val === null || val === void 0 || Number.isNaN(val)) return false;
|
|
613
|
-
if (typeof val === "number") return true;
|
|
614
|
-
if (typeof val === "string") {
|
|
615
|
-
const trimmed = val.trim();
|
|
616
|
-
return trimmed !== "" && !isNaN(Number(trimmed));
|
|
617
|
-
}
|
|
618
|
-
return false;
|
|
619
|
-
};
|
|
620
|
-
const baseSchema = z2.any().refine(isValidNumber, { message: "Must be a valid number" }).transform((val) => typeof val === "string" ? Number(val) : val);
|
|
621
|
-
return createChainable(baseSchema);
|
|
332
|
+
// src/database/schema/index.ts
|
|
333
|
+
var timestamps = {
|
|
334
|
+
createdAt: timestamp("created_at", { mode: "string" }).defaultNow(),
|
|
335
|
+
updatedAt: timestamp("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql`CURRENT_TIMESTAMP`)
|
|
622
336
|
};
|
|
623
|
-
var
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
337
|
+
var idField = /* @__PURE__ */ __name((length = 5) => text("id").primaryKey().notNull().$defaultFn(() => nanoid(length)), "idField");
|
|
338
|
+
var rolesTable = pgTable("roles", {
|
|
339
|
+
id: idField(),
|
|
340
|
+
name: text("name").notNull(),
|
|
341
|
+
description: text("description")
|
|
342
|
+
});
|
|
343
|
+
var usersTable = pgTable("users", {
|
|
344
|
+
id: idField(8),
|
|
345
|
+
email: text("email").notNull().unique(),
|
|
346
|
+
emailVerified: boolean("email_verified").default(false),
|
|
347
|
+
password: text("password").notNull(),
|
|
348
|
+
image: text("image").default("noavatar.png"),
|
|
349
|
+
status: userStatusEnum("status").default("pending"),
|
|
350
|
+
roleId: text("role_id").references(() => rolesTable.id),
|
|
351
|
+
lastLogin: timestamp("last_login", { mode: "string" }),
|
|
352
|
+
...timestamps
|
|
353
|
+
});
|
|
354
|
+
var tokensTable = pgTable("tokens", {
|
|
355
|
+
id: idField(10),
|
|
356
|
+
userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }).unique().notNull(),
|
|
357
|
+
token: text("token").notNull(),
|
|
358
|
+
type: tokenTypeEnum("type").default("refresh"),
|
|
359
|
+
status: tokenStatusEnum("status").default("active"),
|
|
360
|
+
expiresAt: timestamp("expires_at", { mode: "string" }).notNull(),
|
|
361
|
+
...timestamps
|
|
362
|
+
});
|
|
363
|
+
var permissionsTable = pgTable("permissions", {
|
|
364
|
+
id: idField(),
|
|
365
|
+
name: text("name").notNull().unique(),
|
|
366
|
+
description: text("description"),
|
|
367
|
+
resource: text("resource").notNull(),
|
|
368
|
+
action: text("action").notNull(),
|
|
369
|
+
...timestamps
|
|
370
|
+
});
|
|
371
|
+
var rolePermissionsTable = pgTable("role_permissions", {
|
|
372
|
+
id: idField(),
|
|
373
|
+
roleId: text("role_id").references(() => rolesTable.id).notNull(),
|
|
374
|
+
permissionId: text("permission_id").references(() => permissionsTable.id).notNull(),
|
|
375
|
+
...timestamps
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// src/users/UserRepository.ts
|
|
379
|
+
import { eq, ne } from "drizzle-orm";
|
|
380
|
+
import { Repository } from "najm-api";
|
|
381
|
+
var __decorate3 = function(decorators, target, key, desc) {
|
|
382
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
383
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
384
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
385
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
386
|
+
};
|
|
387
|
+
var _a3;
|
|
388
|
+
var UserRepository = (_a3 = class {
|
|
389
|
+
getUser() {
|
|
390
|
+
return {
|
|
391
|
+
id: usersTable.id,
|
|
392
|
+
email: usersTable.email,
|
|
393
|
+
emailVerified: usersTable.emailVerified,
|
|
394
|
+
image: usersTable.image,
|
|
395
|
+
status: usersTable.status,
|
|
396
|
+
roleId: usersTable.roleId,
|
|
397
|
+
role: rolesTable.name,
|
|
398
|
+
createdAt: usersTable.createdAt,
|
|
399
|
+
updatedAt: usersTable.updatedAt
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
async getAll() {
|
|
403
|
+
const allUsers = await this.db.select(this.getUser()).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id));
|
|
404
|
+
return Promise.all(allUsers.map(async (user) => ({
|
|
405
|
+
...user,
|
|
406
|
+
permissions: await this.getUserPermissions(user.id)
|
|
407
|
+
})));
|
|
408
|
+
}
|
|
409
|
+
async getById(id) {
|
|
410
|
+
const [user] = await this.db.select(this.getUser()).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id)).where(eq(usersTable.id, id)).limit(1);
|
|
411
|
+
if (!user)
|
|
412
|
+
return user;
|
|
413
|
+
return {
|
|
414
|
+
...user,
|
|
415
|
+
permissions: await this.getUserPermissions(user.id)
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
async getByEmail(email) {
|
|
419
|
+
const [existingUser] = await this.db.select(this.getUser()).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id)).where(eq(usersTable.email, email));
|
|
420
|
+
return existingUser;
|
|
421
|
+
}
|
|
422
|
+
async create(data) {
|
|
423
|
+
const [newUser] = await this.db.insert(usersTable).values(data).returning();
|
|
424
|
+
return newUser;
|
|
425
|
+
}
|
|
426
|
+
async update(id, data) {
|
|
427
|
+
const [updatedUser] = await this.db.update(usersTable).set(data).where(eq(usersTable.id, id)).returning();
|
|
428
|
+
return updatedUser;
|
|
429
|
+
}
|
|
430
|
+
async delete(id) {
|
|
431
|
+
const [deletedUser] = await this.db.delete(usersTable).where(eq(usersTable.id, id)).returning();
|
|
432
|
+
return deletedUser;
|
|
433
|
+
}
|
|
434
|
+
async deleteAll() {
|
|
435
|
+
const adminRole = await this.db.select({ id: rolesTable.id }).from(rolesTable).where(eq(rolesTable.name, "admin")).limit(1);
|
|
436
|
+
if (adminRole.length === 0) {
|
|
437
|
+
const deletedUsers2 = await this.db.delete(usersTable).returning();
|
|
438
|
+
return deletedUsers2;
|
|
439
|
+
}
|
|
440
|
+
const deletedUsers = await this.db.delete(usersTable).where(ne(usersTable.roleId, adminRole[0].id)).returning();
|
|
441
|
+
return deletedUsers;
|
|
442
|
+
}
|
|
443
|
+
async getRoleNameById(userId) {
|
|
444
|
+
const [role] = await this.db.select({
|
|
445
|
+
roleName: rolesTable.name
|
|
446
|
+
}).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id)).where(eq(usersTable.id, userId));
|
|
447
|
+
return role.roleName;
|
|
448
|
+
}
|
|
449
|
+
async getUserPassword(email) {
|
|
450
|
+
const [user] = await this.db.select({
|
|
451
|
+
id: usersTable.id,
|
|
452
|
+
email: usersTable.email,
|
|
453
|
+
password: usersTable.password
|
|
454
|
+
}).from(usersTable).where(eq(usersTable.email, email)).limit(1);
|
|
455
|
+
return user.password;
|
|
456
|
+
}
|
|
457
|
+
async getUserPermissions(userId) {
|
|
458
|
+
const [user] = await this.db.select({ roleId: usersTable.roleId }).from(usersTable).where(eq(usersTable.id, userId)).limit(1);
|
|
459
|
+
if (!user || !user.roleId)
|
|
460
|
+
return [];
|
|
461
|
+
const userPermissions = await this.db.select({
|
|
462
|
+
name: permissionsTable.name
|
|
463
|
+
}).from(rolePermissionsTable).leftJoin(permissionsTable, eq(rolePermissionsTable.permissionId, permissionsTable.id)).where(eq(rolePermissionsTable.roleId, user.roleId));
|
|
464
|
+
return userPermissions.map((p) => p.name).filter((name) => name);
|
|
465
|
+
}
|
|
466
|
+
}, __name(_a3, "UserRepository"), _a3);
|
|
467
|
+
UserRepository = __decorate3([
|
|
468
|
+
Repository()
|
|
469
|
+
], UserRepository);
|
|
470
|
+
|
|
471
|
+
// src/users/UserValidator.ts
|
|
472
|
+
import { Injectable as Injectable3, t } from "najm-api";
|
|
473
|
+
|
|
474
|
+
// src/shared/index.ts
|
|
475
|
+
import * as fs from "fs/promises";
|
|
476
|
+
import * as path from "path";
|
|
477
|
+
import _isEmpty from "lodash.isempty";
|
|
478
|
+
var avatarsPath = path.join(process.cwd(), "avatars");
|
|
479
|
+
var parseSchema = /* @__PURE__ */ __name(async (schema, data) => {
|
|
480
|
+
try {
|
|
481
|
+
return await schema.parseAsync(data);
|
|
482
|
+
} catch (error) {
|
|
483
|
+
const errors = error.issues || error.errors || [];
|
|
484
|
+
const errorMessage = errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
|
|
485
|
+
throw new Error(errorMessage);
|
|
486
|
+
}
|
|
487
|
+
}, "parseSchema");
|
|
488
|
+
var clean = /* @__PURE__ */ __name((obj) => {
|
|
489
|
+
const cleaned = {};
|
|
490
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
491
|
+
if (value !== null && value !== void 0 && value !== "") {
|
|
492
|
+
cleaned[key] = value;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return cleaned;
|
|
496
|
+
}, "clean");
|
|
497
|
+
var getAvatarFile = /* @__PURE__ */ __name(async (fileName) => {
|
|
498
|
+
try {
|
|
499
|
+
const filePath = path.join(avatarsPath, fileName);
|
|
500
|
+
const buffer = await fs.readFile(filePath);
|
|
501
|
+
const file = new File([buffer], fileName, {
|
|
502
|
+
type: "image/png"
|
|
503
|
+
});
|
|
504
|
+
return file;
|
|
505
|
+
} catch (error) {
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
}, "getAvatarFile");
|
|
509
|
+
var formatDate = /* @__PURE__ */ __name((dateValue) => {
|
|
510
|
+
if (!dateValue)
|
|
511
|
+
return null;
|
|
512
|
+
let date;
|
|
513
|
+
if (dateValue instanceof Date) {
|
|
514
|
+
date = dateValue;
|
|
515
|
+
} else if (typeof dateValue === "string") {
|
|
516
|
+
date = new Date(dateValue);
|
|
517
|
+
} else {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
if (isNaN(date.getTime()))
|
|
521
|
+
return null;
|
|
522
|
+
return date.toISOString().split("T")[0];
|
|
523
|
+
}, "formatDate");
|
|
524
|
+
function calculateAge(dateOfBirth) {
|
|
525
|
+
if (!dateOfBirth)
|
|
526
|
+
return null;
|
|
527
|
+
const formattedDate = formatDate(dateOfBirth);
|
|
528
|
+
if (!formattedDate)
|
|
529
|
+
return null;
|
|
530
|
+
const birth = new Date(formattedDate);
|
|
531
|
+
const today = /* @__PURE__ */ new Date();
|
|
532
|
+
let age = today.getFullYear() - birth.getFullYear();
|
|
533
|
+
const monthDiff = today.getMonth() - birth.getMonth();
|
|
534
|
+
if (monthDiff < 0 || monthDiff === 0 && today.getDate() < birth.getDate()) {
|
|
535
|
+
age--;
|
|
536
|
+
}
|
|
537
|
+
return age;
|
|
538
|
+
}
|
|
539
|
+
__name(calculateAge, "calculateAge");
|
|
540
|
+
function calculateYearsOfExperience(hireDate) {
|
|
541
|
+
if (!hireDate)
|
|
542
|
+
return null;
|
|
543
|
+
const formattedDate = formatDate(hireDate);
|
|
544
|
+
if (!formattedDate)
|
|
545
|
+
return null;
|
|
546
|
+
const hire = new Date(formattedDate);
|
|
547
|
+
const today = /* @__PURE__ */ new Date();
|
|
548
|
+
let years = today.getFullYear() - hire.getFullYear();
|
|
549
|
+
const monthDiff = today.getMonth() - hire.getMonth();
|
|
550
|
+
if (monthDiff < 0 || monthDiff === 0 && today.getDate() < hire.getDate()) {
|
|
551
|
+
years--;
|
|
552
|
+
}
|
|
553
|
+
return years;
|
|
554
|
+
}
|
|
555
|
+
__name(calculateYearsOfExperience, "calculateYearsOfExperience");
|
|
556
|
+
function pickProps(source, keys) {
|
|
557
|
+
const result = {};
|
|
558
|
+
for (const key of keys) {
|
|
559
|
+
if (source[key] !== void 0) {
|
|
560
|
+
result[key] = source[key];
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return result;
|
|
564
|
+
}
|
|
565
|
+
__name(pickProps, "pickProps");
|
|
566
|
+
var isEmpty = _isEmpty;
|
|
567
|
+
var isPath = /* @__PURE__ */ __name((img) => typeof img === "string" && img.trim().length > 0 && (img.startsWith("/") || img.startsWith("http") || img.startsWith("storage/")), "isPath");
|
|
568
|
+
var isFile = /* @__PURE__ */ __name((img) => !!img && typeof img !== "string" && img instanceof File, "isFile");
|
|
569
|
+
|
|
570
|
+
// src/lib/validations.ts
|
|
571
|
+
import { z as z2 } from "zod";
|
|
572
|
+
|
|
573
|
+
// src/lib/ZodEnum.ts
|
|
574
|
+
import { z } from "zod";
|
|
575
|
+
var createZodEnum = /* @__PURE__ */ __name((enumKey) => {
|
|
576
|
+
const values = ENUMS[enumKey]?.values;
|
|
577
|
+
if (!values)
|
|
578
|
+
throw new Error(`Enum ${enumKey} not found`);
|
|
579
|
+
return z.enum(values);
|
|
580
|
+
}, "createZodEnum");
|
|
581
|
+
var userTypeEnum = createZodEnum("userType");
|
|
582
|
+
var userStatusEnum2 = createZodEnum("userStatus");
|
|
583
|
+
var tokenStatusEnum2 = createZodEnum("tokenStatus");
|
|
584
|
+
var tokenTypeEnum2 = createZodEnum("tokenType");
|
|
585
|
+
var fileStatusEnum = createZodEnum("fileStatus");
|
|
586
|
+
var genderEnum = createZodEnum("gender");
|
|
587
|
+
var studentStatusEnum2 = createZodEnum("studentStatus");
|
|
588
|
+
var teacherStatusEnum = createZodEnum("teacherStatus");
|
|
589
|
+
var employmentTypeEnum = createZodEnum("employmentType");
|
|
590
|
+
var relationshipTypeEnum = createZodEnum("relationshipType");
|
|
591
|
+
var semesterEnum = createZodEnum("semester");
|
|
592
|
+
var classStatusEnum = createZodEnum("classStatus");
|
|
593
|
+
var sectionStatusEnum = createZodEnum("sectionStatus");
|
|
594
|
+
var languageEnum = createZodEnum("language");
|
|
595
|
+
var enrollmentStatusEnum = createZodEnum("enrollmentStatus");
|
|
596
|
+
var assignmentStatusEnum = createZodEnum("assignmentStatus");
|
|
597
|
+
var calendarSystemEnum = createZodEnum("calendarSystem");
|
|
598
|
+
var assessmentTypeEnum = createZodEnum("assessmentType");
|
|
599
|
+
var assessmentStatusEnum = createZodEnum("assessmentStatus");
|
|
600
|
+
var submissionTypeEnum = createZodEnum("submissionType");
|
|
601
|
+
var examTypeEnum = createZodEnum("examType");
|
|
602
|
+
var examSecurityEnum = createZodEnum("examSecurity");
|
|
603
|
+
var examStatusEnum = createZodEnum("examStatus");
|
|
604
|
+
var gradeStatusEnum = createZodEnum("gradeStatus");
|
|
605
|
+
var attendanceStatusEnum = createZodEnum("attendanceStatus");
|
|
606
|
+
var proficiencyLevelEnum = createZodEnum("proficiencyLevel");
|
|
607
|
+
var dayOfWeekEnum = createZodEnum("dayOfWeek");
|
|
608
|
+
var alertTypeEnum = createZodEnum("alertType");
|
|
609
|
+
var alertPriorityEnum = createZodEnum("alertPriority");
|
|
610
|
+
var alertStatusEnum = createZodEnum("alertStatus");
|
|
611
|
+
var feeTypeStatusEnum = createZodEnum("feeTypeStatus");
|
|
612
|
+
var paymentTypeEnum = createZodEnum("paymentType");
|
|
613
|
+
var scheduleEnum = createZodEnum("schedule");
|
|
614
|
+
var feeStatusEnum = createZodEnum("feeStatus");
|
|
615
|
+
var feeInstallmentStatusEnum = createZodEnum("feeInstallmentStatus");
|
|
616
|
+
var paymentMethodEnum = createZodEnum("paymentMethod");
|
|
617
|
+
var paymentStatusEnum = createZodEnum("paymentStatus");
|
|
618
|
+
var eventTypeEnum = createZodEnum("eventType");
|
|
619
|
+
var eventStatusEnum = createZodEnum("eventStatus");
|
|
620
|
+
var eventVisibilityEnum = createZodEnum("eventVisibility");
|
|
621
|
+
var participantTypeEnum = createZodEnum("participantType");
|
|
622
|
+
var expenseCategoryEnum = createZodEnum("expenseCategory");
|
|
623
|
+
var expenseStatusEnum = createZodEnum("expenseStatus");
|
|
624
|
+
var trackerModeEnum = createZodEnum("trackerMode");
|
|
625
|
+
var driverStatusEnum = createZodEnum("driverStatus");
|
|
626
|
+
var vehicleStatusEnum = createZodEnum("vehicleStatus");
|
|
627
|
+
var vehicleTypeEnum = createZodEnum("vehicleType");
|
|
628
|
+
var vehicleDocumentTypeEnum = createZodEnum("vehicleDocumentType");
|
|
629
|
+
var busStatusEnum = createZodEnum("busStatus");
|
|
630
|
+
var refuelStatusEnum = createZodEnum("refuelStatus");
|
|
631
|
+
var fuelTypeEnum = createZodEnum("fuelType");
|
|
632
|
+
var maintenanceTypeEnum = createZodEnum("maintenanceType");
|
|
633
|
+
var maintenanceStatusEnum = createZodEnum("maintenanceStatus");
|
|
634
|
+
var maritalStatusEnum = createZodEnum("maritalStatus");
|
|
635
|
+
|
|
636
|
+
// src/lib/validations.ts
|
|
637
|
+
var requiredId = z2.preprocess((val) => val ?? "", z2.string().min(1, "ID is required"));
|
|
638
|
+
var optionalId = z2.string().min(1, "ID cannot be empty").nullish().optional();
|
|
639
|
+
var emailField = z2.string().email("Invalid email format").or(z2.literal(""));
|
|
640
|
+
var phoneField = z2.string().regex(/^[\+]?[1-9][\d]{0,15}$/, "Invalid phone number");
|
|
641
|
+
var nameField = z2.string().min(2, "Name must be at least 2 characters").max(100, "Name too long");
|
|
642
|
+
var dateField = z2.string().regex(/^(\d{4}-\d{2}-\d{2}|\d{2}\/\d{2}\/\d{4}|\d{2}-\d{2}-\d{2}|\d{2}-\d{2}-\d{4})$/, "Date must be in YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MM-YY, or DD-MM-YYYY format");
|
|
643
|
+
var optionalDateField = z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").nullable().optional();
|
|
644
|
+
var timeField = z2.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, "Time must be in HH:MM format").optional().nullable();
|
|
645
|
+
var cinField = z2.string().min(8, "CIN must be at least 8 characters").max(20, "CIN too long");
|
|
646
|
+
var addressField = z2.string().max(500, "Address too long").optional();
|
|
647
|
+
var academicYearField = z2.string().min(9, "Academic year is required").regex(/^\d{4}-\d{4}$/, "Academic year must be in YYYY-YYYY format");
|
|
648
|
+
var num = /* @__PURE__ */ __name(() => {
|
|
649
|
+
const createChainable = /* @__PURE__ */ __name((currentSchema) => {
|
|
650
|
+
const methods = {
|
|
651
|
+
positive: /* @__PURE__ */ __name((msg = "Must be positive") => createChainable(currentSchema.refine((val) => val > 0, { message: msg })), "positive"),
|
|
652
|
+
min: /* @__PURE__ */ __name((value, msg) => createChainable(currentSchema.refine((val) => val >= value, { message: msg || `Must be at least ${value}` })), "min"),
|
|
653
|
+
max: /* @__PURE__ */ __name((value, msg) => createChainable(currentSchema.refine((val) => val <= value, { message: msg || `Cannot exceed ${value}` })), "max"),
|
|
654
|
+
int: /* @__PURE__ */ __name((msg = "Must be an integer") => createChainable(currentSchema.refine((val) => Number.isInteger(val), { message: msg })), "int")
|
|
655
|
+
};
|
|
656
|
+
return Object.assign(currentSchema, methods);
|
|
657
|
+
}, "createChainable");
|
|
658
|
+
const isValidNumber = /* @__PURE__ */ __name((val) => {
|
|
659
|
+
if (val === null || val === void 0 || Number.isNaN(val))
|
|
660
|
+
return false;
|
|
661
|
+
if (typeof val === "number")
|
|
662
|
+
return true;
|
|
663
|
+
if (typeof val === "string") {
|
|
664
|
+
const trimmed = val.trim();
|
|
665
|
+
return trimmed !== "" && !isNaN(Number(trimmed));
|
|
666
|
+
}
|
|
667
|
+
return false;
|
|
668
|
+
}, "isValidNumber");
|
|
669
|
+
const baseSchema = z2.any().refine(isValidNumber, { message: "Must be a valid number" }).transform((val) => typeof val === "string" ? Number(val) : val);
|
|
670
|
+
return createChainable(baseSchema);
|
|
671
|
+
}, "num");
|
|
672
|
+
var userSchema = z2.object({
|
|
673
|
+
id: optionalId,
|
|
674
|
+
username: nameField.max(50).optional(),
|
|
675
|
+
email: emailField,
|
|
676
|
+
password: z2.string().min(8, "Password must be at least 8 characters"),
|
|
677
|
+
roleId: optionalId,
|
|
629
678
|
roleName: nameField.max(50).optional(),
|
|
630
679
|
lastLogin: optionalDateField,
|
|
631
680
|
image: z2.union([z2.string(), z2.instanceof(File), z2.undefined()]).optional(),
|
|
632
681
|
emailVerified: z2.boolean().default(false),
|
|
633
|
-
status:
|
|
682
|
+
status: userStatusEnum2,
|
|
634
683
|
createdAt: optionalDateField
|
|
635
684
|
});
|
|
636
685
|
var roleSchema = z2.object({
|
|
@@ -654,7 +703,7 @@ var studentSchema = z2.object({
|
|
|
654
703
|
medicalConditions: z2.string().max(1e3, "Medical conditions description too long").nullish().optional(),
|
|
655
704
|
previousSchool: z2.string().max(500, "Previous school name too long").optional().nullable(),
|
|
656
705
|
image: z2.union([z2.string(), z2.instanceof(File), z2.null()]).optional(),
|
|
657
|
-
status:
|
|
706
|
+
status: studentStatusEnum2.default("active")
|
|
658
707
|
});
|
|
659
708
|
var parentSchema = z2.object({
|
|
660
709
|
id: optionalId,
|
|
@@ -1075,648 +1124,612 @@ var dateRangeSchema = z2.object({
|
|
|
1075
1124
|
dateTo: dateField
|
|
1076
1125
|
});
|
|
1077
1126
|
|
|
1078
|
-
// src/
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
import { pgEnum } from "drizzle-orm/pg-core";
|
|
1085
|
-
var createPgEnum = (enumKey) => {
|
|
1086
|
-
const config = getEnumConfig(enumKey);
|
|
1087
|
-
if (!config) throw new Error(`Enum ${enumKey} not found`);
|
|
1088
|
-
const enumName = config.name || enumKey;
|
|
1089
|
-
return pgEnum(enumName, config.values);
|
|
1127
|
+
// src/users/UserValidator.ts
|
|
1128
|
+
var __decorate4 = function(decorators, target, key, desc) {
|
|
1129
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1130
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1131
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1132
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1090
1133
|
};
|
|
1091
|
-
var
|
|
1092
|
-
|
|
1093
|
-
var tokenTypeEnum2 = createPgEnum("tokenType");
|
|
1094
|
-
var studentStatusEnum2 = createPgEnum("studentStatus");
|
|
1095
|
-
|
|
1096
|
-
// src/database/schema/index.ts
|
|
1097
|
-
var timestamps = {
|
|
1098
|
-
createdAt: timestamp("created_at", { mode: "string" }).defaultNow(),
|
|
1099
|
-
updatedAt: timestamp("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql`CURRENT_TIMESTAMP`)
|
|
1134
|
+
var __metadata2 = function(k, v) {
|
|
1135
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1100
1136
|
};
|
|
1101
|
-
var
|
|
1102
|
-
var
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
id: idField(8),
|
|
1109
|
-
email: text("email").notNull().unique(),
|
|
1110
|
-
emailVerified: boolean("email_verified").default(false),
|
|
1111
|
-
password: text("password").notNull(),
|
|
1112
|
-
image: text("image").default("noavatar.png"),
|
|
1113
|
-
status: userStatusEnum2("status").default("pending"),
|
|
1114
|
-
roleId: text("role_id").references(() => rolesTable.id),
|
|
1115
|
-
lastLogin: timestamp("last_login", { mode: "string" }),
|
|
1116
|
-
...timestamps
|
|
1117
|
-
});
|
|
1118
|
-
var tokensTable = pgTable("tokens", {
|
|
1119
|
-
id: idField(10),
|
|
1120
|
-
userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }).unique().notNull(),
|
|
1121
|
-
token: text("token").notNull(),
|
|
1122
|
-
type: tokenTypeEnum2("type").default("refresh"),
|
|
1123
|
-
status: tokenStatusEnum2("status").default("active"),
|
|
1124
|
-
expiresAt: timestamp("expires_at", { mode: "string" }).notNull(),
|
|
1125
|
-
...timestamps
|
|
1126
|
-
});
|
|
1127
|
-
var permissionsTable = pgTable("permissions", {
|
|
1128
|
-
id: idField(),
|
|
1129
|
-
name: text("name").notNull().unique(),
|
|
1130
|
-
description: text("description"),
|
|
1131
|
-
resource: text("resource").notNull(),
|
|
1132
|
-
action: text("action").notNull(),
|
|
1133
|
-
...timestamps
|
|
1134
|
-
});
|
|
1135
|
-
var rolePermissionsTable = pgTable("role_permissions", {
|
|
1136
|
-
id: idField(),
|
|
1137
|
-
roleId: text("role_id").references(() => rolesTable.id).notNull(),
|
|
1138
|
-
permissionId: text("permission_id").references(() => permissionsTable.id).notNull(),
|
|
1139
|
-
...timestamps
|
|
1140
|
-
});
|
|
1141
|
-
|
|
1142
|
-
// src/permissions/PermissionRepository.ts
|
|
1143
|
-
import { eq, and } from "drizzle-orm";
|
|
1144
|
-
import { Repository } from "najm-api";
|
|
1145
|
-
var PermissionRepository = class {
|
|
1146
|
-
async getAll() {
|
|
1147
|
-
return await this.db.select().from(permissionsTable);
|
|
1148
|
-
}
|
|
1149
|
-
async getById(id) {
|
|
1150
|
-
const [existingPermission] = await this.db.select().from(permissionsTable).where(eq(permissionsTable.id, id));
|
|
1151
|
-
return existingPermission;
|
|
1152
|
-
}
|
|
1153
|
-
async getByName(name) {
|
|
1154
|
-
const [existingPermission] = await this.db.select().from(permissionsTable).where(eq(permissionsTable.name, name));
|
|
1155
|
-
return existingPermission;
|
|
1156
|
-
}
|
|
1157
|
-
async create(data) {
|
|
1158
|
-
const [newPermission] = await this.db.insert(permissionsTable).values(data).returning();
|
|
1159
|
-
return newPermission;
|
|
1160
|
-
}
|
|
1161
|
-
async update(id, data) {
|
|
1162
|
-
const [updatedPermission] = await this.db.update(permissionsTable).set(data).where(eq(permissionsTable.id, id)).returning();
|
|
1163
|
-
return updatedPermission;
|
|
1164
|
-
}
|
|
1165
|
-
async delete(id) {
|
|
1166
|
-
const [deletedPermission] = await this.db.delete(permissionsTable).where(eq(permissionsTable.id, id)).returning();
|
|
1167
|
-
return deletedPermission;
|
|
1168
|
-
}
|
|
1169
|
-
async getPermissionsByRole(roleId) {
|
|
1170
|
-
return await this.db.select({
|
|
1171
|
-
id: permissionsTable.id,
|
|
1172
|
-
name: permissionsTable.name,
|
|
1173
|
-
description: permissionsTable.description,
|
|
1174
|
-
resource: permissionsTable.resource,
|
|
1175
|
-
action: permissionsTable.action
|
|
1176
|
-
}).from(rolePermissionsTable).leftJoin(permissionsTable, eq(rolePermissionsTable.permissionId, permissionsTable.id)).where(eq(rolePermissionsTable.roleId, roleId));
|
|
1177
|
-
}
|
|
1178
|
-
async getRolesByPermission(permissionId) {
|
|
1179
|
-
return await this.db.select({
|
|
1180
|
-
id: rolesTable.id,
|
|
1181
|
-
name: rolesTable.name,
|
|
1182
|
-
description: rolesTable.description
|
|
1183
|
-
}).from(rolePermissionsTable).leftJoin(rolesTable, eq(rolePermissionsTable.roleId, rolesTable.id)).where(eq(rolePermissionsTable.permissionId, permissionId));
|
|
1137
|
+
var _a4;
|
|
1138
|
+
var _b;
|
|
1139
|
+
var _a5;
|
|
1140
|
+
var UserValidator = (_a5 = class {
|
|
1141
|
+
constructor(userRepository, encryptionService) {
|
|
1142
|
+
this.userRepository = userRepository;
|
|
1143
|
+
this.encryptionService = encryptionService;
|
|
1184
1144
|
}
|
|
1185
|
-
async
|
|
1186
|
-
|
|
1187
|
-
return newRolePermission;
|
|
1145
|
+
async validateCreateUser(data) {
|
|
1146
|
+
return parseSchema(userSchema, data);
|
|
1188
1147
|
}
|
|
1189
|
-
async
|
|
1190
|
-
const
|
|
1191
|
-
return
|
|
1148
|
+
async isEmailExists(email) {
|
|
1149
|
+
const existingUser = await this.userRepository.getByEmail(email);
|
|
1150
|
+
return !!existingUser;
|
|
1192
1151
|
}
|
|
1193
|
-
async
|
|
1194
|
-
const
|
|
1195
|
-
return !!
|
|
1152
|
+
async isPasswordValid(password, hashedPassword) {
|
|
1153
|
+
const isPasswordValid = await this.encryptionService.comparePassword(password, hashedPassword);
|
|
1154
|
+
return !!isPasswordValid;
|
|
1196
1155
|
}
|
|
1197
|
-
async
|
|
1198
|
-
await this.
|
|
1199
|
-
|
|
1200
|
-
return deletedPermissions;
|
|
1156
|
+
async isUserExist(id) {
|
|
1157
|
+
const existingUser = await this.userRepository.getById(id);
|
|
1158
|
+
return !!existingUser;
|
|
1201
1159
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
var PermissionGuards = class {
|
|
1210
|
-
constructor(tokenService) {
|
|
1211
|
-
this.tokenService = tokenService;
|
|
1160
|
+
async checkUserIdIsUnique(id) {
|
|
1161
|
+
if (!id)
|
|
1162
|
+
return;
|
|
1163
|
+
const existingUser = await this.userRepository.getById(id);
|
|
1164
|
+
if (existingUser) {
|
|
1165
|
+
throw new Error(t("users.errors.idExists"));
|
|
1166
|
+
}
|
|
1212
1167
|
}
|
|
1213
|
-
async
|
|
1214
|
-
|
|
1215
|
-
if (!permissions || !Array.isArray(permissions)) return null;
|
|
1216
|
-
return permissions;
|
|
1168
|
+
async isCorrectPass(password) {
|
|
1169
|
+
return password && typeof password === "string" && password.trim().length > 0;
|
|
1217
1170
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
const [requiredAction, requiredResource] = requiredPermission.split(":");
|
|
1223
|
-
if (requiredAction && requiredResource) {
|
|
1224
|
-
if (permissions.includes(`${requiredAction}:*`)) {
|
|
1225
|
-
return true;
|
|
1226
|
-
}
|
|
1227
|
-
if (permissions.includes(`*:${requiredResource}`)) {
|
|
1228
|
-
return true;
|
|
1229
|
-
}
|
|
1171
|
+
async hasRole(userId, roles) {
|
|
1172
|
+
const roleName = await this.userRepository.getRoleNameById(userId);
|
|
1173
|
+
if (!roleName) {
|
|
1174
|
+
throw Error(t("auth.errors.accessDenied"));
|
|
1230
1175
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1176
|
+
const hasRole = roles.some((item) => roleName.toLowerCase() === item.toLowerCase());
|
|
1177
|
+
if (!hasRole) {
|
|
1178
|
+
throw Error(t("auth.errors.accessDenied"));
|
|
1233
1179
|
}
|
|
1234
|
-
return
|
|
1235
|
-
}
|
|
1236
|
-
async hasPermission(auth, ctx, requiredPermission) {
|
|
1237
|
-
await this.tokenService.storeUserInCache(auth, ctx);
|
|
1238
|
-
const permissions = await this.getUserPermissions(auth);
|
|
1239
|
-
if (!permissions) return false;
|
|
1240
|
-
const check = this.checkPermissionMatch(permissions, requiredPermission);
|
|
1241
|
-
return check;
|
|
1242
|
-
}
|
|
1243
|
-
};
|
|
1244
|
-
__decorateClass([
|
|
1245
|
-
__decorateParam(0, Headers2("authorization")),
|
|
1246
|
-
__decorateParam(1, Ctx2()),
|
|
1247
|
-
__decorateParam(2, GuardParams2())
|
|
1248
|
-
], PermissionGuards.prototype, "hasPermission", 1);
|
|
1249
|
-
PermissionGuards = __decorateClass([
|
|
1250
|
-
Injectable5()
|
|
1251
|
-
], PermissionGuards);
|
|
1252
|
-
var Permission = (...permissions) => createGuard2(PermissionGuards, "hasPermission")(...permissions);
|
|
1253
|
-
|
|
1254
|
-
// src/permissions/PermissionController.ts
|
|
1255
|
-
import { Controller as Controller2, Get as Get2, Post as Post2, Put, Delete, Params as Params2, Body as Body2, t as t3 } from "najm-api";
|
|
1256
|
-
var PermissionController = class {
|
|
1257
|
-
constructor(permissionService) {
|
|
1258
|
-
this.permissionService = permissionService;
|
|
1259
|
-
}
|
|
1260
|
-
async getPermissions() {
|
|
1261
|
-
const permissions = await this.permissionService.getAll();
|
|
1262
|
-
return {
|
|
1263
|
-
data: permissions,
|
|
1264
|
-
message: t3("permissions.success.retrieved"),
|
|
1265
|
-
status: "success"
|
|
1266
|
-
};
|
|
1267
|
-
}
|
|
1268
|
-
async getPermission(id) {
|
|
1269
|
-
const permission = await this.permissionService.getById(id);
|
|
1270
|
-
return {
|
|
1271
|
-
data: permission,
|
|
1272
|
-
message: t3("permissions.success.retrieved"),
|
|
1273
|
-
status: "success"
|
|
1274
|
-
};
|
|
1275
|
-
}
|
|
1276
|
-
async create(body) {
|
|
1277
|
-
const newPermission = await this.permissionService.create(body);
|
|
1278
|
-
return {
|
|
1279
|
-
data: newPermission,
|
|
1280
|
-
message: t3("permissions.success.created"),
|
|
1281
|
-
status: "success"
|
|
1282
|
-
};
|
|
1283
|
-
}
|
|
1284
|
-
async update(id, body) {
|
|
1285
|
-
const updatedPermission = await this.permissionService.update(id, body);
|
|
1286
|
-
return {
|
|
1287
|
-
data: updatedPermission,
|
|
1288
|
-
message: t3("permissions.success.updated"),
|
|
1289
|
-
status: "success"
|
|
1290
|
-
};
|
|
1291
|
-
}
|
|
1292
|
-
async delete(id) {
|
|
1293
|
-
const result = await this.permissionService.delete(id);
|
|
1294
|
-
return {
|
|
1295
|
-
data: result,
|
|
1296
|
-
message: t3("permissions.success.deleted"),
|
|
1297
|
-
status: "success"
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1300
|
-
async getByRole(roleId) {
|
|
1301
|
-
const permissions = await this.permissionService.getPermissionsByRole(roleId);
|
|
1302
|
-
return {
|
|
1303
|
-
data: permissions,
|
|
1304
|
-
message: t3("permissions.success.retrieved"),
|
|
1305
|
-
status: "success"
|
|
1306
|
-
};
|
|
1180
|
+
return true;
|
|
1307
1181
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1182
|
+
//======================= throw errors
|
|
1183
|
+
async checkUserExistsByEmail(email) {
|
|
1184
|
+
const user = await this.userRepository.getByEmail(email);
|
|
1185
|
+
if (!user) {
|
|
1186
|
+
throw new Error(t("auth.errors.invalidCredentials"));
|
|
1187
|
+
}
|
|
1188
|
+
return user;
|
|
1315
1189
|
}
|
|
1316
|
-
async
|
|
1317
|
-
const
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
};
|
|
1190
|
+
async checkUserExists(id) {
|
|
1191
|
+
const userExists = await this.isUserExist(id);
|
|
1192
|
+
if (!userExists) {
|
|
1193
|
+
throw new Error(t("users.errors.notFound"));
|
|
1194
|
+
}
|
|
1195
|
+
return userExists;
|
|
1323
1196
|
}
|
|
1324
|
-
async
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
}
|
|
1197
|
+
async checkEmailUnique(email, excludeId = null) {
|
|
1198
|
+
if (!email)
|
|
1199
|
+
return;
|
|
1200
|
+
const existingUser = await this.userRepository.getByEmail(email);
|
|
1201
|
+
if (existingUser && existingUser.id !== excludeId) {
|
|
1202
|
+
throw new Error(t("auth.errors.emailExists"));
|
|
1203
|
+
}
|
|
1331
1204
|
}
|
|
1332
|
-
async
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
};
|
|
1205
|
+
async checkEmailExists(email) {
|
|
1206
|
+
const user = await this.userRepository.getByEmail(email);
|
|
1207
|
+
if (!user) {
|
|
1208
|
+
throw new Error(t("users.errors.notFound"));
|
|
1209
|
+
}
|
|
1210
|
+
return user;
|
|
1339
1211
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
Get2("/:id"),
|
|
1346
|
-
__decorateParam(0, Params2("id"))
|
|
1347
|
-
], PermissionController.prototype, "getPermission", 1);
|
|
1348
|
-
__decorateClass([
|
|
1349
|
-
Post2(),
|
|
1350
|
-
__decorateParam(0, Body2())
|
|
1351
|
-
], PermissionController.prototype, "create", 1);
|
|
1352
|
-
__decorateClass([
|
|
1353
|
-
Put("/:id"),
|
|
1354
|
-
__decorateParam(0, Params2("id")),
|
|
1355
|
-
__decorateParam(1, Body2())
|
|
1356
|
-
], PermissionController.prototype, "update", 1);
|
|
1357
|
-
__decorateClass([
|
|
1358
|
-
Delete("/:id"),
|
|
1359
|
-
__decorateParam(0, Params2("id"))
|
|
1360
|
-
], PermissionController.prototype, "delete", 1);
|
|
1361
|
-
__decorateClass([
|
|
1362
|
-
Get2("/role/:roleId"),
|
|
1363
|
-
__decorateParam(0, Params2("roleId"))
|
|
1364
|
-
], PermissionController.prototype, "getByRole", 1);
|
|
1365
|
-
__decorateClass([
|
|
1366
|
-
Get2("/roles/:permissionId"),
|
|
1367
|
-
__decorateParam(0, Params2("permissionId"))
|
|
1368
|
-
], PermissionController.prototype, "getRolesByPermission", 1);
|
|
1369
|
-
__decorateClass([
|
|
1370
|
-
Post2("/assign/:roleId/:permissionId"),
|
|
1371
|
-
__decorateParam(0, Params2("roleId")),
|
|
1372
|
-
__decorateParam(1, Params2("permissionId"))
|
|
1373
|
-
], PermissionController.prototype, "assignToRole", 1);
|
|
1374
|
-
__decorateClass([
|
|
1375
|
-
Delete("/remove/:roleId/:permissionId"),
|
|
1376
|
-
__decorateParam(0, Params2("roleId")),
|
|
1377
|
-
__decorateParam(1, Params2("permissionId"))
|
|
1378
|
-
], PermissionController.prototype, "removeFromRole", 1);
|
|
1379
|
-
__decorateClass([
|
|
1380
|
-
Delete(),
|
|
1381
|
-
isAdmin()
|
|
1382
|
-
], PermissionController.prototype, "deleteAll", 1);
|
|
1383
|
-
PermissionController = __decorateClass([
|
|
1384
|
-
Controller2("/permissions"),
|
|
1385
|
-
isAdmin()
|
|
1386
|
-
], PermissionController);
|
|
1387
|
-
|
|
1388
|
-
// src/permissions/PermissionService.ts
|
|
1389
|
-
import { Injectable as Injectable6 } from "najm-api";
|
|
1390
|
-
var PermissionService = class {
|
|
1391
|
-
constructor(permissionRepository, permissionValidator, roleService) {
|
|
1392
|
-
this.permissionRepository = permissionRepository;
|
|
1393
|
-
this.permissionValidator = permissionValidator;
|
|
1394
|
-
this.roleService = roleService;
|
|
1212
|
+
async checkPasswordValid(password, hashedPassword) {
|
|
1213
|
+
const isPasswordValid = await this.isPasswordValid(password, hashedPassword);
|
|
1214
|
+
if (!isPasswordValid) {
|
|
1215
|
+
throw new Error(t("auth.errors.invalidCredentials"));
|
|
1216
|
+
}
|
|
1395
1217
|
}
|
|
1218
|
+
}, __name(_a5, "UserValidator"), _a5);
|
|
1219
|
+
UserValidator = __decorate4([
|
|
1220
|
+
Injectable3(),
|
|
1221
|
+
__metadata2("design:paramtypes", [typeof (_a4 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _a4 : Object, typeof (_b = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b : Object])
|
|
1222
|
+
], UserValidator);
|
|
1223
|
+
|
|
1224
|
+
// src/users/UserService.ts
|
|
1225
|
+
import { Injectable as Injectable8, setLanguage, getCurrentLanguage, Transactional } from "najm-api";
|
|
1226
|
+
|
|
1227
|
+
// src/roles/RoleRepository.ts
|
|
1228
|
+
import { eq as eq2 } from "drizzle-orm";
|
|
1229
|
+
import { Repository as Repository2 } from "najm-api";
|
|
1230
|
+
var __decorate5 = function(decorators, target, key, desc) {
|
|
1231
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1232
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1233
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1234
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1235
|
+
};
|
|
1236
|
+
var _a6;
|
|
1237
|
+
var RoleRepository = (_a6 = class {
|
|
1396
1238
|
async getAll() {
|
|
1397
|
-
return await this.
|
|
1239
|
+
return await this.db.select().from(rolesTable);
|
|
1398
1240
|
}
|
|
1399
1241
|
async getById(id) {
|
|
1400
|
-
await this.
|
|
1401
|
-
return
|
|
1242
|
+
const [existingRole] = await this.db.select().from(rolesTable).where(eq2(rolesTable.id, id));
|
|
1243
|
+
return existingRole;
|
|
1402
1244
|
}
|
|
1403
1245
|
async getByName(name) {
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
async getByResource(resource) {
|
|
1407
|
-
return await this.permissionRepository.getAll().then(
|
|
1408
|
-
(permissions) => permissions.filter((p) => p.resource === resource)
|
|
1409
|
-
);
|
|
1246
|
+
const [existingRole] = await this.db.select().from(rolesTable).where(eq2(rolesTable.name, name));
|
|
1247
|
+
return existingRole;
|
|
1410
1248
|
}
|
|
1411
1249
|
async create(data) {
|
|
1412
|
-
await this.
|
|
1413
|
-
|
|
1414
|
-
return await this.permissionRepository.create(data);
|
|
1250
|
+
const [newRole] = await this.db.insert(rolesTable).values(data).returning();
|
|
1251
|
+
return newRole;
|
|
1415
1252
|
}
|
|
1416
1253
|
async update(id, data) {
|
|
1417
|
-
await this.
|
|
1418
|
-
|
|
1419
|
-
return await this.permissionRepository.update(id, data);
|
|
1254
|
+
const [updatedRole] = await this.db.update(rolesTable).set(data).where(eq2(rolesTable.id, id)).returning();
|
|
1255
|
+
return updatedRole;
|
|
1420
1256
|
}
|
|
1421
1257
|
async delete(id) {
|
|
1422
|
-
await this.
|
|
1423
|
-
return
|
|
1258
|
+
const [deletedRole] = await this.db.delete(rolesTable).where(eq2(rolesTable.id, id)).returning();
|
|
1259
|
+
return deletedRole;
|
|
1424
1260
|
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1261
|
+
}, __name(_a6, "RoleRepository"), _a6);
|
|
1262
|
+
RoleRepository = __decorate5([
|
|
1263
|
+
Repository2()
|
|
1264
|
+
], RoleRepository);
|
|
1265
|
+
|
|
1266
|
+
// src/roles/RoleValidator.ts
|
|
1267
|
+
import { Injectable as Injectable4, t as t2 } from "najm-api";
|
|
1268
|
+
var __decorate6 = function(decorators, target, key, desc) {
|
|
1269
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1270
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1271
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1272
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1273
|
+
};
|
|
1274
|
+
var __metadata3 = function(k, v) {
|
|
1275
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1276
|
+
};
|
|
1277
|
+
var _a7;
|
|
1278
|
+
var _a8;
|
|
1279
|
+
var RoleValidator = (_a8 = class {
|
|
1280
|
+
constructor(roleRepository) {
|
|
1281
|
+
this.roleRepository = roleRepository;
|
|
1427
1282
|
}
|
|
1428
|
-
async
|
|
1429
|
-
|
|
1430
|
-
return await this.permissionRepository.getRolesByPermission(permissionId);
|
|
1283
|
+
async validateCreateRole(data) {
|
|
1284
|
+
return parseSchema(roleSchema, data);
|
|
1431
1285
|
}
|
|
1432
|
-
async
|
|
1433
|
-
await this.
|
|
1434
|
-
return
|
|
1286
|
+
async isRoleNameExists(roleName) {
|
|
1287
|
+
const existingRole = await this.roleRepository.getByName(roleName);
|
|
1288
|
+
return !!existingRole;
|
|
1435
1289
|
}
|
|
1436
|
-
async
|
|
1437
|
-
|
|
1290
|
+
async isRoleIdExists(id) {
|
|
1291
|
+
const existingRole = await this.roleRepository.getById(id);
|
|
1292
|
+
return !!existingRole;
|
|
1438
1293
|
}
|
|
1439
|
-
async
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
} catch (error) {
|
|
1446
|
-
continue;
|
|
1447
|
-
}
|
|
1294
|
+
async checkNameUnique(roleName, excludeId = null) {
|
|
1295
|
+
if (!roleName)
|
|
1296
|
+
return;
|
|
1297
|
+
const existingRole = await this.roleRepository.getByName(roleName);
|
|
1298
|
+
if (existingRole && existingRole.id !== excludeId) {
|
|
1299
|
+
throw new Error(t2("roles.errors.exists"));
|
|
1448
1300
|
}
|
|
1449
|
-
return createdPermissions;
|
|
1450
1301
|
}
|
|
1451
|
-
async
|
|
1452
|
-
const
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
await this.permissionValidator.checkRoleExistsByName(roleName);
|
|
1456
|
-
const role = await this.roleService.getByName(roleName);
|
|
1457
|
-
for (const permissionName of permissions) {
|
|
1458
|
-
try {
|
|
1459
|
-
await this.permissionValidator.checkPermissionExistsByName(permissionName);
|
|
1460
|
-
const permission = await this.getByName(permissionName);
|
|
1461
|
-
await this.permissionValidator.checkRoleHasPermission(role.id, permission.id);
|
|
1462
|
-
await this.assignPermissionToRole(role.id, permission.id);
|
|
1463
|
-
results.push({ role: roleName, permission: permissionName });
|
|
1464
|
-
} catch (error) {
|
|
1465
|
-
continue;
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
} catch (error) {
|
|
1469
|
-
continue;
|
|
1470
|
-
}
|
|
1302
|
+
async checkRoleExists(id) {
|
|
1303
|
+
const roleIdExists = await this.isRoleIdExists(id);
|
|
1304
|
+
if (!roleIdExists) {
|
|
1305
|
+
throw new Error(t2("roles.errors.notFound"));
|
|
1471
1306
|
}
|
|
1472
|
-
return results;
|
|
1473
1307
|
}
|
|
1474
|
-
async
|
|
1475
|
-
|
|
1308
|
+
async checkRoleExistsByName(roleName) {
|
|
1309
|
+
const roleNameExists = await this.isRoleNameExists(roleName);
|
|
1310
|
+
if (!roleNameExists) {
|
|
1311
|
+
throw new Error(t2("roles.errors.notFound"));
|
|
1312
|
+
}
|
|
1476
1313
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1314
|
+
async checkAdminRoleExists() {
|
|
1315
|
+
const adminRole = await this.roleRepository.getByName("admin");
|
|
1316
|
+
if (!adminRole) {
|
|
1317
|
+
throw new Error(t2("users.errors.adminRoleNotFound"));
|
|
1318
|
+
}
|
|
1319
|
+
return adminRole;
|
|
1320
|
+
}
|
|
1321
|
+
}, __name(_a8, "RoleValidator"), _a8);
|
|
1322
|
+
RoleValidator = __decorate6([
|
|
1323
|
+
Injectable4(),
|
|
1324
|
+
__metadata3("design:paramtypes", [typeof (_a7 = typeof RoleRepository !== "undefined" && RoleRepository) === "function" ? _a7 : Object])
|
|
1325
|
+
], RoleValidator);
|
|
1481
1326
|
|
|
1482
|
-
// src/
|
|
1483
|
-
import { Injectable as
|
|
1327
|
+
// src/roles/RoleGuards.ts
|
|
1328
|
+
import { Injectable as Injectable6, Headers, createGuard, GuardParams, Ctx } from "najm-api";
|
|
1484
1329
|
|
|
1485
|
-
// src/
|
|
1486
|
-
import
|
|
1487
|
-
import
|
|
1488
|
-
|
|
1489
|
-
var
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
} catch (error) {
|
|
1494
|
-
const errors = error.issues || error.errors || [];
|
|
1495
|
-
const errorMessage = errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
|
|
1496
|
-
throw new Error(errorMessage);
|
|
1497
|
-
}
|
|
1330
|
+
// src/tokens/TokenRepository.ts
|
|
1331
|
+
import { eq as eq3 } from "drizzle-orm";
|
|
1332
|
+
import { Repository as Repository3 } from "najm-api";
|
|
1333
|
+
var __decorate7 = function(decorators, target, key, desc) {
|
|
1334
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1335
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1336
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1337
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1498
1338
|
};
|
|
1499
|
-
var
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1339
|
+
var _a9;
|
|
1340
|
+
var TokenRepository = (_a9 = class {
|
|
1341
|
+
async storeRefreshToken(tokenData) {
|
|
1342
|
+
return await this.db.insert(tokensTable).values(tokenData).onConflictDoUpdate({
|
|
1343
|
+
target: tokensTable.userId,
|
|
1344
|
+
set: {
|
|
1345
|
+
token: tokenData.token,
|
|
1346
|
+
expiresAt: tokenData.expiresAt
|
|
1347
|
+
}
|
|
1348
|
+
}).returning();
|
|
1505
1349
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
try {
|
|
1510
|
-
const filePath = path.join(avatarsPath, fileName);
|
|
1511
|
-
const buffer = await fs.readFile(filePath);
|
|
1512
|
-
const file = new File([buffer], fileName, {
|
|
1513
|
-
type: "image/png"
|
|
1514
|
-
});
|
|
1515
|
-
return file;
|
|
1516
|
-
} catch (error) {
|
|
1517
|
-
return null;
|
|
1350
|
+
async getRefreshToken(userId) {
|
|
1351
|
+
const [token] = await this.db.select().from(tokensTable).where(eq3(tokensTable.userId, userId));
|
|
1352
|
+
return token?.token;
|
|
1518
1353
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
let date;
|
|
1523
|
-
if (dateValue instanceof Date) {
|
|
1524
|
-
date = dateValue;
|
|
1525
|
-
} else if (typeof dateValue === "string") {
|
|
1526
|
-
date = new Date(dateValue);
|
|
1527
|
-
} else {
|
|
1528
|
-
return null;
|
|
1354
|
+
async revokeToken(userId) {
|
|
1355
|
+
const [deletedToken] = await this.db.delete(tokensTable).where(eq3(tokensTable.userId, userId)).returning();
|
|
1356
|
+
return deletedToken;
|
|
1529
1357
|
}
|
|
1530
|
-
|
|
1531
|
-
|
|
1358
|
+
async isUserExists(userId) {
|
|
1359
|
+
const [user] = await this.db.select({ id: usersTable.id }).from(usersTable).where(eq3(usersTable.id, userId)).limit(1);
|
|
1360
|
+
return !!user;
|
|
1361
|
+
}
|
|
1362
|
+
async getRoleNameById(userId) {
|
|
1363
|
+
const [role] = await this.db.select({
|
|
1364
|
+
roleName: rolesTable.name
|
|
1365
|
+
}).from(usersTable).leftJoin(rolesTable, eq3(usersTable.roleId, rolesTable.id)).where(eq3(usersTable.id, userId)).limit(1);
|
|
1366
|
+
return role?.roleName;
|
|
1367
|
+
}
|
|
1368
|
+
async getUserPermissions(userId) {
|
|
1369
|
+
const [user] = await this.db.select({ roleId: usersTable.roleId }).from(usersTable).where(eq3(usersTable.id, userId)).limit(1);
|
|
1370
|
+
if (!user || !user.roleId)
|
|
1371
|
+
return [];
|
|
1372
|
+
const userPermissions = await this.db.select({
|
|
1373
|
+
name: permissionsTable.name
|
|
1374
|
+
}).from(rolePermissionsTable).leftJoin(permissionsTable, eq3(rolePermissionsTable.permissionId, permissionsTable.id)).where(eq3(rolePermissionsTable.roleId, user.roleId));
|
|
1375
|
+
return userPermissions.map((p) => p.name).filter((name) => name);
|
|
1376
|
+
}
|
|
1377
|
+
async getUser(userId) {
|
|
1378
|
+
const [user] = await this.db.select({
|
|
1379
|
+
id: usersTable.id,
|
|
1380
|
+
email: usersTable.email,
|
|
1381
|
+
status: usersTable.status,
|
|
1382
|
+
roleId: usersTable.roleId,
|
|
1383
|
+
roleName: rolesTable.name,
|
|
1384
|
+
createdAt: usersTable.createdAt,
|
|
1385
|
+
updatedAt: usersTable.updatedAt
|
|
1386
|
+
}).from(usersTable).leftJoin(rolesTable, eq3(usersTable.roleId, rolesTable.id)).where(eq3(usersTable.id, userId)).limit(1);
|
|
1387
|
+
return user ? { ...user, role: user.roleName } : null;
|
|
1388
|
+
}
|
|
1389
|
+
}, __name(_a9, "TokenRepository"), _a9);
|
|
1390
|
+
TokenRepository = __decorate7([
|
|
1391
|
+
Repository3()
|
|
1392
|
+
], TokenRepository);
|
|
1393
|
+
|
|
1394
|
+
// src/tokens/TokenService.ts
|
|
1395
|
+
import { t as t3 } from "najm-api";
|
|
1396
|
+
import { getCookie, Injectable as Injectable5 } from "najm-api";
|
|
1397
|
+
import jwt from "jsonwebtoken";
|
|
1398
|
+
import { jwtDecode } from "jwt-decode";
|
|
1399
|
+
import timestring2 from "timestring";
|
|
1400
|
+
var __decorate8 = function(decorators, target, key, desc) {
|
|
1401
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1402
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1403
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1404
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1405
|
+
};
|
|
1406
|
+
var __metadata4 = function(k, v) {
|
|
1407
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1532
1408
|
};
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
age--;
|
|
1409
|
+
var _a10;
|
|
1410
|
+
var _a11;
|
|
1411
|
+
var TokenService = (_a11 = class {
|
|
1412
|
+
constructor(tokenRepository) {
|
|
1413
|
+
this.tokenRepository = tokenRepository;
|
|
1414
|
+
this.accessSecretKey = process.env.JWT_ACCESS_SECRET;
|
|
1415
|
+
this.accessExpiresIn = process.env.ACCESS_EXPIRES_IN;
|
|
1416
|
+
this.refreshSecretKey = process.env.JWT_REFRESH_SECRET;
|
|
1417
|
+
this.refreshExpiresIn = process.env.REFRESH_EXPIRES_IN;
|
|
1543
1418
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
const hire = new Date(formattedDate);
|
|
1551
|
-
const today = /* @__PURE__ */ new Date();
|
|
1552
|
-
let years = today.getFullYear() - hire.getFullYear();
|
|
1553
|
-
const monthDiff = today.getMonth() - hire.getMonth();
|
|
1554
|
-
if (monthDiff < 0 || monthDiff === 0 && today.getDate() < hire.getDate()) {
|
|
1555
|
-
years--;
|
|
1419
|
+
//==== Validate tokens
|
|
1420
|
+
extractAccessToken(authorization) {
|
|
1421
|
+
if (authorization && authorization.startsWith("Bearer")) {
|
|
1422
|
+
return authorization.split(" ")[1];
|
|
1423
|
+
}
|
|
1424
|
+
throw new Error(t3("auth.errors.tokenMissing"));
|
|
1556
1425
|
}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
if (source[key] !== void 0) {
|
|
1563
|
-
result[key] = source[key];
|
|
1426
|
+
verifyAccessToken(token) {
|
|
1427
|
+
try {
|
|
1428
|
+
return jwt.verify(token, this.accessSecretKey);
|
|
1429
|
+
} catch (error) {
|
|
1430
|
+
throw new Error(t3("auth.errors.tokenVerificationFailed"));
|
|
1564
1431
|
}
|
|
1565
1432
|
}
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
import { z as z3 } from "zod";
|
|
1574
|
-
var permissionSchema = z3.object({
|
|
1575
|
-
name: z3.string().min(1, "Permission name is required"),
|
|
1576
|
-
description: z3.string().optional(),
|
|
1577
|
-
resource: z3.string().min(1, "Resource is required"),
|
|
1578
|
-
action: z3.string().min(1, "Action is required")
|
|
1579
|
-
});
|
|
1580
|
-
var PermissionValidator = class {
|
|
1581
|
-
constructor(permissionRepository, roleValidator) {
|
|
1582
|
-
this.permissionRepository = permissionRepository;
|
|
1583
|
-
this.roleValidator = roleValidator;
|
|
1433
|
+
verifyRefreshToken(token) {
|
|
1434
|
+
try {
|
|
1435
|
+
const decoded = jwt.verify(token, this.refreshSecretKey);
|
|
1436
|
+
return decoded.userId;
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
throw new Error(t3("auth.errors.tokenVerificationFailed"));
|
|
1439
|
+
}
|
|
1584
1440
|
}
|
|
1585
|
-
async
|
|
1586
|
-
|
|
1441
|
+
async getUserIdByAccessToken(header) {
|
|
1442
|
+
const token = this.extractAccessToken(header);
|
|
1443
|
+
const decodedToken = this.verifyAccessToken(token);
|
|
1444
|
+
const userId = decodedToken.userId;
|
|
1445
|
+
const userExists = await this.tokenRepository.isUserExists(userId);
|
|
1446
|
+
if (!userExists) {
|
|
1447
|
+
throw new Error(t3("users.errors.notFound"));
|
|
1448
|
+
}
|
|
1449
|
+
return userId;
|
|
1587
1450
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1451
|
+
//=== Generate tokens
|
|
1452
|
+
async storeRefreshToken(userId, refreshToken) {
|
|
1453
|
+
const expireInSecond = timestring2(this.refreshExpiresIn, "s");
|
|
1454
|
+
const tokenData = {
|
|
1455
|
+
userId,
|
|
1456
|
+
token: refreshToken,
|
|
1457
|
+
expiresAt: new Date(Date.now() + expireInSecond * 1e3).toISOString()
|
|
1458
|
+
};
|
|
1459
|
+
await this.tokenRepository.storeRefreshToken(tokenData);
|
|
1591
1460
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
return !!existingPermission;
|
|
1461
|
+
getTokenExpire(token) {
|
|
1462
|
+
return jwtDecode(token).exp;
|
|
1595
1463
|
}
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
if (!permissionExists) {
|
|
1600
|
-
throw new Error(t4("permissions.errors.notFound"));
|
|
1601
|
-
}
|
|
1602
|
-
return permissionExists;
|
|
1464
|
+
generateAccessToken(data) {
|
|
1465
|
+
const options = { expiresIn: this.accessExpiresIn };
|
|
1466
|
+
return jwt.sign(data, this.accessSecretKey, options);
|
|
1603
1467
|
}
|
|
1604
|
-
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
throw new Error(t4("permissions.errors.notFound"));
|
|
1608
|
-
}
|
|
1609
|
-
return permissionExists;
|
|
1468
|
+
generateRefreshToken(data) {
|
|
1469
|
+
const options = { expiresIn: this.refreshExpiresIn };
|
|
1470
|
+
return jwt.sign(data, this.refreshSecretKey, options);
|
|
1610
1471
|
}
|
|
1611
|
-
async
|
|
1612
|
-
|
|
1613
|
-
const
|
|
1614
|
-
|
|
1615
|
-
|
|
1472
|
+
async generateTokens(userId) {
|
|
1473
|
+
const tokenData = { userId };
|
|
1474
|
+
const accessToken = await this.generateAccessToken(tokenData);
|
|
1475
|
+
const refreshToken = await this.generateRefreshToken(tokenData);
|
|
1476
|
+
const accessTokenExpiresAt = this.getTokenExpire(accessToken);
|
|
1477
|
+
const refreshTokenExpiresAt = this.getTokenExpire(refreshToken);
|
|
1478
|
+
await this.storeRefreshToken(userId, refreshToken);
|
|
1479
|
+
return {
|
|
1480
|
+
accessToken,
|
|
1481
|
+
refreshToken,
|
|
1482
|
+
accessTokenExpiresAt,
|
|
1483
|
+
refreshTokenExpiresAt
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
async refreshTokens() {
|
|
1487
|
+
const newRefreshToken = getCookie("refreshToken");
|
|
1488
|
+
const userId = this.verifyRefreshToken(newRefreshToken);
|
|
1489
|
+
const userExists = await this.tokenRepository.isUserExists(userId);
|
|
1490
|
+
if (!userExists) {
|
|
1491
|
+
throw new Error(t3("users.errors.notFound"));
|
|
1492
|
+
}
|
|
1493
|
+
const storedRefreshToken = await this.tokenRepository.getRefreshToken(userId);
|
|
1494
|
+
if (newRefreshToken != storedRefreshToken) {
|
|
1495
|
+
throw new Error(t3("auth.errors.refreshTokenInvalid"));
|
|
1616
1496
|
}
|
|
1497
|
+
return await this.generateTokens(userId);
|
|
1617
1498
|
}
|
|
1618
|
-
async
|
|
1619
|
-
return await this.
|
|
1499
|
+
async revokeToken(userId) {
|
|
1500
|
+
return await this.tokenRepository.revokeToken(userId);
|
|
1620
1501
|
}
|
|
1621
|
-
async
|
|
1622
|
-
|
|
1502
|
+
async getUserPermissions(auth) {
|
|
1503
|
+
if (!auth)
|
|
1504
|
+
return;
|
|
1505
|
+
const userId = await this.getUserIdByAccessToken(auth);
|
|
1506
|
+
const permissions = await this.tokenRepository.getUserPermissions(userId);
|
|
1507
|
+
return permissions;
|
|
1623
1508
|
}
|
|
1624
|
-
async
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1509
|
+
async getUserRole(auth) {
|
|
1510
|
+
if (!auth)
|
|
1511
|
+
return;
|
|
1512
|
+
const userId = await this.getUserIdByAccessToken(auth);
|
|
1513
|
+
const roleName = await this.tokenRepository.getRoleNameById(userId);
|
|
1514
|
+
return roleName;
|
|
1515
|
+
}
|
|
1516
|
+
async getUser(auth) {
|
|
1517
|
+
if (!auth)
|
|
1518
|
+
return;
|
|
1519
|
+
const userId = await this.getUserIdByAccessToken(auth);
|
|
1520
|
+
const user = await this.tokenRepository.getUser(userId);
|
|
1521
|
+
if (!user)
|
|
1522
|
+
return null;
|
|
1523
|
+
return user;
|
|
1524
|
+
}
|
|
1525
|
+
async storeUserInCache(auth, ctx) {
|
|
1526
|
+
const cachedUser = ctx.get("user");
|
|
1527
|
+
if (cachedUser)
|
|
1528
|
+
return cachedUser;
|
|
1529
|
+
const user = await this.getUser(auth);
|
|
1530
|
+
if (user) {
|
|
1531
|
+
ctx.set("user", user);
|
|
1630
1532
|
}
|
|
1533
|
+
return user;
|
|
1631
1534
|
}
|
|
1632
|
-
};
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1535
|
+
}, __name(_a11, "TokenService"), _a11);
|
|
1536
|
+
TokenService = __decorate8([
|
|
1537
|
+
Injectable5(),
|
|
1538
|
+
__metadata4("design:paramtypes", [typeof (_a10 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _a10 : Object])
|
|
1539
|
+
], TokenService);
|
|
1636
1540
|
|
|
1637
|
-
// src/roles/
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1541
|
+
// src/roles/RoleGuards.ts
|
|
1542
|
+
var __decorate9 = function(decorators, target, key, desc) {
|
|
1543
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1544
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1545
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1546
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1547
|
+
};
|
|
1548
|
+
var __metadata5 = function(k, v) {
|
|
1549
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1550
|
+
};
|
|
1551
|
+
var __param = function(paramIndex, decorator) {
|
|
1552
|
+
return function(target, key) {
|
|
1553
|
+
decorator(target, key, paramIndex);
|
|
1554
|
+
};
|
|
1555
|
+
};
|
|
1556
|
+
var _a12;
|
|
1557
|
+
var ROLES = {
|
|
1558
|
+
ADMIN: "admin",
|
|
1559
|
+
PRINCIPAL: "principal",
|
|
1560
|
+
ACCOUNTING: "accounting",
|
|
1561
|
+
SECRETARY: "secretary",
|
|
1562
|
+
TEACHER: "teacher",
|
|
1563
|
+
STUDENT: "student",
|
|
1564
|
+
PARENT: "parent"
|
|
1565
|
+
};
|
|
1566
|
+
var ROLE_GROUPS = {
|
|
1567
|
+
ADMINISTRATORS: [ROLES.ADMIN, ROLES.PRINCIPAL],
|
|
1568
|
+
FINANCIAL: [ROLES.ADMIN, ROLES.ACCOUNTING],
|
|
1569
|
+
STAFF: [ROLES.ADMIN, ROLES.PRINCIPAL, ROLES.ACCOUNTING, ROLES.SECRETARY, ROLES.TEACHER],
|
|
1570
|
+
END_USERS: [ROLES.STUDENT, ROLES.PARENT],
|
|
1571
|
+
ALL: [ROLES.ADMIN, ROLES.PRINCIPAL, ROLES.ACCOUNTING, ROLES.SECRETARY, ROLES.TEACHER, ROLES.STUDENT, ROLES.PARENT]
|
|
1572
|
+
};
|
|
1573
|
+
var _a13;
|
|
1574
|
+
var RoleChecker = (_a13 = class {
|
|
1575
|
+
isInGroup(userRole, group) {
|
|
1576
|
+
return group.includes(userRole?.toLowerCase());
|
|
1643
1577
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
return existingRole;
|
|
1578
|
+
isAdministrator(userRole) {
|
|
1579
|
+
return this.isInGroup(userRole, ROLE_GROUPS.ADMINISTRATORS);
|
|
1647
1580
|
}
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
return existingRole;
|
|
1581
|
+
isStaff(userRole) {
|
|
1582
|
+
return this.isInGroup(userRole, ROLE_GROUPS.STAFF);
|
|
1651
1583
|
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
return newRole;
|
|
1584
|
+
hasAnyRole(userRole, roles) {
|
|
1585
|
+
return roles.includes(userRole?.toLowerCase());
|
|
1655
1586
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
return updatedRole;
|
|
1587
|
+
hasExactRole(userRole, requiredRole) {
|
|
1588
|
+
return userRole?.toLowerCase() === requiredRole?.toLowerCase();
|
|
1659
1589
|
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1590
|
+
}, __name(_a13, "RoleChecker"), _a13);
|
|
1591
|
+
RoleChecker = __decorate9([
|
|
1592
|
+
Injectable6()
|
|
1593
|
+
], RoleChecker);
|
|
1594
|
+
var _a14;
|
|
1595
|
+
var RoleGuards = (_a14 = class {
|
|
1596
|
+
constructor(roleChecker, tokenService) {
|
|
1597
|
+
this.roleChecker = roleChecker;
|
|
1598
|
+
this.tokenService = tokenService;
|
|
1663
1599
|
}
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1600
|
+
async isAuth(auth, ctx) {
|
|
1601
|
+
const user = await this.tokenService.storeUserInCache(auth, ctx);
|
|
1602
|
+
return !!user;
|
|
1603
|
+
}
|
|
1604
|
+
async hasRoles(auth, ctx, roles) {
|
|
1605
|
+
try {
|
|
1606
|
+
const user = await this.tokenService.storeUserInCache(auth, ctx);
|
|
1607
|
+
if (!user?.role)
|
|
1608
|
+
return false;
|
|
1609
|
+
const roleArray = Array.isArray(roles) ? roles : [roles];
|
|
1610
|
+
return this.roleChecker.hasAnyRole(user.role, roleArray);
|
|
1611
|
+
} catch {
|
|
1612
|
+
return false;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}, __name(_a14, "RoleGuards"), _a14);
|
|
1616
|
+
__decorate9([
|
|
1617
|
+
__param(0, Headers("authorization")),
|
|
1618
|
+
__param(1, Ctx()),
|
|
1619
|
+
__metadata5("design:type", Function),
|
|
1620
|
+
__metadata5("design:paramtypes", [Object, Object]),
|
|
1621
|
+
__metadata5("design:returntype", Promise)
|
|
1622
|
+
], RoleGuards.prototype, "isAuth", null);
|
|
1623
|
+
__decorate9([
|
|
1624
|
+
__param(0, Headers("authorization")),
|
|
1625
|
+
__param(1, Ctx()),
|
|
1626
|
+
__param(2, GuardParams()),
|
|
1627
|
+
__metadata5("design:type", Function),
|
|
1628
|
+
__metadata5("design:paramtypes", [Object, Object, Object]),
|
|
1629
|
+
__metadata5("design:returntype", Promise)
|
|
1630
|
+
], RoleGuards.prototype, "hasRoles", null);
|
|
1631
|
+
RoleGuards = __decorate9([
|
|
1632
|
+
Injectable6(),
|
|
1633
|
+
__metadata5("design:paramtypes", [RoleChecker, typeof (_a12 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a12 : Object])
|
|
1634
|
+
], RoleGuards);
|
|
1635
|
+
var isAdmin = /* @__PURE__ */ __name(() => Role("admin"), "isAdmin");
|
|
1636
|
+
var isPrincipal = /* @__PURE__ */ __name(() => Role("principal"), "isPrincipal");
|
|
1637
|
+
var isAccounting = /* @__PURE__ */ __name(() => Role("accounting"), "isAccounting");
|
|
1638
|
+
var isSecretary = /* @__PURE__ */ __name(() => Role("secretary"), "isSecretary");
|
|
1639
|
+
var isTeacher = /* @__PURE__ */ __name(() => Role("teacher"), "isTeacher");
|
|
1640
|
+
var isParent = /* @__PURE__ */ __name(() => Role("parent"), "isParent");
|
|
1641
|
+
var isStudent = /* @__PURE__ */ __name(() => Role("student"), "isStudent");
|
|
1642
|
+
var isAdministrator = /* @__PURE__ */ __name(() => Role("admin", "principal"), "isAdministrator");
|
|
1643
|
+
var isFinancial = /* @__PURE__ */ __name(() => Role("admin", "accounting"), "isFinancial");
|
|
1644
|
+
var isStaff = /* @__PURE__ */ __name(() => Role("admin", "principal", "accounting", "secretary", "teacher"), "isStaff");
|
|
1645
|
+
var isAuth = createGuard(RoleGuards, "isAuth");
|
|
1646
|
+
var Role = /* @__PURE__ */ __name((...roles) => createGuard(RoleGuards, "hasRoles")(...roles), "Role");
|
|
1668
1647
|
|
|
1669
|
-
// src/roles/
|
|
1670
|
-
import {
|
|
1671
|
-
|
|
1672
|
-
|
|
1648
|
+
// src/roles/RoleController.ts
|
|
1649
|
+
import { Controller, Get, Post, Put, Delete, Params, Body, t as t4 } from "najm-api";
|
|
1650
|
+
|
|
1651
|
+
// src/roles/RoleService.ts
|
|
1652
|
+
import { Injectable as Injectable7 } from "najm-api";
|
|
1653
|
+
var __decorate10 = function(decorators, target, key, desc) {
|
|
1654
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1655
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1656
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1657
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1658
|
+
};
|
|
1659
|
+
var __metadata6 = function(k, v) {
|
|
1660
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1661
|
+
};
|
|
1662
|
+
var _a15;
|
|
1663
|
+
var _b2;
|
|
1664
|
+
var _a16;
|
|
1665
|
+
var RoleService = (_a16 = class {
|
|
1666
|
+
constructor(roleRepository, roleValidator) {
|
|
1673
1667
|
this.roleRepository = roleRepository;
|
|
1668
|
+
this.roleValidator = roleValidator;
|
|
1674
1669
|
}
|
|
1675
|
-
async
|
|
1676
|
-
return
|
|
1670
|
+
async getAll() {
|
|
1671
|
+
return await this.roleRepository.getAll();
|
|
1672
|
+
}
|
|
1673
|
+
async getById(id) {
|
|
1674
|
+
await this.roleValidator.checkRoleExists(id);
|
|
1675
|
+
return await this.roleRepository.getById(id);
|
|
1677
1676
|
}
|
|
1678
|
-
async
|
|
1679
|
-
|
|
1680
|
-
return !!existingRole;
|
|
1677
|
+
async getByName(name) {
|
|
1678
|
+
return await this.roleRepository.getByName(name);
|
|
1681
1679
|
}
|
|
1682
|
-
async
|
|
1683
|
-
|
|
1684
|
-
|
|
1680
|
+
async create(data) {
|
|
1681
|
+
await this.roleValidator.validateCreateRole(data);
|
|
1682
|
+
await this.roleValidator.checkNameUnique(data.name);
|
|
1683
|
+
return await this.roleRepository.create(data);
|
|
1685
1684
|
}
|
|
1686
|
-
async
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
throw new Error(t5("roles.errors.exists"));
|
|
1691
|
-
}
|
|
1685
|
+
async update(id, data) {
|
|
1686
|
+
await this.roleValidator.checkRoleExists(id);
|
|
1687
|
+
await this.roleValidator.checkNameUnique(data.name, id);
|
|
1688
|
+
return await this.roleRepository.update(id, data);
|
|
1692
1689
|
}
|
|
1693
|
-
async
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
throw new Error(t5("roles.errors.notFound"));
|
|
1697
|
-
}
|
|
1690
|
+
async delete(id) {
|
|
1691
|
+
await this.roleValidator.checkRoleExists(id);
|
|
1692
|
+
return await this.roleRepository.delete(id);
|
|
1698
1693
|
}
|
|
1699
|
-
async
|
|
1700
|
-
const
|
|
1701
|
-
|
|
1702
|
-
|
|
1694
|
+
async seedDefaultRoles(defaultRoles) {
|
|
1695
|
+
const rolesToCreate = [];
|
|
1696
|
+
for (const role of defaultRoles) {
|
|
1697
|
+
const exists = await this.roleValidator.isRoleNameExists(role.name);
|
|
1698
|
+
if (!exists) {
|
|
1699
|
+
rolesToCreate.push(role);
|
|
1700
|
+
}
|
|
1703
1701
|
}
|
|
1702
|
+
const createdRoles = await Promise.all(rolesToCreate.map((role) => this.roleRepository.create(role)));
|
|
1703
|
+
return createdRoles;
|
|
1704
1704
|
}
|
|
1705
|
-
async
|
|
1706
|
-
const
|
|
1707
|
-
|
|
1708
|
-
throw new Error(t5("users.errors.adminRoleNotFound"));
|
|
1709
|
-
}
|
|
1710
|
-
return adminRole;
|
|
1705
|
+
async getRoleIdByName(name) {
|
|
1706
|
+
const teacherRole = await this.getByName(name);
|
|
1707
|
+
return teacherRole?.id;
|
|
1711
1708
|
}
|
|
1712
|
-
};
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1709
|
+
}, __name(_a16, "RoleService"), _a16);
|
|
1710
|
+
RoleService = __decorate10([
|
|
1711
|
+
Injectable7(),
|
|
1712
|
+
__metadata6("design:paramtypes", [typeof (_a15 = typeof RoleRepository !== "undefined" && RoleRepository) === "function" ? _a15 : Object, typeof (_b2 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b2 : Object])
|
|
1713
|
+
], RoleService);
|
|
1716
1714
|
|
|
1717
1715
|
// src/roles/RoleController.ts
|
|
1718
|
-
|
|
1719
|
-
var
|
|
1716
|
+
var __decorate11 = function(decorators, target, key, desc) {
|
|
1717
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1718
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1719
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1720
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1721
|
+
};
|
|
1722
|
+
var __metadata7 = function(k, v) {
|
|
1723
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1724
|
+
};
|
|
1725
|
+
var __param2 = function(paramIndex, decorator) {
|
|
1726
|
+
return function(target, key) {
|
|
1727
|
+
decorator(target, key, paramIndex);
|
|
1728
|
+
};
|
|
1729
|
+
};
|
|
1730
|
+
var _a17;
|
|
1731
|
+
var _a18;
|
|
1732
|
+
var RoleController = (_a18 = class {
|
|
1720
1733
|
constructor(roleService) {
|
|
1721
1734
|
this.roleService = roleService;
|
|
1722
1735
|
}
|
|
@@ -1724,7 +1737,7 @@ var RoleController = class {
|
|
|
1724
1737
|
const roles = await this.roleService.getAll();
|
|
1725
1738
|
return {
|
|
1726
1739
|
data: roles,
|
|
1727
|
-
message:
|
|
1740
|
+
message: t4("roles.success.retrieved"),
|
|
1728
1741
|
status: "success"
|
|
1729
1742
|
};
|
|
1730
1743
|
}
|
|
@@ -1732,7 +1745,7 @@ var RoleController = class {
|
|
|
1732
1745
|
const role = await this.roleService.getById(id);
|
|
1733
1746
|
return {
|
|
1734
1747
|
data: role,
|
|
1735
|
-
message:
|
|
1748
|
+
message: t4("roles.success.retrieved"),
|
|
1736
1749
|
status: "success"
|
|
1737
1750
|
};
|
|
1738
1751
|
}
|
|
@@ -1740,7 +1753,7 @@ var RoleController = class {
|
|
|
1740
1753
|
const newRole = await this.roleService.create(body);
|
|
1741
1754
|
return {
|
|
1742
1755
|
data: newRole,
|
|
1743
|
-
message:
|
|
1756
|
+
message: t4("roles.success.created"),
|
|
1744
1757
|
status: "success"
|
|
1745
1758
|
};
|
|
1746
1759
|
}
|
|
@@ -1748,7 +1761,7 @@ var RoleController = class {
|
|
|
1748
1761
|
const updatedRole = await this.roleService.update(id, body);
|
|
1749
1762
|
return {
|
|
1750
1763
|
data: updatedRole,
|
|
1751
|
-
message:
|
|
1764
|
+
message: t4("roles.success.updated"),
|
|
1752
1765
|
status: "success"
|
|
1753
1766
|
};
|
|
1754
1767
|
}
|
|
@@ -1756,761 +1769,1133 @@ var RoleController = class {
|
|
|
1756
1769
|
const result = await this.roleService.delete(id);
|
|
1757
1770
|
return {
|
|
1758
1771
|
data: result,
|
|
1759
|
-
message:
|
|
1772
|
+
message: t4("roles.success.deleted"),
|
|
1760
1773
|
status: "success"
|
|
1761
1774
|
};
|
|
1762
1775
|
}
|
|
1763
|
-
};
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
isAdmin()
|
|
1767
|
-
], RoleController.prototype, "getRoles", 1);
|
|
1768
|
-
__decorateClass([
|
|
1769
|
-
Get3("/:id"),
|
|
1776
|
+
}, __name(_a18, "RoleController"), _a18);
|
|
1777
|
+
__decorate11([
|
|
1778
|
+
Get(),
|
|
1770
1779
|
isAdmin(),
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1780
|
+
__metadata7("design:type", Function),
|
|
1781
|
+
__metadata7("design:paramtypes", []),
|
|
1782
|
+
__metadata7("design:returntype", Promise)
|
|
1783
|
+
], RoleController.prototype, "getRoles", null);
|
|
1784
|
+
__decorate11([
|
|
1785
|
+
Get("/:id"),
|
|
1775
1786
|
isAdmin(),
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1787
|
+
__param2(0, Params("id")),
|
|
1788
|
+
__metadata7("design:type", Function),
|
|
1789
|
+
__metadata7("design:paramtypes", [Object]),
|
|
1790
|
+
__metadata7("design:returntype", Promise)
|
|
1791
|
+
], RoleController.prototype, "getRole", null);
|
|
1792
|
+
__decorate11([
|
|
1793
|
+
Post(),
|
|
1780
1794
|
isAdmin(),
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1795
|
+
__param2(0, Body()),
|
|
1796
|
+
__metadata7("design:type", Function),
|
|
1797
|
+
__metadata7("design:paramtypes", [Object]),
|
|
1798
|
+
__metadata7("design:returntype", Promise)
|
|
1799
|
+
], RoleController.prototype, "createRole", null);
|
|
1800
|
+
__decorate11([
|
|
1801
|
+
Put("/:id"),
|
|
1802
|
+
isAdmin(),
|
|
1803
|
+
__param2(0, Params("id")),
|
|
1804
|
+
__param2(1, Body()),
|
|
1805
|
+
__metadata7("design:type", Function),
|
|
1806
|
+
__metadata7("design:paramtypes", [Object, Object]),
|
|
1807
|
+
__metadata7("design:returntype", Promise)
|
|
1808
|
+
], RoleController.prototype, "updateRole", null);
|
|
1809
|
+
__decorate11([
|
|
1810
|
+
Delete("/:id"),
|
|
1786
1811
|
isAdmin(),
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1812
|
+
__param2(0, Params("id")),
|
|
1813
|
+
__metadata7("design:type", Function),
|
|
1814
|
+
__metadata7("design:paramtypes", [Object]),
|
|
1815
|
+
__metadata7("design:returntype", Promise)
|
|
1816
|
+
], RoleController.prototype, "deleteRole", null);
|
|
1817
|
+
RoleController = __decorate11([
|
|
1818
|
+
Controller("/roles"),
|
|
1819
|
+
__metadata7("design:paramtypes", [typeof (_a17 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a17 : Object])
|
|
1791
1820
|
], RoleController);
|
|
1792
1821
|
|
|
1793
|
-
// src/
|
|
1794
|
-
import {
|
|
1795
|
-
var
|
|
1796
|
-
|
|
1797
|
-
|
|
1822
|
+
// src/users/UserService.ts
|
|
1823
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
1824
|
+
var __decorate12 = function(decorators, target, key, desc) {
|
|
1825
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1826
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1827
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1828
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1829
|
+
};
|
|
1830
|
+
var __metadata8 = function(k, v) {
|
|
1831
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1832
|
+
};
|
|
1833
|
+
var _a19;
|
|
1834
|
+
var _b3;
|
|
1835
|
+
var _c;
|
|
1836
|
+
var _d;
|
|
1837
|
+
var _e;
|
|
1838
|
+
var _a20;
|
|
1839
|
+
var UserService = (_a20 = class {
|
|
1840
|
+
constructor(roleValidator, roleService, userRepository, userValidator, encryptionService) {
|
|
1798
1841
|
this.roleValidator = roleValidator;
|
|
1842
|
+
this.roleService = roleService;
|
|
1843
|
+
this.userRepository = userRepository;
|
|
1844
|
+
this.userValidator = userValidator;
|
|
1845
|
+
this.encryptionService = encryptionService;
|
|
1846
|
+
}
|
|
1847
|
+
sanitizeUser(user) {
|
|
1848
|
+
if (!user)
|
|
1849
|
+
return user;
|
|
1850
|
+
const { password, ...sanitizedUser } = user;
|
|
1851
|
+
return sanitizedUser;
|
|
1852
|
+
}
|
|
1853
|
+
sanitizeUsers(users) {
|
|
1854
|
+
return users.map((user) => this.sanitizeUser(user));
|
|
1855
|
+
}
|
|
1856
|
+
async resolveUserRole(roleId, roleName) {
|
|
1857
|
+
if (roleId) {
|
|
1858
|
+
await this.roleValidator.checkRoleExists(roleId);
|
|
1859
|
+
return roleId;
|
|
1860
|
+
}
|
|
1861
|
+
if (roleName) {
|
|
1862
|
+
const roleByName = await this.roleService.getByName(roleName);
|
|
1863
|
+
if (roleByName) {
|
|
1864
|
+
return roleByName.id;
|
|
1865
|
+
}
|
|
1866
|
+
throw new Error(`Role '${roleName}' not found`);
|
|
1867
|
+
}
|
|
1868
|
+
const defaultRole = await this.roleService.getByName("Student");
|
|
1869
|
+
return defaultRole.id;
|
|
1799
1870
|
}
|
|
1800
1871
|
async getAll() {
|
|
1801
|
-
|
|
1872
|
+
const users = await this.userRepository.getAll();
|
|
1873
|
+
return this.sanitizeUsers(users);
|
|
1802
1874
|
}
|
|
1803
1875
|
async getById(id) {
|
|
1804
|
-
await this.
|
|
1805
|
-
|
|
1876
|
+
await this.userValidator.checkUserExists(id);
|
|
1877
|
+
const user = await this.userRepository.getById(id);
|
|
1878
|
+
return this.sanitizeUser(user);
|
|
1806
1879
|
}
|
|
1807
|
-
async
|
|
1808
|
-
|
|
1880
|
+
async getByEmail(email) {
|
|
1881
|
+
const user = await this.userValidator.checkUserExistsByEmail(email);
|
|
1882
|
+
return this.sanitizeUser(user);
|
|
1809
1883
|
}
|
|
1810
1884
|
async create(data) {
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1885
|
+
const { id, email, image, emailVerified, password, roleId, role } = data;
|
|
1886
|
+
let userId = id || nanoid2(5);
|
|
1887
|
+
let pass = password || "12345678";
|
|
1888
|
+
await this.userValidator.checkEmailUnique(data.email);
|
|
1889
|
+
await this.userValidator.checkUserIdIsUnique(id);
|
|
1890
|
+
const hashedPassword = await this.encryptionService.hashPassword(pass);
|
|
1891
|
+
const resolvedRoleId = await this.resolveUserRole(roleId, role);
|
|
1892
|
+
const userDetails = {
|
|
1893
|
+
id: userId,
|
|
1894
|
+
email,
|
|
1895
|
+
image,
|
|
1896
|
+
password: hashedPassword,
|
|
1897
|
+
roleId: resolvedRoleId,
|
|
1898
|
+
emailVerified,
|
|
1899
|
+
status: "pending"
|
|
1900
|
+
};
|
|
1901
|
+
await this.userValidator.validateCreateUser(userDetails);
|
|
1902
|
+
const newUser = await this.userRepository.create(userDetails);
|
|
1903
|
+
return this.sanitizeUser(newUser);
|
|
1814
1904
|
}
|
|
1815
1905
|
async update(id, data) {
|
|
1816
|
-
|
|
1817
|
-
await this.
|
|
1818
|
-
|
|
1906
|
+
const { password, image } = data;
|
|
1907
|
+
await this.userValidator.checkUserExists(id);
|
|
1908
|
+
await this.userValidator.checkEmailUnique(data.email, id);
|
|
1909
|
+
const currentUser = await this.userRepository.getById(id);
|
|
1910
|
+
const hashedPassword = await this.encryptionService.hashPassword(password);
|
|
1911
|
+
const updateData = {
|
|
1912
|
+
...data,
|
|
1913
|
+
image,
|
|
1914
|
+
...hashedPassword && { password: hashedPassword }
|
|
1915
|
+
};
|
|
1916
|
+
const cleanedUpdateData = clean(updateData);
|
|
1917
|
+
const updatedUser = await this.userRepository.update(id, cleanedUpdateData);
|
|
1918
|
+
return this.sanitizeUser(updatedUser);
|
|
1819
1919
|
}
|
|
1820
1920
|
async delete(id) {
|
|
1821
|
-
await this.
|
|
1822
|
-
|
|
1921
|
+
await this.userValidator.checkUserExists(id);
|
|
1922
|
+
const user = await this.userRepository.delete(id);
|
|
1923
|
+
return this.sanitizeUser(user);
|
|
1823
1924
|
}
|
|
1824
|
-
async
|
|
1825
|
-
const
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1925
|
+
async deleteAll() {
|
|
1926
|
+
const deletedUsers = await this.userRepository.deleteAll();
|
|
1927
|
+
return this.sanitizeUsers(deletedUsers);
|
|
1928
|
+
}
|
|
1929
|
+
async getRoleName(id) {
|
|
1930
|
+
await this.userValidator.checkUserExists(id);
|
|
1931
|
+
return await this.userRepository.getRoleNameById(id);
|
|
1932
|
+
}
|
|
1933
|
+
async getPassword(email) {
|
|
1934
|
+
await this.userValidator.checkUserExistsByEmail(email);
|
|
1935
|
+
return await this.userRepository.getUserPassword(email);
|
|
1936
|
+
}
|
|
1937
|
+
async assignRole(id, roleId, roleName) {
|
|
1938
|
+
await this.userValidator.checkUserExists(id);
|
|
1939
|
+
const resolvedRoleId = await this.resolveUserRole(roleId, roleName);
|
|
1940
|
+
const updatedUser = await this.userRepository.update(id, { roleId: resolvedRoleId });
|
|
1941
|
+
return this.sanitizeUser(updatedUser);
|
|
1942
|
+
}
|
|
1943
|
+
async removeRole(id) {
|
|
1944
|
+
await this.userValidator.checkUserExists(id);
|
|
1945
|
+
const updatedUser = await this.userRepository.update(id, { roleId: null });
|
|
1946
|
+
return this.sanitizeUser(updatedUser);
|
|
1947
|
+
}
|
|
1948
|
+
async seedAdminUser() {
|
|
1949
|
+
const email = "admin@admin.com";
|
|
1950
|
+
const adminRole = await this.roleValidator.checkAdminRoleExists();
|
|
1951
|
+
const existingUser = await this.userRepository.getByEmail(email);
|
|
1952
|
+
if (existingUser) {
|
|
1953
|
+
await this.delete(existingUser.id);
|
|
1831
1954
|
}
|
|
1832
|
-
const
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1955
|
+
const newAdminUser = await this.create({
|
|
1956
|
+
id: "USR00",
|
|
1957
|
+
name: "System Administrator",
|
|
1958
|
+
email,
|
|
1959
|
+
password: "12345678",
|
|
1960
|
+
image: null,
|
|
1961
|
+
roleId: adminRole.id,
|
|
1962
|
+
status: "active",
|
|
1963
|
+
emailVerified: true
|
|
1964
|
+
});
|
|
1965
|
+
return this.sanitizeUser(newAdminUser);
|
|
1836
1966
|
}
|
|
1837
|
-
async
|
|
1838
|
-
|
|
1839
|
-
return
|
|
1967
|
+
async updateLang(language) {
|
|
1968
|
+
setLanguage(language);
|
|
1969
|
+
return language;
|
|
1840
1970
|
}
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1971
|
+
async getLang() {
|
|
1972
|
+
return getCurrentLanguage();
|
|
1973
|
+
}
|
|
1974
|
+
}, __name(_a20, "UserService"), _a20);
|
|
1975
|
+
__decorate12([
|
|
1976
|
+
Transactional(),
|
|
1977
|
+
__metadata8("design:type", Function),
|
|
1978
|
+
__metadata8("design:paramtypes", [Object]),
|
|
1979
|
+
__metadata8("design:returntype", Promise)
|
|
1980
|
+
], UserService.prototype, "create", null);
|
|
1981
|
+
UserService = __decorate12([
|
|
1982
|
+
Injectable8(),
|
|
1983
|
+
__metadata8("design:paramtypes", [typeof (_a19 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _a19 : Object, typeof (_b3 = typeof RoleService !== "undefined" && RoleService) === "function" ? _b3 : Object, typeof (_c = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _c : Object, typeof (_d = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _d : Object, typeof (_e = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _e : Object])
|
|
1984
|
+
], UserService);
|
|
1845
1985
|
|
|
1846
|
-
// src/
|
|
1847
|
-
import {
|
|
1848
|
-
|
|
1849
|
-
var
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1986
|
+
// src/users/UserController.ts
|
|
1987
|
+
import { Controller as Controller2, Get as Get2, Post as Post2, Put as Put2, Delete as Delete2, Params as Params2, Body as Body2, t as t5 } from "najm-api";
|
|
1988
|
+
var __decorate13 = function(decorators, target, key, desc) {
|
|
1989
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1990
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1991
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1992
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1993
|
+
};
|
|
1994
|
+
var __metadata9 = function(k, v) {
|
|
1995
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1996
|
+
};
|
|
1997
|
+
var __param3 = function(paramIndex, decorator) {
|
|
1998
|
+
return function(target, key) {
|
|
1999
|
+
decorator(target, key, paramIndex);
|
|
2000
|
+
};
|
|
2001
|
+
};
|
|
2002
|
+
var _a21;
|
|
2003
|
+
var _a22;
|
|
2004
|
+
var UserController = (_a22 = class {
|
|
2005
|
+
constructor(userService) {
|
|
2006
|
+
this.userService = userService;
|
|
2007
|
+
}
|
|
2008
|
+
async getUsers() {
|
|
2009
|
+
const users = await this.userService.getAll();
|
|
2010
|
+
return {
|
|
2011
|
+
data: users,
|
|
2012
|
+
message: t5("users.success.retrieved"),
|
|
2013
|
+
status: "success"
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
async getLang() {
|
|
2017
|
+
const language = await this.userService.getLang();
|
|
2018
|
+
return {
|
|
2019
|
+
data: { language },
|
|
2020
|
+
message: t5("users.success.retrieved"),
|
|
2021
|
+
status: "success"
|
|
2022
|
+
};
|
|
2023
|
+
}
|
|
2024
|
+
async updateLang(language) {
|
|
2025
|
+
const data = await this.userService.updateLang(language);
|
|
2026
|
+
return {
|
|
2027
|
+
data,
|
|
2028
|
+
message: t5("users.success.updated"),
|
|
2029
|
+
status: "success"
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
async getUser(id) {
|
|
2033
|
+
const user = await this.userService.getById(id);
|
|
2034
|
+
return {
|
|
2035
|
+
data: user,
|
|
2036
|
+
message: t5("users.success.retrieved"),
|
|
2037
|
+
status: "success"
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
async getByEmail(email) {
|
|
2041
|
+
const user = await this.userService.getByEmail(email);
|
|
2042
|
+
return {
|
|
2043
|
+
data: user,
|
|
2044
|
+
message: t5("users.success.retrieved"),
|
|
2045
|
+
status: "success"
|
|
2046
|
+
};
|
|
1858
2047
|
}
|
|
1859
|
-
async
|
|
1860
|
-
const
|
|
1861
|
-
return
|
|
2048
|
+
async getRole(userId) {
|
|
2049
|
+
const role = await this.userService.getRoleName(userId);
|
|
2050
|
+
return {
|
|
2051
|
+
data: role,
|
|
2052
|
+
message: t5("users.success.retrieved"),
|
|
2053
|
+
status: "success"
|
|
2054
|
+
};
|
|
1862
2055
|
}
|
|
1863
|
-
async
|
|
1864
|
-
const
|
|
1865
|
-
return
|
|
2056
|
+
async create(body) {
|
|
2057
|
+
const newUser = await this.userService.create(body);
|
|
2058
|
+
return {
|
|
2059
|
+
data: newUser,
|
|
2060
|
+
message: t5("users.success.created"),
|
|
2061
|
+
status: "success"
|
|
2062
|
+
};
|
|
1866
2063
|
}
|
|
1867
|
-
async
|
|
1868
|
-
const
|
|
1869
|
-
return
|
|
2064
|
+
async update(id, body) {
|
|
2065
|
+
const updatedUser = await this.userService.update(id, body);
|
|
2066
|
+
return {
|
|
2067
|
+
data: updatedUser,
|
|
2068
|
+
message: t5("users.success.updated"),
|
|
2069
|
+
status: "success"
|
|
2070
|
+
};
|
|
1870
2071
|
}
|
|
1871
|
-
async
|
|
1872
|
-
const
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2072
|
+
async delete(id) {
|
|
2073
|
+
const result = await this.userService.delete(id);
|
|
2074
|
+
return {
|
|
2075
|
+
data: result,
|
|
2076
|
+
message: t5("users.success.deleted"),
|
|
2077
|
+
status: "success"
|
|
2078
|
+
};
|
|
1876
2079
|
}
|
|
1877
|
-
async
|
|
1878
|
-
const
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
2080
|
+
async deleteAll() {
|
|
2081
|
+
const result = await this.userService.deleteAll();
|
|
2082
|
+
return {
|
|
2083
|
+
data: result,
|
|
2084
|
+
message: t5("users.success.allDeleted"),
|
|
2085
|
+
status: "success"
|
|
2086
|
+
};
|
|
1884
2087
|
}
|
|
1885
|
-
async
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
status:
|
|
1890
|
-
|
|
1891
|
-
roleName: rolesTable.name,
|
|
1892
|
-
createdAt: usersTable.createdAt,
|
|
1893
|
-
updatedAt: usersTable.updatedAt
|
|
1894
|
-
}).from(usersTable).leftJoin(rolesTable, eq3(usersTable.roleId, rolesTable.id)).where(eq3(usersTable.id, userId)).limit(1);
|
|
1895
|
-
return user ? { ...user, role: user.roleName } : null;
|
|
2088
|
+
async assignRole(userId, roleId) {
|
|
2089
|
+
await this.userService.assignRole(userId, roleId);
|
|
2090
|
+
return {
|
|
2091
|
+
message: t5("users.success.updated"),
|
|
2092
|
+
status: "success"
|
|
2093
|
+
};
|
|
1896
2094
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
2095
|
+
async removeRole(userId) {
|
|
2096
|
+
await this.userService.removeRole(userId);
|
|
2097
|
+
return {
|
|
2098
|
+
message: t5("users.success.updated"),
|
|
2099
|
+
status: "success"
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
}, __name(_a22, "UserController"), _a22);
|
|
2103
|
+
__decorate13([
|
|
2104
|
+
Get2(),
|
|
2105
|
+
isAdmin(),
|
|
2106
|
+
__metadata9("design:type", Function),
|
|
2107
|
+
__metadata9("design:paramtypes", []),
|
|
2108
|
+
__metadata9("design:returntype", Promise)
|
|
2109
|
+
], UserController.prototype, "getUsers", null);
|
|
2110
|
+
__decorate13([
|
|
2111
|
+
Get2("/lang"),
|
|
2112
|
+
isAuth(),
|
|
2113
|
+
__metadata9("design:type", Function),
|
|
2114
|
+
__metadata9("design:paramtypes", []),
|
|
2115
|
+
__metadata9("design:returntype", Promise)
|
|
2116
|
+
], UserController.prototype, "getLang", null);
|
|
2117
|
+
__decorate13([
|
|
2118
|
+
Post2("/lang/:language"),
|
|
2119
|
+
isAuth(),
|
|
2120
|
+
__param3(0, Params2("language")),
|
|
2121
|
+
__metadata9("design:type", Function),
|
|
2122
|
+
__metadata9("design:paramtypes", [Object]),
|
|
2123
|
+
__metadata9("design:returntype", Promise)
|
|
2124
|
+
], UserController.prototype, "updateLang", null);
|
|
2125
|
+
__decorate13([
|
|
2126
|
+
Get2("/:id"),
|
|
2127
|
+
isAdmin(),
|
|
2128
|
+
__param3(0, Params2("id")),
|
|
2129
|
+
__metadata9("design:type", Function),
|
|
2130
|
+
__metadata9("design:paramtypes", [Object]),
|
|
2131
|
+
__metadata9("design:returntype", Promise)
|
|
2132
|
+
], UserController.prototype, "getUser", null);
|
|
2133
|
+
__decorate13([
|
|
2134
|
+
Get2("/email/:email"),
|
|
2135
|
+
isAdmin(),
|
|
2136
|
+
__param3(0, Params2("email")),
|
|
2137
|
+
__metadata9("design:type", Function),
|
|
2138
|
+
__metadata9("design:paramtypes", [Object]),
|
|
2139
|
+
__metadata9("design:returntype", Promise)
|
|
2140
|
+
], UserController.prototype, "getByEmail", null);
|
|
2141
|
+
__decorate13([
|
|
2142
|
+
Get2("/role/:userId"),
|
|
2143
|
+
isAdmin(),
|
|
2144
|
+
__param3(0, Params2("userId")),
|
|
2145
|
+
__metadata9("design:type", Function),
|
|
2146
|
+
__metadata9("design:paramtypes", [Object]),
|
|
2147
|
+
__metadata9("design:returntype", Promise)
|
|
2148
|
+
], UserController.prototype, "getRole", null);
|
|
2149
|
+
__decorate13([
|
|
2150
|
+
Post2(),
|
|
2151
|
+
isAdmin(),
|
|
2152
|
+
__param3(0, Body2()),
|
|
2153
|
+
__metadata9("design:type", Function),
|
|
2154
|
+
__metadata9("design:paramtypes", [Object]),
|
|
2155
|
+
__metadata9("design:returntype", Promise)
|
|
2156
|
+
], UserController.prototype, "create", null);
|
|
2157
|
+
__decorate13([
|
|
2158
|
+
Put2("/:id"),
|
|
2159
|
+
isAdmin(),
|
|
2160
|
+
__param3(0, Params2("id")),
|
|
2161
|
+
__param3(1, Body2()),
|
|
2162
|
+
__metadata9("design:type", Function),
|
|
2163
|
+
__metadata9("design:paramtypes", [Object, Object]),
|
|
2164
|
+
__metadata9("design:returntype", Promise)
|
|
2165
|
+
], UserController.prototype, "update", null);
|
|
2166
|
+
__decorate13([
|
|
2167
|
+
Delete2("/:id"),
|
|
2168
|
+
isAdmin(),
|
|
2169
|
+
__param3(0, Params2("id")),
|
|
2170
|
+
__metadata9("design:type", Function),
|
|
2171
|
+
__metadata9("design:paramtypes", [Object]),
|
|
2172
|
+
__metadata9("design:returntype", Promise)
|
|
2173
|
+
], UserController.prototype, "delete", null);
|
|
2174
|
+
__decorate13([
|
|
2175
|
+
Delete2(),
|
|
2176
|
+
isAdmin(),
|
|
2177
|
+
__metadata9("design:type", Function),
|
|
2178
|
+
__metadata9("design:paramtypes", []),
|
|
2179
|
+
__metadata9("design:returntype", Promise)
|
|
2180
|
+
], UserController.prototype, "deleteAll", null);
|
|
2181
|
+
__decorate13([
|
|
2182
|
+
Post2("/assign/:userId/:roleId"),
|
|
2183
|
+
isAdmin(),
|
|
2184
|
+
__param3(0, Params2("userId")),
|
|
2185
|
+
__param3(1, Params2("roleId")),
|
|
2186
|
+
__metadata9("design:type", Function),
|
|
2187
|
+
__metadata9("design:paramtypes", [Object, Object]),
|
|
2188
|
+
__metadata9("design:returntype", Promise)
|
|
2189
|
+
], UserController.prototype, "assignRole", null);
|
|
2190
|
+
__decorate13([
|
|
2191
|
+
Delete2("/remove/:userId"),
|
|
2192
|
+
isAdmin(),
|
|
2193
|
+
__param3(0, Params2("userId")),
|
|
2194
|
+
__metadata9("design:type", Function),
|
|
2195
|
+
__metadata9("design:paramtypes", [Object]),
|
|
2196
|
+
__metadata9("design:returntype", Promise)
|
|
2197
|
+
], UserController.prototype, "removeRole", null);
|
|
2198
|
+
UserController = __decorate13([
|
|
2199
|
+
Controller2("/users"),
|
|
2200
|
+
__metadata9("design:paramtypes", [typeof (_a21 = typeof UserService !== "undefined" && UserService) === "function" ? _a21 : Object])
|
|
2201
|
+
], UserController);
|
|
1901
2202
|
|
|
1902
|
-
// src/
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2203
|
+
// src/auth/AuthService.ts
|
|
2204
|
+
var __decorate14 = function(decorators, target, key, desc) {
|
|
2205
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2206
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2207
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2208
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2209
|
+
};
|
|
2210
|
+
var __metadata10 = function(k, v) {
|
|
2211
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2212
|
+
};
|
|
2213
|
+
var _a23;
|
|
2214
|
+
var _b4;
|
|
2215
|
+
var _c2;
|
|
2216
|
+
var _d2;
|
|
2217
|
+
var _a24;
|
|
2218
|
+
var AuthService = (_a24 = class {
|
|
2219
|
+
constructor(tokenService, userService, userValidator, cookieService) {
|
|
2220
|
+
this.tokenService = tokenService;
|
|
2221
|
+
this.userService = userService;
|
|
2222
|
+
this.userValidator = userValidator;
|
|
2223
|
+
this.cookieService = cookieService;
|
|
1915
2224
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
if (authorization && authorization.startsWith("Bearer")) {
|
|
1919
|
-
return authorization.split(" ")[1];
|
|
1920
|
-
}
|
|
1921
|
-
throw new Error(t7("auth.errors.tokenMissing"));
|
|
2225
|
+
async registerUser(body) {
|
|
2226
|
+
return await this.userService.create(body);
|
|
1922
2227
|
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
throw new Error(t7("auth.errors.tokenVerificationFailed"));
|
|
2228
|
+
async loginUser(body) {
|
|
2229
|
+
const { email, password } = body;
|
|
2230
|
+
if (!email || !password) {
|
|
2231
|
+
throw new Error(t6("auth.errors.invalidCredentials"));
|
|
1928
2232
|
}
|
|
2233
|
+
const existingPassword = await this.userService.getPassword(email);
|
|
2234
|
+
const { id } = await this.userService.getByEmail(email);
|
|
2235
|
+
await this.userValidator.checkPasswordValid(password, existingPassword);
|
|
2236
|
+
const data = await this.tokenService.generateTokens(id);
|
|
2237
|
+
this.cookieService.setRefreshCookie(data.refreshToken);
|
|
2238
|
+
return data;
|
|
1929
2239
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
} catch (error) {
|
|
1935
|
-
throw new Error(t7("auth.errors.tokenVerificationFailed"));
|
|
1936
|
-
}
|
|
2240
|
+
async refreshTokens() {
|
|
2241
|
+
const data = await this.tokenService.refreshTokens();
|
|
2242
|
+
this.cookieService.setRefreshCookie(data.refreshToken);
|
|
2243
|
+
return data;
|
|
1937
2244
|
}
|
|
1938
|
-
async
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
if (!userExists) {
|
|
1944
|
-
throw new Error(t7("users.errors.notFound"));
|
|
1945
|
-
}
|
|
1946
|
-
return userId;
|
|
2245
|
+
async logoutUser(userId) {
|
|
2246
|
+
await this.userValidator.checkUserExists(userId);
|
|
2247
|
+
await this.tokenService.revokeToken(userId);
|
|
2248
|
+
this.cookieService.clearRefreshCookie();
|
|
2249
|
+
return { data: null, message: t6("auth.success.logout") };
|
|
1947
2250
|
}
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
token: refreshToken,
|
|
1954
|
-
expiresAt: new Date(Date.now() + expireInSecond * 1e3).toISOString()
|
|
2251
|
+
async getUserProfile(userData) {
|
|
2252
|
+
const lang = getCurrentLanguage2();
|
|
2253
|
+
return {
|
|
2254
|
+
...userData,
|
|
2255
|
+
language: lang
|
|
1955
2256
|
};
|
|
1956
|
-
await this.tokenRepository.storeRefreshToken(tokenData);
|
|
1957
2257
|
}
|
|
1958
|
-
|
|
1959
|
-
return jwtDecode(token).exp;
|
|
2258
|
+
async forgotPassword(email) {
|
|
1960
2259
|
}
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2260
|
+
}, __name(_a24, "AuthService"), _a24);
|
|
2261
|
+
AuthService = __decorate14([
|
|
2262
|
+
Injectable9(),
|
|
2263
|
+
__metadata10("design:paramtypes", [typeof (_a23 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a23 : Object, typeof (_b4 = typeof UserService !== "undefined" && UserService) === "function" ? _b4 : Object, typeof (_c2 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _c2 : Object, typeof (_d2 = typeof CookieService !== "undefined" && CookieService) === "function" ? _d2 : Object])
|
|
2264
|
+
], AuthService);
|
|
2265
|
+
|
|
2266
|
+
// src/auth/AuthController.ts
|
|
2267
|
+
var __decorate15 = function(decorators, target, key, desc) {
|
|
2268
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2269
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2270
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2271
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2272
|
+
};
|
|
2273
|
+
var __metadata11 = function(k, v) {
|
|
2274
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2275
|
+
};
|
|
2276
|
+
var __param4 = function(paramIndex, decorator) {
|
|
2277
|
+
return function(target, key) {
|
|
2278
|
+
decorator(target, key, paramIndex);
|
|
2279
|
+
};
|
|
2280
|
+
};
|
|
2281
|
+
var _a25;
|
|
2282
|
+
var _a26;
|
|
2283
|
+
var AuthController = (_a26 = class {
|
|
2284
|
+
constructor(authService) {
|
|
2285
|
+
this.authService = authService;
|
|
1964
2286
|
}
|
|
1965
|
-
|
|
1966
|
-
const
|
|
1967
|
-
return
|
|
2287
|
+
async registerUser(body) {
|
|
2288
|
+
const data = await this.authService.registerUser(body);
|
|
2289
|
+
return {
|
|
2290
|
+
data,
|
|
2291
|
+
message: t7("auth.success.register"),
|
|
2292
|
+
status: "success"
|
|
2293
|
+
};
|
|
1968
2294
|
}
|
|
1969
|
-
async
|
|
1970
|
-
const
|
|
1971
|
-
const accessToken = await this.generateAccessToken(tokenData);
|
|
1972
|
-
const refreshToken = await this.generateRefreshToken(tokenData);
|
|
1973
|
-
const accessTokenExpiresAt = this.getTokenExpire(accessToken);
|
|
1974
|
-
const refreshTokenExpiresAt = this.getTokenExpire(refreshToken);
|
|
1975
|
-
await this.storeRefreshToken(userId, refreshToken);
|
|
2295
|
+
async loginUser(body) {
|
|
2296
|
+
const data = await this.authService.loginUser(body);
|
|
1976
2297
|
return {
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
refreshTokenExpiresAt
|
|
2298
|
+
data,
|
|
2299
|
+
message: t7("auth.success.login"),
|
|
2300
|
+
status: "success"
|
|
1981
2301
|
};
|
|
1982
2302
|
}
|
|
1983
2303
|
async refreshTokens() {
|
|
1984
|
-
const
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
}
|
|
1990
|
-
const storedRefreshToken = await this.tokenRepository.getRefreshToken(userId);
|
|
1991
|
-
if (newRefreshToken != storedRefreshToken) {
|
|
1992
|
-
throw new Error(t7("auth.errors.refreshTokenInvalid"));
|
|
1993
|
-
}
|
|
1994
|
-
return await this.generateTokens(userId);
|
|
1995
|
-
}
|
|
1996
|
-
async revokeToken(userId) {
|
|
1997
|
-
return await this.tokenRepository.revokeToken(userId);
|
|
1998
|
-
}
|
|
1999
|
-
async getUserPermissions(auth) {
|
|
2000
|
-
if (!auth) return;
|
|
2001
|
-
const userId = await this.getUserIdByAccessToken(auth);
|
|
2002
|
-
const permissions = await this.tokenRepository.getUserPermissions(userId);
|
|
2003
|
-
return permissions;
|
|
2004
|
-
}
|
|
2005
|
-
async getUserRole(auth) {
|
|
2006
|
-
if (!auth) return;
|
|
2007
|
-
const userId = await this.getUserIdByAccessToken(auth);
|
|
2008
|
-
const roleName = await this.tokenRepository.getRoleNameById(userId);
|
|
2009
|
-
return roleName;
|
|
2304
|
+
const data = await this.authService.refreshTokens();
|
|
2305
|
+
return {
|
|
2306
|
+
data,
|
|
2307
|
+
message: t7("auth.success.tokenRefreshed"),
|
|
2308
|
+
status: "success"
|
|
2309
|
+
};
|
|
2010
2310
|
}
|
|
2011
|
-
async
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2311
|
+
async logoutUser(id) {
|
|
2312
|
+
const data = await this.authService.logoutUser(id);
|
|
2313
|
+
return {
|
|
2314
|
+
data,
|
|
2315
|
+
message: t7("auth.success.logout"),
|
|
2316
|
+
status: "success"
|
|
2317
|
+
};
|
|
2017
2318
|
}
|
|
2018
|
-
async
|
|
2019
|
-
const
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
}
|
|
2025
|
-
return user;
|
|
2319
|
+
async userProfile(user) {
|
|
2320
|
+
const data = await this.authService.getUserProfile(user);
|
|
2321
|
+
return {
|
|
2322
|
+
data,
|
|
2323
|
+
message: t7("users.success.retrieved"),
|
|
2324
|
+
status: "success"
|
|
2325
|
+
};
|
|
2026
2326
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
Injectable10()
|
|
2030
|
-
], TokenService);
|
|
2031
|
-
|
|
2032
|
-
// src/users/UserRepository.ts
|
|
2033
|
-
import { eq as eq4, ne } from "drizzle-orm";
|
|
2034
|
-
import { Repository as Repository4 } from "najm-api";
|
|
2035
|
-
var UserRepository = class {
|
|
2036
|
-
getUser() {
|
|
2327
|
+
async forgotPassword(body) {
|
|
2328
|
+
const data = await this.authService.forgotPassword(body.email);
|
|
2037
2329
|
return {
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
image: usersTable.image,
|
|
2042
|
-
status: usersTable.status,
|
|
2043
|
-
roleId: usersTable.roleId,
|
|
2044
|
-
role: rolesTable.name,
|
|
2045
|
-
createdAt: usersTable.createdAt,
|
|
2046
|
-
updatedAt: usersTable.updatedAt
|
|
2330
|
+
data,
|
|
2331
|
+
message: t7("auth.success.passwordReset"),
|
|
2332
|
+
status: "success"
|
|
2047
2333
|
};
|
|
2048
2334
|
}
|
|
2335
|
+
}, __name(_a26, "AuthController"), _a26);
|
|
2336
|
+
__decorate15([
|
|
2337
|
+
Post3("/register"),
|
|
2338
|
+
__param4(0, Body3()),
|
|
2339
|
+
__metadata11("design:type", Function),
|
|
2340
|
+
__metadata11("design:paramtypes", [Object]),
|
|
2341
|
+
__metadata11("design:returntype", Promise)
|
|
2342
|
+
], AuthController.prototype, "registerUser", null);
|
|
2343
|
+
__decorate15([
|
|
2344
|
+
Post3("/login"),
|
|
2345
|
+
__param4(0, Body3()),
|
|
2346
|
+
__metadata11("design:type", Function),
|
|
2347
|
+
__metadata11("design:paramtypes", [Object]),
|
|
2348
|
+
__metadata11("design:returntype", Promise)
|
|
2349
|
+
], AuthController.prototype, "loginUser", null);
|
|
2350
|
+
__decorate15([
|
|
2351
|
+
Get3("/refresh"),
|
|
2352
|
+
__metadata11("design:type", Function),
|
|
2353
|
+
__metadata11("design:paramtypes", []),
|
|
2354
|
+
__metadata11("design:returntype", Promise)
|
|
2355
|
+
], AuthController.prototype, "refreshTokens", null);
|
|
2356
|
+
__decorate15([
|
|
2357
|
+
Get3("/logout/:id"),
|
|
2358
|
+
__param4(0, Params3("id")),
|
|
2359
|
+
__metadata11("design:type", Function),
|
|
2360
|
+
__metadata11("design:paramtypes", [Object]),
|
|
2361
|
+
__metadata11("design:returntype", Promise)
|
|
2362
|
+
], AuthController.prototype, "logoutUser", null);
|
|
2363
|
+
__decorate15([
|
|
2364
|
+
Get3("/me"),
|
|
2365
|
+
isAuth(),
|
|
2366
|
+
__param4(0, User()),
|
|
2367
|
+
__metadata11("design:type", Function),
|
|
2368
|
+
__metadata11("design:paramtypes", [Object]),
|
|
2369
|
+
__metadata11("design:returntype", Promise)
|
|
2370
|
+
], AuthController.prototype, "userProfile", null);
|
|
2371
|
+
__decorate15([
|
|
2372
|
+
Post3("/forgot-password"),
|
|
2373
|
+
isAuth(),
|
|
2374
|
+
__param4(0, Body3()),
|
|
2375
|
+
__metadata11("design:type", Function),
|
|
2376
|
+
__metadata11("design:paramtypes", [Object]),
|
|
2377
|
+
__metadata11("design:returntype", Promise)
|
|
2378
|
+
], AuthController.prototype, "forgotPassword", null);
|
|
2379
|
+
AuthController = __decorate15([
|
|
2380
|
+
Controller3("/auth"),
|
|
2381
|
+
__metadata11("design:paramtypes", [typeof (_a25 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a25 : Object])
|
|
2382
|
+
], AuthController);
|
|
2383
|
+
|
|
2384
|
+
// src/permissions/PermissionRepository.ts
|
|
2385
|
+
import { eq as eq4, and } from "drizzle-orm";
|
|
2386
|
+
import { Repository as Repository4 } from "najm-api";
|
|
2387
|
+
var __decorate16 = function(decorators, target, key, desc) {
|
|
2388
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2389
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2390
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2391
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2392
|
+
};
|
|
2393
|
+
var _a27;
|
|
2394
|
+
var PermissionRepository = (_a27 = class {
|
|
2049
2395
|
async getAll() {
|
|
2050
|
-
|
|
2051
|
-
return Promise.all(allUsers.map(async (user) => ({
|
|
2052
|
-
...user,
|
|
2053
|
-
permissions: await this.getUserPermissions(user.id)
|
|
2054
|
-
})));
|
|
2396
|
+
return await this.db.select().from(permissionsTable);
|
|
2055
2397
|
}
|
|
2056
2398
|
async getById(id) {
|
|
2057
|
-
const [
|
|
2058
|
-
|
|
2059
|
-
return {
|
|
2060
|
-
...user,
|
|
2061
|
-
permissions: await this.getUserPermissions(user.id)
|
|
2062
|
-
};
|
|
2399
|
+
const [existingPermission] = await this.db.select().from(permissionsTable).where(eq4(permissionsTable.id, id));
|
|
2400
|
+
return existingPermission;
|
|
2063
2401
|
}
|
|
2064
|
-
async
|
|
2065
|
-
const [
|
|
2066
|
-
return
|
|
2402
|
+
async getByName(name) {
|
|
2403
|
+
const [existingPermission] = await this.db.select().from(permissionsTable).where(eq4(permissionsTable.name, name));
|
|
2404
|
+
return existingPermission;
|
|
2067
2405
|
}
|
|
2068
2406
|
async create(data) {
|
|
2069
|
-
const [
|
|
2070
|
-
return
|
|
2407
|
+
const [newPermission] = await this.db.insert(permissionsTable).values(data).returning();
|
|
2408
|
+
return newPermission;
|
|
2071
2409
|
}
|
|
2072
2410
|
async update(id, data) {
|
|
2073
|
-
const [
|
|
2074
|
-
return
|
|
2411
|
+
const [updatedPermission] = await this.db.update(permissionsTable).set(data).where(eq4(permissionsTable.id, id)).returning();
|
|
2412
|
+
return updatedPermission;
|
|
2075
2413
|
}
|
|
2076
2414
|
async delete(id) {
|
|
2077
|
-
const [
|
|
2078
|
-
return
|
|
2415
|
+
const [deletedPermission] = await this.db.delete(permissionsTable).where(eq4(permissionsTable.id, id)).returning();
|
|
2416
|
+
return deletedPermission;
|
|
2079
2417
|
}
|
|
2080
|
-
async
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2418
|
+
async getPermissionsByRole(roleId) {
|
|
2419
|
+
return await this.db.select({
|
|
2420
|
+
id: permissionsTable.id,
|
|
2421
|
+
name: permissionsTable.name,
|
|
2422
|
+
description: permissionsTable.description,
|
|
2423
|
+
resource: permissionsTable.resource,
|
|
2424
|
+
action: permissionsTable.action
|
|
2425
|
+
}).from(rolePermissionsTable).leftJoin(permissionsTable, eq4(rolePermissionsTable.permissionId, permissionsTable.id)).where(eq4(rolePermissionsTable.roleId, roleId));
|
|
2088
2426
|
}
|
|
2089
|
-
async
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2427
|
+
async getRolesByPermission(permissionId) {
|
|
2428
|
+
return await this.db.select({
|
|
2429
|
+
id: rolesTable.id,
|
|
2430
|
+
name: rolesTable.name,
|
|
2431
|
+
description: rolesTable.description
|
|
2432
|
+
}).from(rolePermissionsTable).leftJoin(rolesTable, eq4(rolePermissionsTable.roleId, rolesTable.id)).where(eq4(rolePermissionsTable.permissionId, permissionId));
|
|
2094
2433
|
}
|
|
2095
|
-
async
|
|
2096
|
-
const [
|
|
2097
|
-
|
|
2098
|
-
email: usersTable.email,
|
|
2099
|
-
password: usersTable.password
|
|
2100
|
-
}).from(usersTable).where(eq4(usersTable.email, email)).limit(1);
|
|
2101
|
-
return user.password;
|
|
2434
|
+
async assignPermissionToRole(roleId, permissionId) {
|
|
2435
|
+
const [newRolePermission] = await this.db.insert(rolePermissionsTable).values({ roleId, permissionId }).returning();
|
|
2436
|
+
return newRolePermission;
|
|
2102
2437
|
}
|
|
2103
|
-
async
|
|
2104
|
-
const [
|
|
2105
|
-
|
|
2106
|
-
const userPermissions = await this.db.select({
|
|
2107
|
-
name: permissionsTable.name
|
|
2108
|
-
}).from(rolePermissionsTable).leftJoin(permissionsTable, eq4(rolePermissionsTable.permissionId, permissionsTable.id)).where(eq4(rolePermissionsTable.roleId, user.roleId));
|
|
2109
|
-
return userPermissions.map((p) => p.name).filter((name) => name);
|
|
2438
|
+
async removePermissionFromRole(roleId, permissionId) {
|
|
2439
|
+
const [deletedRolePermission] = await this.db.delete(rolePermissionsTable).where(and(eq4(rolePermissionsTable.roleId, roleId), eq4(rolePermissionsTable.permissionId, permissionId))).returning();
|
|
2440
|
+
return deletedRolePermission;
|
|
2110
2441
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2442
|
+
async checkRoleHasPermission(roleId, permissionId) {
|
|
2443
|
+
const [rolePermission] = await this.db.select().from(rolePermissionsTable).where(and(eq4(rolePermissionsTable.roleId, roleId), eq4(rolePermissionsTable.permissionId, permissionId)));
|
|
2444
|
+
return !!rolePermission;
|
|
2445
|
+
}
|
|
2446
|
+
async deleteAll() {
|
|
2447
|
+
await this.db.delete(rolePermissionsTable);
|
|
2448
|
+
const deletedPermissions = await this.db.delete(permissionsTable).returning();
|
|
2449
|
+
return deletedPermissions;
|
|
2450
|
+
}
|
|
2451
|
+
}, __name(_a27, "PermissionRepository"), _a27);
|
|
2452
|
+
PermissionRepository = __decorate16([
|
|
2113
2453
|
Repository4()
|
|
2114
|
-
],
|
|
2454
|
+
], PermissionRepository);
|
|
2115
2455
|
|
|
2116
|
-
// src/
|
|
2117
|
-
import { Injectable as
|
|
2118
|
-
var
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2456
|
+
// src/permissions/PermissionGuards.ts
|
|
2457
|
+
import { createGuard as createGuard2, Injectable as Injectable10, GuardParams as GuardParams2, Headers as Headers2, Ctx as Ctx2 } from "najm-api";
|
|
2458
|
+
var __decorate17 = function(decorators, target, key, desc) {
|
|
2459
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2460
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2461
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2462
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2463
|
+
};
|
|
2464
|
+
var __metadata12 = function(k, v) {
|
|
2465
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2466
|
+
};
|
|
2467
|
+
var __param5 = function(paramIndex, decorator) {
|
|
2468
|
+
return function(target, key) {
|
|
2469
|
+
decorator(target, key, paramIndex);
|
|
2470
|
+
};
|
|
2471
|
+
};
|
|
2472
|
+
var _a28;
|
|
2473
|
+
var _a29;
|
|
2474
|
+
var PermissionGuards = (_a29 = class {
|
|
2475
|
+
constructor(tokenService) {
|
|
2476
|
+
this.tokenService = tokenService;
|
|
2122
2477
|
}
|
|
2123
|
-
async
|
|
2124
|
-
|
|
2478
|
+
async getUserPermissions(auth) {
|
|
2479
|
+
const permissions = await this.tokenService.getUserPermissions(auth);
|
|
2480
|
+
if (!permissions || !Array.isArray(permissions))
|
|
2481
|
+
return null;
|
|
2482
|
+
return permissions;
|
|
2125
2483
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2484
|
+
checkPermissionMatch(permissions, requiredPermission) {
|
|
2485
|
+
if (permissions.includes(requiredPermission)) {
|
|
2486
|
+
return true;
|
|
2487
|
+
}
|
|
2488
|
+
const [requiredAction, requiredResource] = requiredPermission.split(":");
|
|
2489
|
+
if (requiredAction && requiredResource) {
|
|
2490
|
+
if (permissions.includes(`${requiredAction}:*`)) {
|
|
2491
|
+
return true;
|
|
2492
|
+
}
|
|
2493
|
+
if (permissions.includes(`*:${requiredResource}`)) {
|
|
2494
|
+
return true;
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
if (permissions.includes("*:*")) {
|
|
2498
|
+
return true;
|
|
2499
|
+
}
|
|
2500
|
+
return false;
|
|
2129
2501
|
}
|
|
2130
|
-
async
|
|
2131
|
-
|
|
2132
|
-
|
|
2502
|
+
async hasPermission(auth, ctx, requiredPermission) {
|
|
2503
|
+
await this.tokenService.storeUserInCache(auth, ctx);
|
|
2504
|
+
const permissions = await this.getUserPermissions(auth);
|
|
2505
|
+
if (!permissions)
|
|
2506
|
+
return false;
|
|
2507
|
+
const check = this.checkPermissionMatch(permissions, requiredPermission);
|
|
2508
|
+
return check;
|
|
2133
2509
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2510
|
+
}, __name(_a29, "PermissionGuards"), _a29);
|
|
2511
|
+
__decorate17([
|
|
2512
|
+
__param5(0, Headers2("authorization")),
|
|
2513
|
+
__param5(1, Ctx2()),
|
|
2514
|
+
__param5(2, GuardParams2()),
|
|
2515
|
+
__metadata12("design:type", Function),
|
|
2516
|
+
__metadata12("design:paramtypes", [Object, Object, Object]),
|
|
2517
|
+
__metadata12("design:returntype", Promise)
|
|
2518
|
+
], PermissionGuards.prototype, "hasPermission", null);
|
|
2519
|
+
PermissionGuards = __decorate17([
|
|
2520
|
+
Injectable10(),
|
|
2521
|
+
__metadata12("design:paramtypes", [typeof (_a28 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a28 : Object])
|
|
2522
|
+
], PermissionGuards);
|
|
2523
|
+
var Permission = /* @__PURE__ */ __name((...permissions) => createGuard2(PermissionGuards, "hasPermission")(...permissions), "Permission");
|
|
2524
|
+
|
|
2525
|
+
// src/permissions/PermissionController.ts
|
|
2526
|
+
import { Controller as Controller4, Get as Get4, Post as Post4, Put as Put3, Delete as Delete3, Params as Params4, Body as Body4, t as t9 } from "najm-api";
|
|
2527
|
+
|
|
2528
|
+
// src/permissions/PermissionService.ts
|
|
2529
|
+
import { Injectable as Injectable12 } from "najm-api";
|
|
2530
|
+
|
|
2531
|
+
// src/permissions/PermissionValidator.ts
|
|
2532
|
+
import { Injectable as Injectable11, t as t8 } from "najm-api";
|
|
2533
|
+
import { z as z3 } from "zod";
|
|
2534
|
+
var __decorate18 = function(decorators, target, key, desc) {
|
|
2535
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2536
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2537
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2538
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2539
|
+
};
|
|
2540
|
+
var __metadata13 = function(k, v) {
|
|
2541
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2542
|
+
};
|
|
2543
|
+
var _a30;
|
|
2544
|
+
var _b5;
|
|
2545
|
+
var permissionSchema = z3.object({
|
|
2546
|
+
name: z3.string().min(1, "Permission name is required"),
|
|
2547
|
+
description: z3.string().optional(),
|
|
2548
|
+
resource: z3.string().min(1, "Resource is required"),
|
|
2549
|
+
action: z3.string().min(1, "Action is required")
|
|
2550
|
+
});
|
|
2551
|
+
var _a31;
|
|
2552
|
+
var PermissionValidator = (_a31 = class {
|
|
2553
|
+
constructor(permissionRepository, roleValidator) {
|
|
2554
|
+
this.permissionRepository = permissionRepository;
|
|
2555
|
+
this.roleValidator = roleValidator;
|
|
2137
2556
|
}
|
|
2138
|
-
async
|
|
2139
|
-
|
|
2140
|
-
const existingUser = await this.userRepository.getById(id);
|
|
2141
|
-
if (existingUser) {
|
|
2142
|
-
throw new Error(t8("users.errors.idExists"));
|
|
2143
|
-
}
|
|
2557
|
+
async validateCreatePermission(data) {
|
|
2558
|
+
return parseSchema(permissionSchema, data);
|
|
2144
2559
|
}
|
|
2145
|
-
async
|
|
2146
|
-
|
|
2560
|
+
async isPermissionExists(id) {
|
|
2561
|
+
const existingPermission = await this.permissionRepository.getById(id);
|
|
2562
|
+
return !!existingPermission;
|
|
2147
2563
|
}
|
|
2148
|
-
async
|
|
2149
|
-
const
|
|
2150
|
-
|
|
2151
|
-
throw Error(t8("auth.errors.accessDenied"));
|
|
2152
|
-
}
|
|
2153
|
-
const hasRole = roles.some(
|
|
2154
|
-
(item) => roleName.toLowerCase() === item.toLowerCase()
|
|
2155
|
-
);
|
|
2156
|
-
if (!hasRole) {
|
|
2157
|
-
throw Error(t8("auth.errors.accessDenied"));
|
|
2158
|
-
}
|
|
2159
|
-
return true;
|
|
2564
|
+
async isPermissionNameExists(name) {
|
|
2565
|
+
const existingPermission = await this.permissionRepository.getByName(name);
|
|
2566
|
+
return !!existingPermission;
|
|
2160
2567
|
}
|
|
2161
2568
|
//======================= throw errors
|
|
2162
|
-
async
|
|
2163
|
-
const
|
|
2164
|
-
if (!
|
|
2165
|
-
throw new Error(t8("
|
|
2166
|
-
}
|
|
2167
|
-
return user;
|
|
2168
|
-
}
|
|
2169
|
-
async checkUserExists(id) {
|
|
2170
|
-
const userExists = await this.isUserExist(id);
|
|
2171
|
-
if (!userExists) {
|
|
2172
|
-
throw new Error(t8("users.errors.notFound"));
|
|
2173
|
-
}
|
|
2174
|
-
return userExists;
|
|
2175
|
-
}
|
|
2176
|
-
async checkEmailUnique(email, excludeId = null) {
|
|
2177
|
-
if (!email) return;
|
|
2178
|
-
const existingUser = await this.userRepository.getByEmail(email);
|
|
2179
|
-
if (existingUser && existingUser.id !== excludeId) {
|
|
2180
|
-
throw new Error(t8("auth.errors.emailExists"));
|
|
2569
|
+
async checkPermissionExists(id) {
|
|
2570
|
+
const permissionExists = await this.isPermissionExists(id);
|
|
2571
|
+
if (!permissionExists) {
|
|
2572
|
+
throw new Error(t8("permissions.errors.notFound"));
|
|
2181
2573
|
}
|
|
2574
|
+
return permissionExists;
|
|
2182
2575
|
}
|
|
2183
|
-
async
|
|
2184
|
-
const
|
|
2185
|
-
if (!
|
|
2186
|
-
throw new Error(t8("
|
|
2576
|
+
async checkPermissionExistsByName(name) {
|
|
2577
|
+
const permissionExists = await this.isPermissionNameExists(name);
|
|
2578
|
+
if (!permissionExists) {
|
|
2579
|
+
throw new Error(t8("permissions.errors.notFound"));
|
|
2187
2580
|
}
|
|
2188
|
-
return
|
|
2581
|
+
return permissionExists;
|
|
2189
2582
|
}
|
|
2190
|
-
async
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2583
|
+
async checkPermissionNameUnique(name, excludeId = null) {
|
|
2584
|
+
if (!name)
|
|
2585
|
+
return;
|
|
2586
|
+
const existingPermission = await this.permissionRepository.getByName(name);
|
|
2587
|
+
if (existingPermission && existingPermission.id !== excludeId) {
|
|
2588
|
+
throw new Error(t8("permissions.errors.nameExists"));
|
|
2194
2589
|
}
|
|
2195
2590
|
}
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
this.userRepository = userRepository;
|
|
2209
|
-
this.userValidator = userValidator;
|
|
2210
|
-
this.encryptionService = encryptionService;
|
|
2211
|
-
}
|
|
2212
|
-
sanitizeUser(user) {
|
|
2213
|
-
if (!user) return user;
|
|
2214
|
-
const { password, ...sanitizedUser } = user;
|
|
2215
|
-
return sanitizedUser;
|
|
2216
|
-
}
|
|
2217
|
-
sanitizeUsers(users) {
|
|
2218
|
-
return users.map((user) => this.sanitizeUser(user));
|
|
2219
|
-
}
|
|
2220
|
-
async resolveUserRole(roleId, roleName) {
|
|
2221
|
-
if (roleId) {
|
|
2222
|
-
await this.roleValidator.checkRoleExists(roleId);
|
|
2223
|
-
return roleId;
|
|
2224
|
-
}
|
|
2225
|
-
if (roleName) {
|
|
2226
|
-
const roleByName = await this.roleService.getByName(roleName);
|
|
2227
|
-
if (roleByName) {
|
|
2228
|
-
return roleByName.id;
|
|
2229
|
-
}
|
|
2230
|
-
throw new Error(`Role '${roleName}' not found`);
|
|
2591
|
+
async checkRoleExists(id) {
|
|
2592
|
+
return await this.roleValidator.checkRoleExists(id);
|
|
2593
|
+
}
|
|
2594
|
+
async checkRoleExistsByName(name) {
|
|
2595
|
+
return await this.roleValidator.checkRoleExistsByName(name);
|
|
2596
|
+
}
|
|
2597
|
+
async checkRoleHasPermission(roleId, permissionId) {
|
|
2598
|
+
await this.roleValidator.checkRoleExists(roleId);
|
|
2599
|
+
await this.checkPermissionExists(permissionId);
|
|
2600
|
+
const hasPermission = await this.permissionRepository.checkRoleHasPermission(roleId, permissionId);
|
|
2601
|
+
if (hasPermission) {
|
|
2602
|
+
throw new Error(t8("permissions.errors.roleAlreadyHasPermission"));
|
|
2231
2603
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2604
|
+
}
|
|
2605
|
+
}, __name(_a31, "PermissionValidator"), _a31);
|
|
2606
|
+
PermissionValidator = __decorate18([
|
|
2607
|
+
Injectable11(),
|
|
2608
|
+
__metadata13("design:paramtypes", [typeof (_a30 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a30 : Object, typeof (_b5 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b5 : Object])
|
|
2609
|
+
], PermissionValidator);
|
|
2610
|
+
|
|
2611
|
+
// src/permissions/PermissionService.ts
|
|
2612
|
+
var __decorate19 = function(decorators, target, key, desc) {
|
|
2613
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2614
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2615
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2616
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2617
|
+
};
|
|
2618
|
+
var __metadata14 = function(k, v) {
|
|
2619
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2620
|
+
};
|
|
2621
|
+
var _a32;
|
|
2622
|
+
var _b6;
|
|
2623
|
+
var _c3;
|
|
2624
|
+
var _a33;
|
|
2625
|
+
var PermissionService = (_a33 = class {
|
|
2626
|
+
constructor(permissionRepository, permissionValidator, roleService) {
|
|
2627
|
+
this.permissionRepository = permissionRepository;
|
|
2628
|
+
this.permissionValidator = permissionValidator;
|
|
2629
|
+
this.roleService = roleService;
|
|
2234
2630
|
}
|
|
2235
2631
|
async getAll() {
|
|
2236
|
-
|
|
2237
|
-
return this.sanitizeUsers(users);
|
|
2632
|
+
return await this.permissionRepository.getAll();
|
|
2238
2633
|
}
|
|
2239
2634
|
async getById(id) {
|
|
2240
|
-
await this.
|
|
2241
|
-
|
|
2242
|
-
return this.sanitizeUser(user);
|
|
2635
|
+
await this.permissionValidator.checkPermissionExists(id);
|
|
2636
|
+
return await this.permissionRepository.getById(id);
|
|
2243
2637
|
}
|
|
2244
|
-
async
|
|
2245
|
-
|
|
2246
|
-
|
|
2638
|
+
async getByName(name) {
|
|
2639
|
+
return await this.permissionRepository.getByName(name);
|
|
2640
|
+
}
|
|
2641
|
+
async getByResource(resource) {
|
|
2642
|
+
return await this.permissionRepository.getAll().then((permissions) => permissions.filter((p) => p.resource === resource));
|
|
2247
2643
|
}
|
|
2248
2644
|
async create(data) {
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
await this.userValidator.checkEmailUnique(data.email);
|
|
2253
|
-
await this.userValidator.checkUserIdIsUnique(id);
|
|
2254
|
-
const hashedPassword = await this.encryptionService.hashPassword(pass);
|
|
2255
|
-
const resolvedRoleId = await this.resolveUserRole(roleId, role);
|
|
2256
|
-
const userDetails = {
|
|
2257
|
-
id: userId,
|
|
2258
|
-
email,
|
|
2259
|
-
image,
|
|
2260
|
-
password: hashedPassword,
|
|
2261
|
-
roleId: resolvedRoleId,
|
|
2262
|
-
emailVerified,
|
|
2263
|
-
status: "pending"
|
|
2264
|
-
};
|
|
2265
|
-
await this.userValidator.validateCreateUser(userDetails);
|
|
2266
|
-
const newUser = await this.userRepository.create(userDetails);
|
|
2267
|
-
return this.sanitizeUser(newUser);
|
|
2645
|
+
await this.permissionValidator.validateCreatePermission(data);
|
|
2646
|
+
await this.permissionValidator.checkPermissionNameUnique(data.name);
|
|
2647
|
+
return await this.permissionRepository.create(data);
|
|
2268
2648
|
}
|
|
2269
2649
|
async update(id, data) {
|
|
2270
|
-
|
|
2271
|
-
await this.
|
|
2272
|
-
await this.
|
|
2273
|
-
const currentUser = await this.userRepository.getById(id);
|
|
2274
|
-
const hashedPassword = await this.encryptionService.hashPassword(password);
|
|
2275
|
-
const updateData = {
|
|
2276
|
-
...data,
|
|
2277
|
-
image,
|
|
2278
|
-
...hashedPassword && { password: hashedPassword }
|
|
2279
|
-
};
|
|
2280
|
-
const cleanedUpdateData = clean(updateData);
|
|
2281
|
-
const updatedUser = await this.userRepository.update(id, cleanedUpdateData);
|
|
2282
|
-
return this.sanitizeUser(updatedUser);
|
|
2650
|
+
await this.permissionValidator.checkPermissionExists(id);
|
|
2651
|
+
await this.permissionValidator.checkPermissionNameUnique(data.name, id);
|
|
2652
|
+
return await this.permissionRepository.update(id, data);
|
|
2283
2653
|
}
|
|
2284
2654
|
async delete(id) {
|
|
2285
|
-
await this.
|
|
2286
|
-
|
|
2287
|
-
return this.sanitizeUser(user);
|
|
2288
|
-
}
|
|
2289
|
-
async deleteAll() {
|
|
2290
|
-
const deletedUsers = await this.userRepository.deleteAll();
|
|
2291
|
-
return this.sanitizeUsers(deletedUsers);
|
|
2655
|
+
await this.permissionValidator.checkPermissionExists(id);
|
|
2656
|
+
return await this.permissionRepository.delete(id);
|
|
2292
2657
|
}
|
|
2293
|
-
async
|
|
2294
|
-
await this.
|
|
2295
|
-
return await this.userRepository.getRoleNameById(id);
|
|
2658
|
+
async getPermissionsByRole(roleId) {
|
|
2659
|
+
return await this.permissionRepository.getPermissionsByRole(roleId);
|
|
2296
2660
|
}
|
|
2297
|
-
async
|
|
2298
|
-
await this.
|
|
2299
|
-
return await this.
|
|
2661
|
+
async getRolesByPermission(permissionId) {
|
|
2662
|
+
await this.permissionValidator.checkPermissionExists(permissionId);
|
|
2663
|
+
return await this.permissionRepository.getRolesByPermission(permissionId);
|
|
2300
2664
|
}
|
|
2301
|
-
async
|
|
2302
|
-
await this.
|
|
2303
|
-
|
|
2304
|
-
const updatedUser = await this.userRepository.update(id, { roleId: resolvedRoleId });
|
|
2305
|
-
return this.sanitizeUser(updatedUser);
|
|
2665
|
+
async assignPermissionToRole(roleId, permissionId) {
|
|
2666
|
+
await this.permissionValidator.checkRoleHasPermission(roleId, permissionId);
|
|
2667
|
+
return await this.permissionRepository.assignPermissionToRole(roleId, permissionId);
|
|
2306
2668
|
}
|
|
2307
|
-
async
|
|
2308
|
-
await this.
|
|
2309
|
-
const updatedUser = await this.userRepository.update(id, { roleId: null });
|
|
2310
|
-
return this.sanitizeUser(updatedUser);
|
|
2669
|
+
async removePermissionFromRole(roleId, permissionId) {
|
|
2670
|
+
return await this.permissionRepository.removePermissionFromRole(roleId, permissionId);
|
|
2311
2671
|
}
|
|
2312
|
-
async
|
|
2313
|
-
const
|
|
2314
|
-
const
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2672
|
+
async seedDefaultPermissions(defaultPermissions) {
|
|
2673
|
+
const createdPermissions = [];
|
|
2674
|
+
for (const permission of defaultPermissions) {
|
|
2675
|
+
try {
|
|
2676
|
+
const permissionEntity = await this.create(permission);
|
|
2677
|
+
createdPermissions.push(permissionEntity);
|
|
2678
|
+
} catch (error) {
|
|
2679
|
+
continue;
|
|
2680
|
+
}
|
|
2318
2681
|
}
|
|
2319
|
-
|
|
2320
|
-
id: "USR00",
|
|
2321
|
-
name: "System Administrator",
|
|
2322
|
-
email,
|
|
2323
|
-
password: "12345678",
|
|
2324
|
-
image: null,
|
|
2325
|
-
roleId: adminRole.id,
|
|
2326
|
-
status: "active",
|
|
2327
|
-
emailVerified: true
|
|
2328
|
-
});
|
|
2329
|
-
return this.sanitizeUser(newAdminUser);
|
|
2682
|
+
return createdPermissions;
|
|
2330
2683
|
}
|
|
2331
|
-
async
|
|
2332
|
-
|
|
2333
|
-
|
|
2684
|
+
async seedDefaultRolePermissions(defaultRolePermissions) {
|
|
2685
|
+
const results = [];
|
|
2686
|
+
for (const { roleName, permissions } of defaultRolePermissions) {
|
|
2687
|
+
try {
|
|
2688
|
+
await this.permissionValidator.checkRoleExistsByName(roleName);
|
|
2689
|
+
const role = await this.roleService.getByName(roleName);
|
|
2690
|
+
for (const permissionName of permissions) {
|
|
2691
|
+
try {
|
|
2692
|
+
await this.permissionValidator.checkPermissionExistsByName(permissionName);
|
|
2693
|
+
const permission = await this.getByName(permissionName);
|
|
2694
|
+
await this.permissionValidator.checkRoleHasPermission(role.id, permission.id);
|
|
2695
|
+
await this.assignPermissionToRole(role.id, permission.id);
|
|
2696
|
+
results.push({ role: roleName, permission: permissionName });
|
|
2697
|
+
} catch (error) {
|
|
2698
|
+
continue;
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
} catch (error) {
|
|
2702
|
+
continue;
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
return results;
|
|
2334
2706
|
}
|
|
2335
|
-
async
|
|
2336
|
-
return
|
|
2707
|
+
async deleteAll() {
|
|
2708
|
+
return await this.permissionRepository.deleteAll();
|
|
2337
2709
|
}
|
|
2338
|
-
};
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
Injectable12()
|
|
2344
|
-
], UserService);
|
|
2710
|
+
}, __name(_a33, "PermissionService"), _a33);
|
|
2711
|
+
PermissionService = __decorate19([
|
|
2712
|
+
Injectable12(),
|
|
2713
|
+
__metadata14("design:paramtypes", [typeof (_a32 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a32 : Object, typeof (_b6 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b6 : Object, typeof (_c3 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c3 : Object])
|
|
2714
|
+
], PermissionService);
|
|
2345
2715
|
|
|
2346
|
-
// src/
|
|
2347
|
-
|
|
2348
|
-
var
|
|
2349
|
-
|
|
2350
|
-
|
|
2716
|
+
// src/permissions/PermissionController.ts
|
|
2717
|
+
var __decorate20 = function(decorators, target, key, desc) {
|
|
2718
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2719
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2720
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2721
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2722
|
+
};
|
|
2723
|
+
var __metadata15 = function(k, v) {
|
|
2724
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2725
|
+
};
|
|
2726
|
+
var __param6 = function(paramIndex, decorator) {
|
|
2727
|
+
return function(target, key) {
|
|
2728
|
+
decorator(target, key, paramIndex);
|
|
2729
|
+
};
|
|
2730
|
+
};
|
|
2731
|
+
var _a34;
|
|
2732
|
+
var _a35;
|
|
2733
|
+
var PermissionController = (_a35 = class {
|
|
2734
|
+
constructor(permissionService) {
|
|
2735
|
+
this.permissionService = permissionService;
|
|
2351
2736
|
}
|
|
2352
|
-
async
|
|
2353
|
-
const
|
|
2737
|
+
async getPermissions() {
|
|
2738
|
+
const permissions = await this.permissionService.getAll();
|
|
2354
2739
|
return {
|
|
2355
|
-
data:
|
|
2356
|
-
message: t9("
|
|
2740
|
+
data: permissions,
|
|
2741
|
+
message: t9("permissions.success.retrieved"),
|
|
2357
2742
|
status: "success"
|
|
2358
2743
|
};
|
|
2359
2744
|
}
|
|
2360
|
-
async
|
|
2361
|
-
const
|
|
2745
|
+
async getPermission(id) {
|
|
2746
|
+
const permission = await this.permissionService.getById(id);
|
|
2362
2747
|
return {
|
|
2363
|
-
data:
|
|
2364
|
-
message: t9("
|
|
2748
|
+
data: permission,
|
|
2749
|
+
message: t9("permissions.success.retrieved"),
|
|
2365
2750
|
status: "success"
|
|
2366
2751
|
};
|
|
2367
2752
|
}
|
|
2368
|
-
async
|
|
2369
|
-
const
|
|
2753
|
+
async create(body) {
|
|
2754
|
+
const newPermission = await this.permissionService.create(body);
|
|
2370
2755
|
return {
|
|
2371
|
-
data,
|
|
2372
|
-
message: t9("
|
|
2756
|
+
data: newPermission,
|
|
2757
|
+
message: t9("permissions.success.created"),
|
|
2373
2758
|
status: "success"
|
|
2374
2759
|
};
|
|
2375
2760
|
}
|
|
2376
|
-
async
|
|
2377
|
-
const
|
|
2761
|
+
async update(id, body) {
|
|
2762
|
+
const updatedPermission = await this.permissionService.update(id, body);
|
|
2378
2763
|
return {
|
|
2379
|
-
data:
|
|
2380
|
-
message: t9("
|
|
2764
|
+
data: updatedPermission,
|
|
2765
|
+
message: t9("permissions.success.updated"),
|
|
2381
2766
|
status: "success"
|
|
2382
2767
|
};
|
|
2383
2768
|
}
|
|
2384
|
-
async
|
|
2385
|
-
const
|
|
2769
|
+
async delete(id) {
|
|
2770
|
+
const result = await this.permissionService.delete(id);
|
|
2386
2771
|
return {
|
|
2387
|
-
data:
|
|
2388
|
-
message: t9("
|
|
2772
|
+
data: result,
|
|
2773
|
+
message: t9("permissions.success.deleted"),
|
|
2389
2774
|
status: "success"
|
|
2390
2775
|
};
|
|
2391
2776
|
}
|
|
2392
|
-
async
|
|
2393
|
-
const
|
|
2777
|
+
async getByRole(roleId) {
|
|
2778
|
+
const permissions = await this.permissionService.getPermissionsByRole(roleId);
|
|
2394
2779
|
return {
|
|
2395
|
-
data:
|
|
2396
|
-
message: t9("
|
|
2780
|
+
data: permissions,
|
|
2781
|
+
message: t9("permissions.success.retrieved"),
|
|
2397
2782
|
status: "success"
|
|
2398
2783
|
};
|
|
2399
2784
|
}
|
|
2400
|
-
async
|
|
2401
|
-
const
|
|
2785
|
+
async getRolesByPermission(permissionId) {
|
|
2786
|
+
const roles = await this.permissionService.getRolesByPermission(permissionId);
|
|
2402
2787
|
return {
|
|
2403
|
-
data:
|
|
2404
|
-
message: t9("
|
|
2788
|
+
data: roles,
|
|
2789
|
+
message: t9("permissions.success.retrieved"),
|
|
2405
2790
|
status: "success"
|
|
2406
2791
|
};
|
|
2407
2792
|
}
|
|
2408
|
-
async
|
|
2409
|
-
const
|
|
2793
|
+
async assignToRole(roleId, permissionId) {
|
|
2794
|
+
const result = await this.permissionService.assignPermissionToRole(roleId, permissionId);
|
|
2410
2795
|
return {
|
|
2411
|
-
data:
|
|
2412
|
-
message: t9("
|
|
2796
|
+
data: result,
|
|
2797
|
+
message: t9("permissions.success.assigned"),
|
|
2413
2798
|
status: "success"
|
|
2414
2799
|
};
|
|
2415
2800
|
}
|
|
2416
|
-
async
|
|
2417
|
-
const result = await this.
|
|
2801
|
+
async removeFromRole(roleId, permissionId) {
|
|
2802
|
+
const result = await this.permissionService.removePermissionFromRole(roleId, permissionId);
|
|
2418
2803
|
return {
|
|
2419
2804
|
data: result,
|
|
2420
|
-
message: t9("
|
|
2805
|
+
message: t9("permissions.success.removed"),
|
|
2421
2806
|
status: "success"
|
|
2422
2807
|
};
|
|
2423
2808
|
}
|
|
2424
2809
|
async deleteAll() {
|
|
2425
|
-
const result = await this.
|
|
2810
|
+
const result = await this.permissionService.deleteAll();
|
|
2426
2811
|
return {
|
|
2427
2812
|
data: result,
|
|
2428
|
-
message: t9("
|
|
2429
|
-
status: "success"
|
|
2430
|
-
};
|
|
2431
|
-
}
|
|
2432
|
-
async assignRole(userId, roleId) {
|
|
2433
|
-
await this.userService.assignRole(userId, roleId);
|
|
2434
|
-
return {
|
|
2435
|
-
message: t9("users.success.updated"),
|
|
2436
|
-
status: "success"
|
|
2437
|
-
};
|
|
2438
|
-
}
|
|
2439
|
-
async removeRole(userId) {
|
|
2440
|
-
await this.userService.removeRole(userId);
|
|
2441
|
-
return {
|
|
2442
|
-
message: t9("users.success.updated"),
|
|
2813
|
+
message: t9("permissions.success.allDeleted"),
|
|
2443
2814
|
status: "success"
|
|
2444
2815
|
};
|
|
2445
2816
|
}
|
|
2446
|
-
};
|
|
2447
|
-
|
|
2817
|
+
}, __name(_a35, "PermissionController"), _a35);
|
|
2818
|
+
__decorate20([
|
|
2448
2819
|
Get4(),
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
], UserController.prototype, "getLang", 1);
|
|
2455
|
-
__decorateClass([
|
|
2456
|
-
Post4("/lang/:language"),
|
|
2457
|
-
isAuth(),
|
|
2458
|
-
__decorateParam(0, Params4("language"))
|
|
2459
|
-
], UserController.prototype, "updateLang", 1);
|
|
2460
|
-
__decorateClass([
|
|
2820
|
+
__metadata15("design:type", Function),
|
|
2821
|
+
__metadata15("design:paramtypes", []),
|
|
2822
|
+
__metadata15("design:returntype", Promise)
|
|
2823
|
+
], PermissionController.prototype, "getPermissions", null);
|
|
2824
|
+
__decorate20([
|
|
2461
2825
|
Get4("/:id"),
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
__decorateParam(0, Params4("email"))
|
|
2469
|
-
], UserController.prototype, "getByEmail", 1);
|
|
2470
|
-
__decorateClass([
|
|
2471
|
-
Get4("/role/:userId"),
|
|
2472
|
-
isAdmin(),
|
|
2473
|
-
__decorateParam(0, Params4("userId"))
|
|
2474
|
-
], UserController.prototype, "getRole", 1);
|
|
2475
|
-
__decorateClass([
|
|
2826
|
+
__param6(0, Params4("id")),
|
|
2827
|
+
__metadata15("design:type", Function),
|
|
2828
|
+
__metadata15("design:paramtypes", [String]),
|
|
2829
|
+
__metadata15("design:returntype", Promise)
|
|
2830
|
+
], PermissionController.prototype, "getPermission", null);
|
|
2831
|
+
__decorate20([
|
|
2476
2832
|
Post4(),
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2833
|
+
__param6(0, Body4()),
|
|
2834
|
+
__metadata15("design:type", Function),
|
|
2835
|
+
__metadata15("design:paramtypes", [Object]),
|
|
2836
|
+
__metadata15("design:returntype", Promise)
|
|
2837
|
+
], PermissionController.prototype, "create", null);
|
|
2838
|
+
__decorate20([
|
|
2481
2839
|
Put3("/:id"),
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2840
|
+
__param6(0, Params4("id")),
|
|
2841
|
+
__param6(1, Body4()),
|
|
2842
|
+
__metadata15("design:type", Function),
|
|
2843
|
+
__metadata15("design:paramtypes", [String, Object]),
|
|
2844
|
+
__metadata15("design:returntype", Promise)
|
|
2845
|
+
], PermissionController.prototype, "update", null);
|
|
2846
|
+
__decorate20([
|
|
2487
2847
|
Delete3("/:id"),
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2848
|
+
__param6(0, Params4("id")),
|
|
2849
|
+
__metadata15("design:type", Function),
|
|
2850
|
+
__metadata15("design:paramtypes", [String]),
|
|
2851
|
+
__metadata15("design:returntype", Promise)
|
|
2852
|
+
], PermissionController.prototype, "delete", null);
|
|
2853
|
+
__decorate20([
|
|
2854
|
+
Get4("/role/:roleId"),
|
|
2855
|
+
__param6(0, Params4("roleId")),
|
|
2856
|
+
__metadata15("design:type", Function),
|
|
2857
|
+
__metadata15("design:paramtypes", [String]),
|
|
2858
|
+
__metadata15("design:returntype", Promise)
|
|
2859
|
+
], PermissionController.prototype, "getByRole", null);
|
|
2860
|
+
__decorate20([
|
|
2861
|
+
Get4("/roles/:permissionId"),
|
|
2862
|
+
__param6(0, Params4("permissionId")),
|
|
2863
|
+
__metadata15("design:type", Function),
|
|
2864
|
+
__metadata15("design:paramtypes", [String]),
|
|
2865
|
+
__metadata15("design:returntype", Promise)
|
|
2866
|
+
], PermissionController.prototype, "getRolesByPermission", null);
|
|
2867
|
+
__decorate20([
|
|
2868
|
+
Post4("/assign/:roleId/:permissionId"),
|
|
2869
|
+
__param6(0, Params4("roleId")),
|
|
2870
|
+
__param6(1, Params4("permissionId")),
|
|
2871
|
+
__metadata15("design:type", Function),
|
|
2872
|
+
__metadata15("design:paramtypes", [String, String]),
|
|
2873
|
+
__metadata15("design:returntype", Promise)
|
|
2874
|
+
], PermissionController.prototype, "assignToRole", null);
|
|
2875
|
+
__decorate20([
|
|
2876
|
+
Delete3("/remove/:roleId/:permissionId"),
|
|
2877
|
+
__param6(0, Params4("roleId")),
|
|
2878
|
+
__param6(1, Params4("permissionId")),
|
|
2879
|
+
__metadata15("design:type", Function),
|
|
2880
|
+
__metadata15("design:paramtypes", [String, String]),
|
|
2881
|
+
__metadata15("design:returntype", Promise)
|
|
2882
|
+
], PermissionController.prototype, "removeFromRole", null);
|
|
2883
|
+
__decorate20([
|
|
2492
2884
|
Delete3(),
|
|
2493
|
-
isAdmin()
|
|
2494
|
-
], UserController.prototype, "deleteAll", 1);
|
|
2495
|
-
__decorateClass([
|
|
2496
|
-
Post4("/assign/:userId/:roleId"),
|
|
2497
2885
|
isAdmin(),
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2886
|
+
__metadata15("design:type", Function),
|
|
2887
|
+
__metadata15("design:paramtypes", []),
|
|
2888
|
+
__metadata15("design:returntype", Promise)
|
|
2889
|
+
], PermissionController.prototype, "deleteAll", null);
|
|
2890
|
+
PermissionController = __decorate20([
|
|
2891
|
+
Controller4("/permissions"),
|
|
2503
2892
|
isAdmin(),
|
|
2504
|
-
|
|
2505
|
-
],
|
|
2506
|
-
UserController = __decorateClass([
|
|
2507
|
-
Controller4("/users")
|
|
2508
|
-
], UserController);
|
|
2893
|
+
__metadata15("design:paramtypes", [typeof (_a34 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a34 : Object])
|
|
2894
|
+
], PermissionController);
|
|
2509
2895
|
|
|
2510
2896
|
// src/plugin.ts
|
|
2511
2897
|
var AuthPlugin = {
|
|
2512
2898
|
name: "najm-auth",
|
|
2513
|
-
version: "0.1.3",
|
|
2514
2899
|
database: "default",
|
|
2515
2900
|
controllers: [
|
|
2516
2901
|
UserController,
|
|
@@ -2539,16 +2924,7 @@ var AuthPlugin = {
|
|
|
2539
2924
|
PermissionValidator,
|
|
2540
2925
|
RoleGuards,
|
|
2541
2926
|
PermissionGuards
|
|
2542
|
-
]
|
|
2543
|
-
onSetup: async () => {
|
|
2544
|
-
console.log(" \u2713 najm-auth plugin initialized");
|
|
2545
|
-
console.log(" - Authentication endpoints ready");
|
|
2546
|
-
console.log(" - Authorization system active");
|
|
2547
|
-
console.log(" - Database connection established");
|
|
2548
|
-
},
|
|
2549
|
-
onTeardown: async () => {
|
|
2550
|
-
console.log(" \u2713 najm-auth plugin cleanup complete");
|
|
2551
|
-
}
|
|
2927
|
+
]
|
|
2552
2928
|
};
|
|
2553
2929
|
export {
|
|
2554
2930
|
AuthController,
|
|
@@ -2684,19 +3060,19 @@ export {
|
|
|
2684
3060
|
semesterEnum,
|
|
2685
3061
|
settingsSchema,
|
|
2686
3062
|
studentSchema,
|
|
2687
|
-
studentStatusEnum,
|
|
3063
|
+
studentStatusEnum2 as studentStatusEnum,
|
|
2688
3064
|
subjectSchema,
|
|
2689
3065
|
submissionTypeEnum,
|
|
2690
3066
|
teacherFullSchema,
|
|
2691
3067
|
teacherPersonalSchema,
|
|
2692
3068
|
teacherProfessionalSchema,
|
|
2693
3069
|
teacherStatusEnum,
|
|
2694
|
-
tokenStatusEnum,
|
|
2695
|
-
tokenTypeEnum,
|
|
3070
|
+
tokenStatusEnum2 as tokenStatusEnum,
|
|
3071
|
+
tokenTypeEnum2 as tokenTypeEnum,
|
|
2696
3072
|
tokensTable,
|
|
2697
3073
|
trackerModeEnum,
|
|
2698
3074
|
userSchema,
|
|
2699
|
-
userStatusEnum,
|
|
3075
|
+
userStatusEnum2 as userStatusEnum,
|
|
2700
3076
|
userTypeEnum,
|
|
2701
3077
|
usersTable,
|
|
2702
3078
|
vehicleDocumentTypeEnum,
|