najm-auth 1.1.1

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.
package/dist/index.js ADDED
@@ -0,0 +1,3201 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+
8
+ // src/AuthPlugin.ts
9
+ import { Err as Err8, plugin } from "najm-core";
10
+ import { cache } from "najm-cache";
11
+
12
+ // src/auth.tokens.ts
13
+ var AUTH_CONFIG = /* @__PURE__ */ Symbol("auth:config");
14
+ var AUTH_SCHEMA = /* @__PURE__ */ Symbol("auth:schema");
15
+ var AUTH_USER = /* @__PURE__ */ Symbol("auth:user");
16
+ var AUTH_ROLE = /* @__PURE__ */ Symbol("auth:role");
17
+ var AUTH_PERMISSIONS = /* @__PURE__ */ Symbol("auth:permissions");
18
+
19
+ // src/schema/pg.ts
20
+ import { pgTable, text, boolean, timestamp, pgEnum, primaryKey } from "drizzle-orm/pg-core";
21
+ import { sql } from "drizzle-orm";
22
+ import { nanoid } from "nanoid";
23
+
24
+ // src/schema/constants.ts
25
+ var USER_STATUS = ["active", "inactive", "pending"];
26
+ var TOKEN_STATUS = ["active", "revoked", "expired"];
27
+ var TOKEN_TYPE = ["access", "refresh"];
28
+
29
+ // src/schema/pg.ts
30
+ var baseFields = /* @__PURE__ */ __name((idLength = 5) => ({
31
+ id: text("id").primaryKey().$defaultFn(() => nanoid(idLength)),
32
+ createdAt: timestamp("created_at", { mode: "string" }).defaultNow(),
33
+ updatedAt: timestamp("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql`CURRENT_TIMESTAMP`)
34
+ }), "baseFields");
35
+ var userStatusEnum = pgEnum("user_status", USER_STATUS);
36
+ var tokenStatusEnum = pgEnum("token_status", TOKEN_STATUS);
37
+ var tokenTypeEnum = pgEnum("token_type", TOKEN_TYPE);
38
+ var rolesTable = pgTable("roles", {
39
+ ...baseFields(5),
40
+ name: text("name").notNull(),
41
+ description: text("description")
42
+ });
43
+ var usersTable = pgTable("users", {
44
+ ...baseFields(8),
45
+ email: text("email").notNull().unique(),
46
+ emailVerified: boolean("email_verified").default(false),
47
+ password: text("password").notNull(),
48
+ image: text("image").default("noavatar.png"),
49
+ status: userStatusEnum("status").default("pending"),
50
+ roleId: text("role_id").references(() => rolesTable.id),
51
+ lastLogin: timestamp("last_login", { mode: "string" })
52
+ });
53
+ var permissionsTable = pgTable("permissions", {
54
+ ...baseFields(5),
55
+ name: text("name").notNull().unique(),
56
+ description: text("description"),
57
+ resource: text("resource").notNull(),
58
+ action: text("action").notNull()
59
+ });
60
+ var tokensTable = pgTable("tokens", {
61
+ ...baseFields(10),
62
+ userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }).unique().notNull(),
63
+ token: text("token").notNull(),
64
+ type: tokenTypeEnum("type").default("refresh"),
65
+ status: tokenStatusEnum("status").default("active"),
66
+ expiresAt: timestamp("expires_at", { mode: "string" }).notNull()
67
+ });
68
+ var rolePermissionsTable = pgTable("role_permissions", {
69
+ ...baseFields(10),
70
+ roleId: text("role_id").notNull().references(() => rolesTable.id, { onDelete: "cascade" }),
71
+ permissionId: text("permission_id").notNull().references(() => permissionsTable.id, { onDelete: "cascade" })
72
+ }, (table) => ({
73
+ pk: primaryKey({ columns: [table.roleId, table.permissionId] })
74
+ }));
75
+ var authSchema = {
76
+ users: usersTable,
77
+ tokens: tokensTable,
78
+ roles: rolesTable,
79
+ permissions: permissionsTable,
80
+ rolePermissions: rolePermissionsTable
81
+ };
82
+
83
+ // src/schema/sqlite.ts
84
+ import { sqliteTable, text as text2, integer, uniqueIndex } from "drizzle-orm/sqlite-core";
85
+ import { sql as sql2 } from "drizzle-orm";
86
+ import { nanoid as nanoid2 } from "nanoid";
87
+ var baseFields2 = /* @__PURE__ */ __name((idLength = 5) => ({
88
+ id: text2("id").primaryKey().$defaultFn(() => nanoid2(idLength)),
89
+ createdAt: text2("created_at").$defaultFn(() => (/* @__PURE__ */ new Date()).toISOString()),
90
+ updatedAt: text2("updated_at").$defaultFn(() => (/* @__PURE__ */ new Date()).toISOString()).$onUpdate(() => sql2`(datetime('now'))`)
91
+ }), "baseFields");
92
+ var rolesTable2 = sqliteTable("roles", {
93
+ ...baseFields2(5),
94
+ name: text2("name").notNull(),
95
+ description: text2("description")
96
+ });
97
+ var usersTable2 = sqliteTable("users", {
98
+ ...baseFields2(8),
99
+ email: text2("email").notNull().unique(),
100
+ emailVerified: integer("email_verified", { mode: "boolean" }).default(false),
101
+ password: text2("password").notNull(),
102
+ image: text2("image").default("noavatar.png"),
103
+ status: text2("status").$type().default("pending"),
104
+ roleId: text2("role_id").references(() => rolesTable2.id),
105
+ lastLogin: text2("last_login")
106
+ });
107
+ var permissionsTable2 = sqliteTable("permissions", {
108
+ ...baseFields2(5),
109
+ name: text2("name").notNull().unique(),
110
+ description: text2("description"),
111
+ resource: text2("resource").notNull(),
112
+ action: text2("action").notNull()
113
+ });
114
+ var tokensTable2 = sqliteTable("tokens", {
115
+ ...baseFields2(10),
116
+ userId: text2("user_id").references(() => usersTable2.id, { onDelete: "cascade" }).unique().notNull(),
117
+ token: text2("token").notNull(),
118
+ type: text2("type").$type().default("refresh"),
119
+ status: text2("status").$type().default("active"),
120
+ expiresAt: text2("expires_at").notNull()
121
+ });
122
+ var rolePermissionsTable2 = sqliteTable("role_permissions", {
123
+ ...baseFields2(10),
124
+ roleId: text2("role_id").notNull().references(() => rolesTable2.id, { onDelete: "cascade" }),
125
+ permissionId: text2("permission_id").notNull().references(() => permissionsTable2.id, { onDelete: "cascade" })
126
+ }, (table) => ({
127
+ uniq: uniqueIndex("role_permission_unique").on(table.roleId, table.permissionId)
128
+ }));
129
+ var authSchema2 = {
130
+ users: usersTable2,
131
+ tokens: tokensTable2,
132
+ roles: rolesTable2,
133
+ permissions: permissionsTable2,
134
+ rolePermissions: rolePermissionsTable2
135
+ };
136
+
137
+ // src/schema/mysql.ts
138
+ import { mysqlTable, varchar, boolean as boolean2, timestamp as timestamp2, mysqlEnum, primaryKey as primaryKey2 } from "drizzle-orm/mysql-core";
139
+ import { sql as sql3 } from "drizzle-orm";
140
+ import { nanoid as nanoid3 } from "nanoid";
141
+ var baseFields3 = /* @__PURE__ */ __name((idLength = 5) => ({
142
+ id: varchar("id", { length: 21 }).primaryKey().$defaultFn(() => nanoid3(idLength)),
143
+ createdAt: timestamp2("created_at", { mode: "string" }).defaultNow(),
144
+ updatedAt: timestamp2("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql3`CURRENT_TIMESTAMP`)
145
+ }), "baseFields");
146
+ var rolesTable3 = mysqlTable("roles", {
147
+ ...baseFields3(5),
148
+ name: varchar("name", { length: 255 }).notNull(),
149
+ description: varchar("description", { length: 1e3 })
150
+ });
151
+ var usersTable3 = mysqlTable("users", {
152
+ ...baseFields3(8),
153
+ email: varchar("email", { length: 255 }).notNull().unique(),
154
+ emailVerified: boolean2("email_verified").default(false),
155
+ password: varchar("password", { length: 255 }).notNull(),
156
+ image: varchar("image", { length: 255 }).default("noavatar.png"),
157
+ status: mysqlEnum("status", [...USER_STATUS]).default("pending"),
158
+ roleId: varchar("role_id", { length: 21 }).references(() => rolesTable3.id),
159
+ lastLogin: timestamp2("last_login", { mode: "string" })
160
+ });
161
+ var permissionsTable3 = mysqlTable("permissions", {
162
+ ...baseFields3(5),
163
+ name: varchar("name", { length: 255 }).notNull().unique(),
164
+ description: varchar("description", { length: 1e3 }),
165
+ resource: varchar("resource", { length: 255 }).notNull(),
166
+ action: varchar("action", { length: 255 }).notNull()
167
+ });
168
+ var tokensTable3 = mysqlTable("tokens", {
169
+ ...baseFields3(10),
170
+ userId: varchar("user_id", { length: 21 }).references(() => usersTable3.id, { onDelete: "cascade" }).unique().notNull(),
171
+ token: varchar("token", { length: 500 }).notNull(),
172
+ type: mysqlEnum("type", [...TOKEN_TYPE]).default("refresh"),
173
+ status: mysqlEnum("status", [...TOKEN_STATUS]).default("active"),
174
+ expiresAt: timestamp2("expires_at", { mode: "string" }).notNull()
175
+ });
176
+ var rolePermissionsTable3 = mysqlTable("role_permissions", {
177
+ ...baseFields3(10),
178
+ roleId: varchar("role_id", { length: 21 }).notNull().references(() => rolesTable3.id, { onDelete: "cascade" }),
179
+ permissionId: varchar("permission_id", { length: 21 }).notNull().references(() => permissionsTable3.id, { onDelete: "cascade" })
180
+ }, (table) => ({
181
+ pk: primaryKey2({ columns: [table.roleId, table.permissionId] })
182
+ }));
183
+ var authSchema3 = {
184
+ users: usersTable3,
185
+ tokens: tokensTable3,
186
+ roles: rolesTable3,
187
+ permissions: permissionsTable3,
188
+ rolePermissions: rolePermissionsTable3
189
+ };
190
+
191
+ // src/auth/index.ts
192
+ var auth_exports = {};
193
+ __export(auth_exports, {
194
+ AUTH_MODULE: () => AUTH_MODULE,
195
+ AuthController: () => AuthController,
196
+ AuthGuard: () => AuthGuard,
197
+ AuthService: () => AuthService,
198
+ CookieManager: () => CookieManager,
199
+ EncryptionService: () => EncryptionService,
200
+ isAuth: () => isAuth
201
+ });
202
+
203
+ // src/auth/EncryptionService.ts
204
+ import { Injectable } from "najm-core";
205
+ import bcrypt from "bcryptjs";
206
+ var __decorate = function(decorators, target, key, desc) {
207
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
208
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
209
+ 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;
210
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
211
+ };
212
+ var __metadata = function(k, v) {
213
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
214
+ };
215
+ var EncryptionService = class EncryptionService2 {
216
+ static {
217
+ __name(this, "EncryptionService");
218
+ }
219
+ constructor() {
220
+ }
221
+ async hashPassword(password) {
222
+ return bcrypt.hash(password, 10);
223
+ }
224
+ async comparePassword(password, hashedPassword) {
225
+ return bcrypt.compare(password, hashedPassword);
226
+ }
227
+ };
228
+ EncryptionService = __decorate([
229
+ Injectable(),
230
+ __metadata("design:paramtypes", [])
231
+ ], EncryptionService);
232
+
233
+ // src/auth/CookieManager.ts
234
+ import { Service, Inject } from "najm-core";
235
+ import { CookieService } from "najm-cookies";
236
+ import timestring from "timestring";
237
+ var __decorate2 = function(decorators, target, key, desc) {
238
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
239
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
240
+ 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;
241
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
242
+ };
243
+ var __metadata2 = function(k, v) {
244
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
245
+ };
246
+ var _a;
247
+ var CookieManager = class CookieManager2 {
248
+ static {
249
+ __name(this, "CookieManager");
250
+ }
251
+ config;
252
+ cookieService;
253
+ get cookieName() {
254
+ return this.config.refreshCookieName || "refreshToken";
255
+ }
256
+ setRefreshToken(refreshToken) {
257
+ const maxAge = timestring(this.config.jwt.refreshExpiresIn, "s");
258
+ this.cookieService.set(this.cookieName, refreshToken, { maxAge });
259
+ }
260
+ clearRefreshToken() {
261
+ this.cookieService.delete(this.cookieName);
262
+ }
263
+ getRefreshToken() {
264
+ return this.cookieService.get(this.cookieName);
265
+ }
266
+ hasRefreshToken() {
267
+ return this.cookieService.has(this.cookieName);
268
+ }
269
+ getCookieName() {
270
+ return this.cookieName;
271
+ }
272
+ };
273
+ __decorate2([
274
+ Inject(AUTH_CONFIG),
275
+ __metadata2("design:type", Object)
276
+ ], CookieManager.prototype, "config", void 0);
277
+ __decorate2([
278
+ Inject(CookieService),
279
+ __metadata2("design:type", typeof (_a = typeof CookieService !== "undefined" && CookieService) === "function" ? _a : Object)
280
+ ], CookieManager.prototype, "cookieService", void 0);
281
+ CookieManager = __decorate2([
282
+ Service()
283
+ ], CookieManager);
284
+
285
+ // src/auth/AuthController.ts
286
+ import { Controller } from "najm-core";
287
+ import { Get, Post, ResMsg } from "najm-core";
288
+ import { Body, User, Headers as Headers2 } from "najm-core";
289
+
290
+ // src/auth/AuthService.ts
291
+ import { Injectable as Injectable7 } from "najm-core";
292
+ import { Err as Err6, Log } from "najm-core";
293
+ import { I18n as I18n4, I18nService as I18nService2 } from "najm-i18n";
294
+ import { EmailService, passwordResetTemplate } from "najm-email";
295
+
296
+ // src/users/UserService.ts
297
+ import { Injectable as Injectable5, Inject as Inject4 } from "najm-core";
298
+ import { Transaction } from "najm-database";
299
+ import { I18nService } from "najm-i18n";
300
+
301
+ // src/users/UserRepository.ts
302
+ import { eq as eq2, ne } from "drizzle-orm";
303
+ import { Repository, Inject as Inject2 } from "najm-core";
304
+ import { DB } from "najm-database";
305
+
306
+ // src/shared/queries.ts
307
+ import { eq } from "drizzle-orm";
308
+ var AuthQueries = class {
309
+ static {
310
+ __name(this, "AuthQueries");
311
+ }
312
+ db;
313
+ schema;
314
+ constructor(db, schema) {
315
+ this.db = db;
316
+ this.schema = schema;
317
+ }
318
+ /**
319
+ * Standard user selection fields with role join
320
+ */
321
+ userSelection() {
322
+ return {
323
+ id: this.schema.users.id,
324
+ email: this.schema.users.email,
325
+ emailVerified: this.schema.users.emailVerified,
326
+ image: this.schema.users.image,
327
+ status: this.schema.users.status,
328
+ roleId: this.schema.users.roleId,
329
+ role: this.schema.roles.name,
330
+ createdAt: this.schema.users.createdAt,
331
+ updatedAt: this.schema.users.updatedAt
332
+ };
333
+ }
334
+ /**
335
+ * Get permissions for a user by their userId
336
+ */
337
+ async getUserPermissions(userId) {
338
+ const [user] = await this.db.select({ roleId: this.schema.users.roleId }).from(this.schema.users).where(eq(this.schema.users.id, userId)).limit(1);
339
+ if (!user?.roleId)
340
+ return [];
341
+ const perms = await this.db.select({ name: this.schema.permissions.name }).from(this.schema.rolePermissions).leftJoin(this.schema.permissions, eq(this.schema.rolePermissions.permissionId, this.schema.permissions.id)).where(eq(this.schema.rolePermissions.roleId, user.roleId));
342
+ return perms.map((p) => p.name).filter(Boolean);
343
+ }
344
+ /**
345
+ * Get role name for a user
346
+ */
347
+ async getRoleName(userId) {
348
+ const [role] = await this.db.select({ roleName: this.schema.roles.name }).from(this.schema.users).leftJoin(this.schema.roles, eq(this.schema.users.roleId, this.schema.roles.id)).where(eq(this.schema.users.id, userId)).limit(1);
349
+ return role?.roleName ?? null;
350
+ }
351
+ /**
352
+ * Batch load permissions for multiple users (fixes N+1 query problem)
353
+ * Returns a Map of roleId -> permissions[]
354
+ */
355
+ async batchLoadPermissionsByRole() {
356
+ const allPermissions = await this.db.select({
357
+ roleId: this.schema.rolePermissions.roleId,
358
+ name: this.schema.permissions.name
359
+ }).from(this.schema.rolePermissions).leftJoin(this.schema.permissions, eq(this.schema.rolePermissions.permissionId, this.schema.permissions.id));
360
+ const permissionsByRole = /* @__PURE__ */ new Map();
361
+ for (const p of allPermissions) {
362
+ if (!p.name)
363
+ continue;
364
+ const list = permissionsByRole.get(p.roleId) || [];
365
+ list.push(p.name);
366
+ permissionsByRole.set(p.roleId, list);
367
+ }
368
+ return permissionsByRole;
369
+ }
370
+ };
371
+
372
+ // src/roles/constants.ts
373
+ var ROLES = {
374
+ ADMIN: "admin"
375
+ };
376
+ var ROLE_GROUPS = {
377
+ ADMINISTRATORS: [ROLES.ADMIN]
378
+ };
379
+
380
+ // src/users/UserRepository.ts
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 __metadata3 = function(k, v) {
388
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
389
+ };
390
+ var UserRepository = class UserRepository2 {
391
+ static {
392
+ __name(this, "UserRepository");
393
+ }
394
+ db;
395
+ schema;
396
+ get users() {
397
+ return this.schema.users;
398
+ }
399
+ get roles() {
400
+ return this.schema.roles;
401
+ }
402
+ /** Shared query helper */
403
+ get q() {
404
+ return new AuthQueries(this.db, this.schema);
405
+ }
406
+ async getAll() {
407
+ const allUsers = await this.db.select(this.q.userSelection()).from(this.users).leftJoin(this.roles, eq2(this.users.roleId, this.roles.id));
408
+ const permissionsByRole = await this.q.batchLoadPermissionsByRole();
409
+ return allUsers.map((user) => ({
410
+ ...user,
411
+ permissions: user.roleId ? permissionsByRole.get(user.roleId) ?? [] : []
412
+ }));
413
+ }
414
+ async getById(id) {
415
+ const [user] = await this.db.select(this.q.userSelection()).from(this.users).leftJoin(this.roles, eq2(this.users.roleId, this.roles.id)).where(eq2(this.users.id, id)).limit(1);
416
+ if (!user)
417
+ return user;
418
+ return {
419
+ ...user,
420
+ permissions: await this.q.getUserPermissions(user.id)
421
+ };
422
+ }
423
+ async getByEmail(email2) {
424
+ const [existingUser] = await this.db.select({
425
+ ...this.q.userSelection(),
426
+ password: this.users.password
427
+ }).from(this.users).leftJoin(this.roles, eq2(this.users.roleId, this.roles.id)).where(eq2(this.users.email, email2));
428
+ return existingUser;
429
+ }
430
+ async create(data) {
431
+ const [newUser] = await this.db.insert(this.users).values(data).returning();
432
+ return newUser;
433
+ }
434
+ async update(id, data) {
435
+ const [updatedUser] = await this.db.update(this.users).set(data).where(eq2(this.users.id, id)).returning();
436
+ return updatedUser;
437
+ }
438
+ async delete(id) {
439
+ const [deletedUser] = await this.db.delete(this.users).where(eq2(this.users.id, id)).returning();
440
+ return deletedUser;
441
+ }
442
+ async deleteAll() {
443
+ const adminRole = await this.db.select({ id: this.roles.id }).from(this.roles).where(eq2(this.roles.name, ROLES.ADMIN)).limit(1);
444
+ if (adminRole.length === 0) {
445
+ const deletedUsers2 = await this.db.delete(this.users).returning();
446
+ return deletedUsers2;
447
+ }
448
+ const deletedUsers = await this.db.delete(this.users).where(ne(this.users.roleId, adminRole[0].id)).returning();
449
+ return deletedUsers;
450
+ }
451
+ async getRoleNameById(userId) {
452
+ return this.q.getRoleName(userId);
453
+ }
454
+ async getUserPassword(email2) {
455
+ const [user] = await this.db.select({
456
+ id: this.users.id,
457
+ email: this.users.email,
458
+ password: this.users.password
459
+ }).from(this.users).where(eq2(this.users.email, email2)).limit(1);
460
+ return user?.password;
461
+ }
462
+ async getUserPermissions(userId) {
463
+ return this.q.getUserPermissions(userId);
464
+ }
465
+ };
466
+ __decorate3([
467
+ DB(),
468
+ __metadata3("design:type", Object)
469
+ ], UserRepository.prototype, "db", void 0);
470
+ __decorate3([
471
+ Inject2(AUTH_SCHEMA),
472
+ __metadata3("design:type", Object)
473
+ ], UserRepository.prototype, "schema", void 0);
474
+ UserRepository = __decorate3([
475
+ Repository()
476
+ ], UserRepository);
477
+
478
+ // src/users/UserValidator.ts
479
+ import { Injectable as Injectable2 } from "najm-core";
480
+ import { Err } from "najm-core";
481
+ import { I18n } from "najm-i18n";
482
+ var __decorate4 = function(decorators, target, key, desc) {
483
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
484
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
485
+ 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;
486
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
487
+ };
488
+ var __metadata4 = function(k, v) {
489
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
490
+ };
491
+ var _a2;
492
+ var _b;
493
+ var UserValidator = class UserValidator2 {
494
+ static {
495
+ __name(this, "UserValidator");
496
+ }
497
+ userRepository;
498
+ encryptionService;
499
+ t;
500
+ constructor(userRepository, encryptionService) {
501
+ this.userRepository = userRepository;
502
+ this.encryptionService = encryptionService;
503
+ }
504
+ /**
505
+ * Check if email already exists in database
506
+ */
507
+ async checkEmailUnique(email2, excludeId) {
508
+ if (!email2)
509
+ return;
510
+ const existingUser = await this.userRepository.getByEmail(email2);
511
+ if (existingUser && existingUser.id !== excludeId) {
512
+ Err(this.t("errors.emailExists"), 409);
513
+ }
514
+ }
515
+ /**
516
+ * Check if user exists by ID
517
+ */
518
+ async checkUserExists(id) {
519
+ const user = await this.userRepository.getById(id);
520
+ if (!user) {
521
+ Err(this.t("errors.notFound"), 404);
522
+ }
523
+ return user;
524
+ }
525
+ /**
526
+ * Check if user exists by email
527
+ */
528
+ async checkUserExistsByEmail(email2) {
529
+ const user = await this.userRepository.getByEmail(email2);
530
+ if (!user) {
531
+ Err(this.t("errors.invalidCredentials"), 401);
532
+ }
533
+ return user;
534
+ }
535
+ /**
536
+ * Check if email exists in database
537
+ */
538
+ async checkEmailExists(email2) {
539
+ const user = await this.userRepository.getByEmail(email2);
540
+ if (!user) {
541
+ Err(this.t("errors.notFound"), 404);
542
+ }
543
+ return user;
544
+ }
545
+ /**
546
+ * Verify password against hashed password (throws on invalid)
547
+ */
548
+ async checkPasswordValid(password, hashedPassword) {
549
+ const isPasswordValid = await this.encryptionService.comparePassword(password, hashedPassword);
550
+ if (!isPasswordValid) {
551
+ Err(this.t("auth.errors.invalidCredentials"), 401);
552
+ }
553
+ }
554
+ /**
555
+ * Compare password against hash - returns boolean (no throw)
556
+ * Used for timing-safe authentication
557
+ */
558
+ async comparePassword(password, hashedPassword) {
559
+ return await this.encryptionService.comparePassword(password, hashedPassword);
560
+ }
561
+ /**
562
+ * Check if user ID is unique (for custom IDs)
563
+ */
564
+ async checkUserIdIsUnique(id) {
565
+ if (!id)
566
+ return;
567
+ const existingUser = await this.userRepository.getById(id);
568
+ if (existingUser) {
569
+ Err(this.t("errors.idExists"), 409);
570
+ }
571
+ }
572
+ /**
573
+ * Check if user has required role
574
+ */
575
+ async hasRole(userId, roles) {
576
+ const roleName = await this.userRepository.getRoleNameById(userId);
577
+ if (!roleName) {
578
+ Err(this.t("errors.accessDenied"), 403);
579
+ }
580
+ const hasRole = roles.some((item) => roleName.toLowerCase() === item.toLowerCase());
581
+ if (!hasRole) {
582
+ Err(this.t("errors.accessDenied"), 403);
583
+ }
584
+ return true;
585
+ }
586
+ /**
587
+ * Validate password strength and complexity
588
+ * Enforces:
589
+ * - Minimum 8 characters
590
+ * - At least one uppercase letter
591
+ * - At least one lowercase letter
592
+ * - At least one number
593
+ */
594
+ validatePasswordStrength(password) {
595
+ if (!password) {
596
+ Err("Password is required", 400);
597
+ }
598
+ const minLength = 8;
599
+ const hasUppercase = /[A-Z]/.test(password);
600
+ const hasLowercase = /[a-z]/.test(password);
601
+ const hasNumber = /\d/.test(password);
602
+ if (password.length < minLength) {
603
+ Err(`Password must be at least ${minLength} characters long`, 400);
604
+ }
605
+ if (!hasUppercase) {
606
+ Err("Password must contain at least one uppercase letter", 400);
607
+ }
608
+ if (!hasLowercase) {
609
+ Err("Password must contain at least one lowercase letter", 400);
610
+ }
611
+ if (!hasNumber) {
612
+ Err("Password must contain at least one number", 400);
613
+ }
614
+ }
615
+ };
616
+ __decorate4([
617
+ I18n("users"),
618
+ __metadata4("design:type", Object)
619
+ ], UserValidator.prototype, "t", void 0);
620
+ UserValidator = __decorate4([
621
+ Injectable2(),
622
+ __metadata4("design:paramtypes", [typeof (_a2 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _a2 : Object, typeof (_b = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b : Object])
623
+ ], UserValidator);
624
+
625
+ // src/roles/RoleService.ts
626
+ import { Injectable as Injectable4 } from "najm-core";
627
+
628
+ // src/roles/RoleRepository.ts
629
+ import { eq as eq3 } from "drizzle-orm";
630
+ import { Repository as Repository2, Inject as Inject3 } from "najm-core";
631
+ import { DB as DB2 } from "najm-database";
632
+ var __decorate5 = function(decorators, target, key, desc) {
633
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
634
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
635
+ 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;
636
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
637
+ };
638
+ var __metadata5 = function(k, v) {
639
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
640
+ };
641
+ var RoleRepository = class RoleRepository2 {
642
+ static {
643
+ __name(this, "RoleRepository");
644
+ }
645
+ db;
646
+ schema;
647
+ get roles() {
648
+ return this.schema.roles;
649
+ }
650
+ async getAll() {
651
+ return await this.db.select().from(this.roles);
652
+ }
653
+ async getById(id) {
654
+ const [existingRole] = await this.db.select().from(this.roles).where(eq3(this.roles.id, id));
655
+ return existingRole;
656
+ }
657
+ async getByName(name) {
658
+ const [existingRole] = await this.db.select().from(this.roles).where(eq3(this.roles.name, name));
659
+ return existingRole;
660
+ }
661
+ async create(data) {
662
+ const [newRole] = await this.db.insert(this.roles).values(data).returning();
663
+ return newRole;
664
+ }
665
+ async update(id, data) {
666
+ const [updatedRole] = await this.db.update(this.roles).set(data).where(eq3(this.roles.id, id)).returning();
667
+ return updatedRole;
668
+ }
669
+ async delete(id) {
670
+ const [deletedRole] = await this.db.delete(this.roles).where(eq3(this.roles.id, id)).returning();
671
+ return deletedRole;
672
+ }
673
+ };
674
+ __decorate5([
675
+ DB2(),
676
+ __metadata5("design:type", Object)
677
+ ], RoleRepository.prototype, "db", void 0);
678
+ __decorate5([
679
+ Inject3(AUTH_SCHEMA),
680
+ __metadata5("design:type", Object)
681
+ ], RoleRepository.prototype, "schema", void 0);
682
+ RoleRepository = __decorate5([
683
+ Repository2()
684
+ ], RoleRepository);
685
+
686
+ // src/roles/RoleValidator.ts
687
+ import { Injectable as Injectable3 } from "najm-core";
688
+ import { I18n as I18n2 } from "najm-i18n";
689
+ import { Err as Err2 } from "najm-core";
690
+ var __decorate6 = function(decorators, target, key, desc) {
691
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
692
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
693
+ 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;
694
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
695
+ };
696
+ var __metadata6 = function(k, v) {
697
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
698
+ };
699
+ var _a3;
700
+ var RoleValidator = class RoleValidator2 {
701
+ static {
702
+ __name(this, "RoleValidator");
703
+ }
704
+ roleRepository;
705
+ t;
706
+ constructor(roleRepository) {
707
+ this.roleRepository = roleRepository;
708
+ }
709
+ /**
710
+ * Check if role name is unique
711
+ */
712
+ async checkNameUnique(roleName, excludeId) {
713
+ if (!roleName)
714
+ return;
715
+ const existingRole = await this.roleRepository.getByName(roleName);
716
+ if (existingRole && existingRole.id !== excludeId) {
717
+ Err2(this.t("errors.exists"), 409);
718
+ }
719
+ }
720
+ /**
721
+ * Check if role exists by ID
722
+ */
723
+ async checkRoleExists(id) {
724
+ const role = await this.roleRepository.getById(id);
725
+ if (!role) {
726
+ Err2(this.t("errors.notFound"), 404);
727
+ }
728
+ return role;
729
+ }
730
+ /**
731
+ * Check if role exists by name
732
+ */
733
+ async checkRoleExistsByName(roleName) {
734
+ const role = await this.roleRepository.getByName(roleName);
735
+ if (!role) {
736
+ Err2(this.t("errors.notFound"), 404);
737
+ }
738
+ return role;
739
+ }
740
+ /**
741
+ * Check if admin role exists (required for system setup)
742
+ */
743
+ async checkAdminRoleExists() {
744
+ const adminRole = await this.roleRepository.getByName(ROLES.ADMIN);
745
+ if (!adminRole) {
746
+ Err2(this.t("errors.adminRoleNotFound"), 500);
747
+ }
748
+ return adminRole;
749
+ }
750
+ /**
751
+ * Check if role name exists (returns boolean, doesn't throw)
752
+ */
753
+ async isRoleNameExists(roleName) {
754
+ const existingRole = await this.roleRepository.getByName(roleName);
755
+ return !!existingRole;
756
+ }
757
+ };
758
+ __decorate6([
759
+ I18n2("roles"),
760
+ __metadata6("design:type", Object)
761
+ ], RoleValidator.prototype, "t", void 0);
762
+ RoleValidator = __decorate6([
763
+ Injectable3(),
764
+ __metadata6("design:paramtypes", [typeof (_a3 = typeof RoleRepository !== "undefined" && RoleRepository) === "function" ? _a3 : Object])
765
+ ], RoleValidator);
766
+
767
+ // src/roles/RoleService.ts
768
+ var __decorate7 = function(decorators, target, key, desc) {
769
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
770
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
771
+ 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;
772
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
773
+ };
774
+ var __metadata7 = function(k, v) {
775
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
776
+ };
777
+ var _a4;
778
+ var _b2;
779
+ var RoleService = class RoleService2 {
780
+ static {
781
+ __name(this, "RoleService");
782
+ }
783
+ roleRepository;
784
+ roleValidator;
785
+ constructor(roleRepository, roleValidator) {
786
+ this.roleRepository = roleRepository;
787
+ this.roleValidator = roleValidator;
788
+ }
789
+ async getAll() {
790
+ return await this.roleRepository.getAll();
791
+ }
792
+ async getById(id) {
793
+ await this.roleValidator.checkRoleExists(id);
794
+ return await this.roleRepository.getById(id);
795
+ }
796
+ async getByName(name) {
797
+ return await this.roleRepository.getByName(name);
798
+ }
799
+ async create(data) {
800
+ await this.roleValidator.checkNameUnique(data.name);
801
+ return await this.roleRepository.create(data);
802
+ }
803
+ async update(id, data) {
804
+ await this.roleValidator.checkRoleExists(id);
805
+ await this.roleValidator.checkNameUnique(data.name, id);
806
+ return await this.roleRepository.update(id, data);
807
+ }
808
+ async delete(id) {
809
+ await this.roleValidator.checkRoleExists(id);
810
+ return await this.roleRepository.delete(id);
811
+ }
812
+ async seedDefaultRoles(defaultRoles) {
813
+ const rolesToCreate = [];
814
+ for (const role of defaultRoles) {
815
+ const exists = await this.roleValidator.isRoleNameExists(role.name);
816
+ if (!exists) {
817
+ rolesToCreate.push(role);
818
+ }
819
+ }
820
+ const createdRoles = await Promise.all(rolesToCreate.map((role) => this.roleRepository.create(role)));
821
+ return createdRoles;
822
+ }
823
+ async getRoleIdByName(name) {
824
+ const role = await this.getByName(name);
825
+ return role?.id;
826
+ }
827
+ };
828
+ RoleService = __decorate7([
829
+ Injectable4(),
830
+ __metadata7("design:paramtypes", [typeof (_a4 = typeof RoleRepository !== "undefined" && RoleRepository) === "function" ? _a4 : Object, typeof (_b2 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b2 : Object])
831
+ ], RoleService);
832
+
833
+ // src/users/UserService.ts
834
+ import { nanoid as nanoid4 } from "nanoid";
835
+
836
+ // src/shared/index.ts
837
+ import * as fs from "fs/promises";
838
+ import * as path from "path";
839
+ import _isEmpty from "lodash.isempty";
840
+ import { Err as Err3 } from "najm-core";
841
+ var avatarsPath = path.join(process.cwd(), "avatars");
842
+ var parseSchema = /* @__PURE__ */ __name(async (schema, data) => {
843
+ try {
844
+ return await schema.parseAsync(data);
845
+ } catch (error) {
846
+ const errors = error.issues || error.errors || [];
847
+ const errorMessage = errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
848
+ Err3(errorMessage);
849
+ }
850
+ }, "parseSchema");
851
+ var clean = /* @__PURE__ */ __name((obj) => {
852
+ const cleaned = {};
853
+ for (const [key, value] of Object.entries(obj)) {
854
+ if (value !== null && value !== void 0 && value !== "") {
855
+ cleaned[key] = value;
856
+ }
857
+ }
858
+ return cleaned;
859
+ }, "clean");
860
+ var getAvatarFile = /* @__PURE__ */ __name(async (fileName) => {
861
+ try {
862
+ const filePath = path.join(avatarsPath, fileName);
863
+ const buffer = await fs.readFile(filePath);
864
+ const file = new File([buffer], fileName, {
865
+ type: "image/png"
866
+ });
867
+ return file;
868
+ } catch (error) {
869
+ return null;
870
+ }
871
+ }, "getAvatarFile");
872
+ var formatDate = /* @__PURE__ */ __name((dateValue) => {
873
+ if (!dateValue)
874
+ return null;
875
+ let date;
876
+ if (dateValue instanceof Date) {
877
+ date = dateValue;
878
+ } else if (typeof dateValue === "string") {
879
+ date = new Date(dateValue);
880
+ } else {
881
+ return null;
882
+ }
883
+ if (isNaN(date.getTime()))
884
+ return null;
885
+ return date.toISOString().split("T")[0];
886
+ }, "formatDate");
887
+ function calculateAge(dateOfBirth) {
888
+ if (!dateOfBirth)
889
+ return null;
890
+ const formattedDate = formatDate(dateOfBirth);
891
+ if (!formattedDate)
892
+ return null;
893
+ const birth = new Date(formattedDate);
894
+ const today = /* @__PURE__ */ new Date();
895
+ let age = today.getFullYear() - birth.getFullYear();
896
+ const monthDiff = today.getMonth() - birth.getMonth();
897
+ if (monthDiff < 0 || monthDiff === 0 && today.getDate() < birth.getDate()) {
898
+ age--;
899
+ }
900
+ return age;
901
+ }
902
+ __name(calculateAge, "calculateAge");
903
+ function calculateYearsOfExperience(hireDate) {
904
+ if (!hireDate)
905
+ return null;
906
+ const formattedDate = formatDate(hireDate);
907
+ if (!formattedDate)
908
+ return null;
909
+ const hire = new Date(formattedDate);
910
+ const today = /* @__PURE__ */ new Date();
911
+ let years = today.getFullYear() - hire.getFullYear();
912
+ const monthDiff = today.getMonth() - hire.getMonth();
913
+ if (monthDiff < 0 || monthDiff === 0 && today.getDate() < hire.getDate()) {
914
+ years--;
915
+ }
916
+ return years;
917
+ }
918
+ __name(calculateYearsOfExperience, "calculateYearsOfExperience");
919
+ function pickProps(source, keys) {
920
+ const result = {};
921
+ for (const key of keys) {
922
+ if (source[key] !== void 0) {
923
+ result[key] = source[key];
924
+ }
925
+ }
926
+ return result;
927
+ }
928
+ __name(pickProps, "pickProps");
929
+ var isEmpty = _isEmpty;
930
+ var isPath = /* @__PURE__ */ __name((img) => typeof img === "string" && img.trim().length > 0 && (img.startsWith("/") || img.startsWith("http") || img.startsWith("storage/")), "isPath");
931
+ var isFile = /* @__PURE__ */ __name((img) => !!img && typeof img !== "string" && img instanceof File, "isFile");
932
+
933
+ // src/users/UserService.ts
934
+ import { Err as Err4 } from "najm-core";
935
+ var __decorate8 = function(decorators, target, key, desc) {
936
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
937
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
938
+ 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;
939
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
940
+ };
941
+ var __metadata8 = function(k, v) {
942
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
943
+ };
944
+ var __param = function(paramIndex, decorator) {
945
+ return function(target, key) {
946
+ decorator(target, key, paramIndex);
947
+ };
948
+ };
949
+ var _a5;
950
+ var _b3;
951
+ var _c;
952
+ var _d;
953
+ var _e;
954
+ var _f;
955
+ var _g;
956
+ var _h;
957
+ var UserService = class UserService2 {
958
+ static {
959
+ __name(this, "UserService");
960
+ }
961
+ roleValidator;
962
+ roleService;
963
+ userRepository;
964
+ userValidator;
965
+ encryptionService;
966
+ i18nService;
967
+ authConfig;
968
+ constructor(roleValidator, roleService, userRepository, userValidator, encryptionService, i18nService, authConfig) {
969
+ this.roleValidator = roleValidator;
970
+ this.roleService = roleService;
971
+ this.userRepository = userRepository;
972
+ this.userValidator = userValidator;
973
+ this.encryptionService = encryptionService;
974
+ this.i18nService = i18nService;
975
+ this.authConfig = authConfig;
976
+ }
977
+ sanitizeUser(user) {
978
+ if (!user)
979
+ return user;
980
+ const { password, ...sanitizedUser } = user;
981
+ return sanitizedUser;
982
+ }
983
+ sanitizeUsers(users) {
984
+ return users.map((user) => this.sanitizeUser(user)).filter(Boolean);
985
+ }
986
+ async resolveUserRole(roleId, roleName) {
987
+ if (roleId) {
988
+ await this.roleValidator.checkRoleExists(roleId);
989
+ return roleId;
990
+ }
991
+ if (roleName) {
992
+ const roleByName = await this.roleService.getByName(roleName);
993
+ if (roleByName) {
994
+ return roleByName.id;
995
+ }
996
+ Err4(`Role '${roleName}' not found`);
997
+ }
998
+ if (this.authConfig.defaultRole) {
999
+ const defaultRole = await this.roleService.getByName(this.authConfig.defaultRole);
1000
+ if (!defaultRole) {
1001
+ Err4(`Default role '${this.authConfig.defaultRole}' not found. Create it first or set defaultRole to null in auth config.`);
1002
+ }
1003
+ return defaultRole.id;
1004
+ }
1005
+ return null;
1006
+ }
1007
+ async getAll() {
1008
+ const users = await this.userRepository.getAll();
1009
+ return this.sanitizeUsers(users);
1010
+ }
1011
+ async getById(id) {
1012
+ await this.userValidator.checkUserExists(id);
1013
+ const user = await this.userRepository.getById(id);
1014
+ return this.sanitizeUser(user);
1015
+ }
1016
+ async getByEmail(email2) {
1017
+ const user = await this.userValidator.checkUserExistsByEmail(email2);
1018
+ return this.sanitizeUser(user);
1019
+ }
1020
+ /**
1021
+ * Find user by email without throwing - returns null if not found
1022
+ * Used for timing-safe authentication
1023
+ */
1024
+ async findByEmail(email2) {
1025
+ return await this.userRepository.getByEmail(email2);
1026
+ }
1027
+ async create(data) {
1028
+ const { id, email: email2, image, emailVerified, password, roleId, role } = data;
1029
+ if (!password || typeof password !== "string" || password.trim().length === 0) {
1030
+ Err4("Password is required");
1031
+ }
1032
+ this.userValidator.validatePasswordStrength(password);
1033
+ let userId = id || nanoid4(5);
1034
+ await this.userValidator.checkEmailUnique(data.email);
1035
+ await this.userValidator.checkUserIdIsUnique(id);
1036
+ const hashedPassword = await this.encryptionService.hashPassword(password);
1037
+ const resolvedRoleId = await this.resolveUserRole(roleId, role);
1038
+ const userDetails = {
1039
+ id: userId,
1040
+ email: email2,
1041
+ image,
1042
+ password: hashedPassword,
1043
+ roleId: resolvedRoleId,
1044
+ emailVerified,
1045
+ status: "pending"
1046
+ };
1047
+ const newUser = await this.userRepository.create(userDetails);
1048
+ return this.sanitizeUser(newUser);
1049
+ }
1050
+ async update(id, data) {
1051
+ const { password, image } = data;
1052
+ await this.userValidator.checkUserExists(id);
1053
+ await this.userValidator.checkEmailUnique(data.email, id);
1054
+ let hashedPassword;
1055
+ if (password) {
1056
+ this.userValidator.validatePasswordStrength(password);
1057
+ hashedPassword = await this.encryptionService.hashPassword(password);
1058
+ }
1059
+ const updateData = {
1060
+ ...data,
1061
+ image,
1062
+ ...hashedPassword && { password: hashedPassword }
1063
+ };
1064
+ const cleanedUpdateData = clean(updateData);
1065
+ const updatedUser = await this.userRepository.update(id, cleanedUpdateData);
1066
+ return this.sanitizeUser(updatedUser);
1067
+ }
1068
+ async delete(id) {
1069
+ await this.userValidator.checkUserExists(id);
1070
+ const user = await this.userRepository.delete(id);
1071
+ return this.sanitizeUser(user);
1072
+ }
1073
+ async deleteAll() {
1074
+ const deletedUsers = await this.userRepository.deleteAll();
1075
+ return this.sanitizeUsers(deletedUsers);
1076
+ }
1077
+ async getRoleName(id) {
1078
+ await this.userValidator.checkUserExists(id);
1079
+ return await this.userRepository.getRoleNameById(id);
1080
+ }
1081
+ async getPassword(email2) {
1082
+ await this.userValidator.checkUserExistsByEmail(email2);
1083
+ return await this.userRepository.getUserPassword(email2);
1084
+ }
1085
+ async assignRole(id, roleId, roleName) {
1086
+ await this.userValidator.checkUserExists(id);
1087
+ const resolvedRoleId = await this.resolveUserRole(roleId, roleName);
1088
+ const updatedUser = await this.userRepository.update(id, { roleId: resolvedRoleId });
1089
+ return this.sanitizeUser(updatedUser);
1090
+ }
1091
+ async removeRole(id) {
1092
+ await this.userValidator.checkUserExists(id);
1093
+ const updatedUser = await this.userRepository.update(id, { roleId: null });
1094
+ return this.sanitizeUser(updatedUser);
1095
+ }
1096
+ async seedAdminUser(config) {
1097
+ if (!config?.email || !config?.password) {
1098
+ Err4("Admin email and password must be provided via config parameter");
1099
+ }
1100
+ if (config.password.length < 12) {
1101
+ Err4("Admin password must be at least 12 characters");
1102
+ }
1103
+ const adminRole = await this.roleValidator.checkAdminRoleExists();
1104
+ const existingUser = await this.userRepository.getByEmail(config.email);
1105
+ if (existingUser) {
1106
+ await this.delete(existingUser.id);
1107
+ }
1108
+ const newAdminUser = await this.create({
1109
+ id: nanoid4(10),
1110
+ // Random ID instead of predictable 'USR00'
1111
+ name: config.name || "System Administrator",
1112
+ email: config.email,
1113
+ password: config.password,
1114
+ image: null,
1115
+ roleId: adminRole.id,
1116
+ status: "active",
1117
+ emailVerified: true
1118
+ });
1119
+ return this.sanitizeUser(newAdminUser);
1120
+ }
1121
+ async updateLang(language) {
1122
+ this.i18nService.setLanguage(language);
1123
+ return language;
1124
+ }
1125
+ async getLang() {
1126
+ return this.i18nService.getCurrentLanguage();
1127
+ }
1128
+ };
1129
+ __decorate8([
1130
+ Transaction(),
1131
+ __metadata8("design:type", Function),
1132
+ __metadata8("design:paramtypes", [typeof (_g = typeof Record !== "undefined" && Record) === "function" ? _g : Object]),
1133
+ __metadata8("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object)
1134
+ ], UserService.prototype, "create", null);
1135
+ UserService = __decorate8([
1136
+ Injectable5(),
1137
+ __param(6, Inject4(AUTH_CONFIG)),
1138
+ __metadata8("design:paramtypes", [typeof (_a5 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _a5 : 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, typeof (_f = typeof I18nService !== "undefined" && I18nService) === "function" ? _f : Object, Object])
1139
+ ], UserService);
1140
+
1141
+ // src/tokens/TokenService.ts
1142
+ import { Injectable as Injectable6, Inject as Inject6 } from "najm-core";
1143
+ import { I18n as I18n3 } from "najm-i18n";
1144
+ import { CacheService } from "najm-cache";
1145
+ import jwt from "jsonwebtoken";
1146
+ import { jwtDecode } from "jwt-decode";
1147
+ import bcrypt2 from "bcryptjs";
1148
+ import { nanoid as nanoid5 } from "nanoid";
1149
+
1150
+ // src/tokens/TokenRepository.ts
1151
+ import { eq as eq4 } from "drizzle-orm";
1152
+ import { Repository as Repository3, Inject as Inject5 } from "najm-core";
1153
+ import { DB as DB3 } from "najm-database";
1154
+ var __decorate9 = function(decorators, target, key, desc) {
1155
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1156
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1157
+ 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;
1158
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1159
+ };
1160
+ var __metadata9 = function(k, v) {
1161
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1162
+ };
1163
+ var TokenRepository = class TokenRepository2 {
1164
+ static {
1165
+ __name(this, "TokenRepository");
1166
+ }
1167
+ db;
1168
+ schema;
1169
+ get tokens() {
1170
+ return this.schema.tokens;
1171
+ }
1172
+ get users() {
1173
+ return this.schema.users;
1174
+ }
1175
+ get roles() {
1176
+ return this.schema.roles;
1177
+ }
1178
+ /** Shared query helper */
1179
+ get q() {
1180
+ return new AuthQueries(this.db, this.schema);
1181
+ }
1182
+ async storeRefreshToken(tokenData) {
1183
+ return await this.db.insert(this.tokens).values(tokenData).onConflictDoUpdate({
1184
+ target: this.tokens.userId,
1185
+ set: {
1186
+ token: tokenData.token,
1187
+ expiresAt: tokenData.expiresAt
1188
+ }
1189
+ }).returning();
1190
+ }
1191
+ async getRefreshToken(userId) {
1192
+ const [token] = await this.db.select().from(this.tokens).where(eq4(this.tokens.userId, userId));
1193
+ return token?.token;
1194
+ }
1195
+ async revokeToken(userId) {
1196
+ const [deletedToken] = await this.db.delete(this.tokens).where(eq4(this.tokens.userId, userId)).returning();
1197
+ return deletedToken;
1198
+ }
1199
+ async isUserExists(userId) {
1200
+ const [user] = await this.db.select({ id: this.users.id }).from(this.users).where(eq4(this.users.id, userId)).limit(1);
1201
+ return !!user;
1202
+ }
1203
+ async getRoleNameById(userId) {
1204
+ return this.q.getRoleName(userId);
1205
+ }
1206
+ async getUserPermissions(userId) {
1207
+ return this.q.getUserPermissions(userId);
1208
+ }
1209
+ async getUser(userId) {
1210
+ const [user] = await this.db.select(this.q.userSelection()).from(this.users).leftJoin(this.roles, eq4(this.users.roleId, this.roles.id)).where(eq4(this.users.id, userId)).limit(1);
1211
+ if (!user)
1212
+ return null;
1213
+ return {
1214
+ ...user,
1215
+ permissions: await this.q.getUserPermissions(userId)
1216
+ };
1217
+ }
1218
+ };
1219
+ __decorate9([
1220
+ DB3(),
1221
+ __metadata9("design:type", Object)
1222
+ ], TokenRepository.prototype, "db", void 0);
1223
+ __decorate9([
1224
+ Inject5(AUTH_SCHEMA),
1225
+ __metadata9("design:type", Object)
1226
+ ], TokenRepository.prototype, "schema", void 0);
1227
+ TokenRepository = __decorate9([
1228
+ Repository3()
1229
+ ], TokenRepository);
1230
+
1231
+ // src/tokens/TokenService.ts
1232
+ import timestring2 from "timestring";
1233
+ import { Err as Err5 } from "najm-core";
1234
+ var __decorate10 = function(decorators, target, key, desc) {
1235
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1236
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1237
+ 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;
1238
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1239
+ };
1240
+ var __metadata10 = function(k, v) {
1241
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1242
+ };
1243
+ var _a6;
1244
+ var _b4;
1245
+ var _c2;
1246
+ var TokenService = class TokenService2 {
1247
+ static {
1248
+ __name(this, "TokenService");
1249
+ }
1250
+ tokenRepository;
1251
+ cookieManager;
1252
+ cache;
1253
+ config;
1254
+ t;
1255
+ constructor(tokenRepository, cookieManager, cache2) {
1256
+ this.tokenRepository = tokenRepository;
1257
+ this.cookieManager = cookieManager;
1258
+ this.cache = cache2;
1259
+ }
1260
+ /**
1261
+ * Get blacklist key prefix
1262
+ */
1263
+ get blacklistPrefix() {
1264
+ return this.config.blacklistPrefix ?? "auth:blacklist:";
1265
+ }
1266
+ // ============ TOKEN VALIDATION ============
1267
+ extractAccessToken(authorization) {
1268
+ if (authorization?.startsWith("Bearer ")) {
1269
+ return authorization.split(" ")[1];
1270
+ }
1271
+ Err5(this.t("errors.tokenMissing"));
1272
+ }
1273
+ /**
1274
+ * Verify access token and check blacklist
1275
+ * Throws error if token is invalid, expired, or blacklisted
1276
+ */
1277
+ async verifyAccessToken(token) {
1278
+ let payload;
1279
+ try {
1280
+ payload = jwt.verify(token, this.config.jwt.accessSecret);
1281
+ } catch {
1282
+ Err5(this.t("errors.tokenVerificationFailed"));
1283
+ }
1284
+ if (payload.jti) {
1285
+ const isBlacklisted = await this.isTokenBlacklisted(payload.jti);
1286
+ if (isBlacklisted) {
1287
+ Err5(this.t("errors.tokenRevoked"));
1288
+ }
1289
+ }
1290
+ return payload;
1291
+ }
1292
+ verifyRefreshToken(token) {
1293
+ try {
1294
+ const decoded = jwt.verify(token, this.config.jwt.refreshSecret);
1295
+ return decoded.userId;
1296
+ } catch {
1297
+ Err5(this.t("errors.tokenVerificationFailed"));
1298
+ }
1299
+ }
1300
+ // ============ USER RETRIEVAL (MAIN METHOD) ============
1301
+ async getUser(auth2) {
1302
+ if (!auth2)
1303
+ return null;
1304
+ const token = this.extractAccessToken(auth2);
1305
+ const { userId } = await this.verifyAccessToken(token);
1306
+ return this.tokenRepository.getUser(userId);
1307
+ }
1308
+ // ============ TOKEN GENERATION ============
1309
+ getTokenExpire(token) {
1310
+ return jwtDecode(token).exp;
1311
+ }
1312
+ /**
1313
+ * Generate access token with unique jti for blacklist support
1314
+ */
1315
+ generateAccessToken(data) {
1316
+ const jti = nanoid5(16);
1317
+ return jwt.sign({ ...data, jti }, this.config.jwt.accessSecret, {
1318
+ expiresIn: this.config.jwt.accessExpiresIn
1319
+ });
1320
+ }
1321
+ /**
1322
+ * Generate refresh token with unique jti
1323
+ */
1324
+ generateRefreshToken(data) {
1325
+ const jti = nanoid5(16);
1326
+ return jwt.sign({ ...data, jti }, this.config.jwt.refreshSecret, {
1327
+ expiresIn: this.config.jwt.refreshExpiresIn
1328
+ });
1329
+ }
1330
+ async generateTokens(userId) {
1331
+ const tokenData = { userId };
1332
+ const accessToken = this.generateAccessToken(tokenData);
1333
+ const refreshToken = this.generateRefreshToken(tokenData);
1334
+ await this.storeRefreshToken(userId, refreshToken);
1335
+ return {
1336
+ accessToken,
1337
+ refreshToken,
1338
+ accessTokenExpiresAt: this.getTokenExpire(accessToken),
1339
+ refreshTokenExpiresAt: this.getTokenExpire(refreshToken)
1340
+ };
1341
+ }
1342
+ // ============ TOKEN BLACKLIST (Cache) ============
1343
+ /**
1344
+ * Blacklist an access token by its jti
1345
+ * Token will be rejected until it naturally expires
1346
+ */
1347
+ async blacklistToken(jti, expiresInSeconds) {
1348
+ const key = `${this.blacklistPrefix}${jti}`;
1349
+ await this.cache.set(key, "1", expiresInSeconds * 1e3);
1350
+ }
1351
+ /**
1352
+ * Check if a token is blacklisted
1353
+ */
1354
+ async isTokenBlacklisted(jti) {
1355
+ const key = `${this.blacklistPrefix}${jti}`;
1356
+ return this.cache.exists(key);
1357
+ }
1358
+ /**
1359
+ * Blacklist the current access token (for logout)
1360
+ * Extracts jti and remaining TTL from the token
1361
+ */
1362
+ async blacklistCurrentToken(token) {
1363
+ try {
1364
+ const decoded = jwtDecode(token);
1365
+ if (!decoded.jti) {
1366
+ return;
1367
+ }
1368
+ const now = Math.floor(Date.now() / 1e3);
1369
+ const exp = decoded.exp ?? now;
1370
+ const ttl = Math.max(0, exp - now);
1371
+ if (ttl > 0) {
1372
+ await this.blacklistToken(decoded.jti, ttl);
1373
+ }
1374
+ } catch {
1375
+ }
1376
+ }
1377
+ // ============ REFRESH TOKEN ============
1378
+ /**
1379
+ * Store hashed refresh token in database for security
1380
+ * This prevents token theft in case of database breach
1381
+ */
1382
+ async storeRefreshToken(userId, refreshToken) {
1383
+ const expireInSecond = timestring2(this.config.jwt.refreshExpiresIn, "s");
1384
+ const hashedToken = await bcrypt2.hash(refreshToken, 10);
1385
+ await this.tokenRepository.storeRefreshToken({
1386
+ userId,
1387
+ token: hashedToken,
1388
+ expiresAt: new Date(Date.now() + expireInSecond * 1e3).toISOString()
1389
+ });
1390
+ }
1391
+ /**
1392
+ * Refresh tokens with secure token comparison
1393
+ * Compares provided token with hashed version in database
1394
+ */
1395
+ async refreshTokens() {
1396
+ const refreshToken = this.cookieManager.getRefreshToken();
1397
+ if (!refreshToken) {
1398
+ Err5(this.t("errors.refreshTokenMissing"));
1399
+ }
1400
+ const userId = this.verifyRefreshToken(refreshToken);
1401
+ const storedHashedToken = await this.tokenRepository.getRefreshToken(userId);
1402
+ if (!storedHashedToken) {
1403
+ Err5(this.t("errors.refreshTokenInvalid"));
1404
+ }
1405
+ const isValid = await bcrypt2.compare(refreshToken, storedHashedToken);
1406
+ if (!isValid) {
1407
+ Err5(this.t("errors.refreshTokenInvalid"));
1408
+ }
1409
+ return this.generateTokens(userId);
1410
+ }
1411
+ async revokeToken(userId) {
1412
+ return this.tokenRepository.revokeToken(userId);
1413
+ }
1414
+ /**
1415
+ * Logout user - blacklist access token and revoke refresh token
1416
+ */
1417
+ async logout(userId, authorization) {
1418
+ if (authorization) {
1419
+ try {
1420
+ const accessToken = this.extractAccessToken(authorization);
1421
+ await this.blacklistCurrentToken(accessToken);
1422
+ } catch {
1423
+ }
1424
+ }
1425
+ await this.revokeToken(userId);
1426
+ }
1427
+ // ============ PASSWORD RESET TOKENS ============
1428
+ /**
1429
+ * Generate secure password reset token
1430
+ * Returns both the plain token (to send via email) and userId for identification
1431
+ */
1432
+ generateResetToken(userId) {
1433
+ const resetData = {
1434
+ userId,
1435
+ type: "reset",
1436
+ timestamp: Date.now()
1437
+ };
1438
+ const token = jwt.sign(resetData, this.config.jwt.accessSecret, {
1439
+ expiresIn: "1h"
1440
+ });
1441
+ return { token, userId };
1442
+ }
1443
+ /**
1444
+ * Verify password reset token
1445
+ * Returns userId if valid, throws error if expired/invalid
1446
+ */
1447
+ verifyResetToken(token) {
1448
+ try {
1449
+ const decoded = jwt.verify(token, this.config.jwt.accessSecret);
1450
+ if (decoded.type !== "reset") {
1451
+ Err5(this.t("errors.invalidResetToken"));
1452
+ }
1453
+ return decoded.userId;
1454
+ } catch (error) {
1455
+ Err5(this.t("errors.resetTokenExpired"));
1456
+ }
1457
+ }
1458
+ };
1459
+ __decorate10([
1460
+ Inject6(AUTH_CONFIG),
1461
+ __metadata10("design:type", Object)
1462
+ ], TokenService.prototype, "config", void 0);
1463
+ __decorate10([
1464
+ I18n3("auth"),
1465
+ __metadata10("design:type", Object)
1466
+ ], TokenService.prototype, "t", void 0);
1467
+ TokenService = __decorate10([
1468
+ Injectable6(),
1469
+ __metadata10("design:paramtypes", [typeof (_a6 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _a6 : Object, typeof (_b4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _b4 : Object, typeof (_c2 = typeof CacheService !== "undefined" && CacheService) === "function" ? _c2 : Object])
1470
+ ], TokenService);
1471
+
1472
+ // src/auth/AuthService.ts
1473
+ var __decorate11 = function(decorators, target, key, desc) {
1474
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1475
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1476
+ 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;
1477
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1478
+ };
1479
+ var __metadata11 = function(k, v) {
1480
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1481
+ };
1482
+ var AuthService_1;
1483
+ var _a7;
1484
+ var _b5;
1485
+ var _c3;
1486
+ var _d2;
1487
+ var _e2;
1488
+ var _f2;
1489
+ var AuthService = class AuthService2 {
1490
+ static {
1491
+ __name(this, "AuthService");
1492
+ }
1493
+ static {
1494
+ AuthService_1 = this;
1495
+ }
1496
+ tokenService;
1497
+ userService;
1498
+ userValidator;
1499
+ cookieManager;
1500
+ i18nService;
1501
+ emailService;
1502
+ t;
1503
+ logger;
1504
+ static DUMMY_HASH = "$2b$10$dummyhashfortimingatackprevention000000000000000";
1505
+ constructor(tokenService, userService, userValidator, cookieManager, i18nService, emailService) {
1506
+ this.tokenService = tokenService;
1507
+ this.userService = userService;
1508
+ this.userValidator = userValidator;
1509
+ this.cookieManager = cookieManager;
1510
+ this.i18nService = i18nService;
1511
+ this.emailService = emailService;
1512
+ }
1513
+ async registerUser(body) {
1514
+ return await this.userService.create(body);
1515
+ }
1516
+ async loginUser(body) {
1517
+ const { email: email2, password } = body;
1518
+ const user = await this.userService.findByEmail(email2);
1519
+ const storedHash = user?.password ?? AuthService_1.DUMMY_HASH;
1520
+ const isValid = await this.userValidator.comparePassword(password, storedHash);
1521
+ if (!user || !isValid) {
1522
+ Err6(this.t("errors.invalidCredentials"));
1523
+ }
1524
+ const data = await this.tokenService.generateTokens(user.id);
1525
+ this.cookieManager.setRefreshToken(data.refreshToken);
1526
+ return data;
1527
+ }
1528
+ async refreshTokens() {
1529
+ const data = await this.tokenService.refreshTokens();
1530
+ this.cookieManager.setRefreshToken(data.refreshToken);
1531
+ return data;
1532
+ }
1533
+ async logoutUser(userId, authorization) {
1534
+ await this.userValidator.checkUserExists(userId);
1535
+ await this.tokenService.logout(userId, authorization);
1536
+ this.cookieManager.clearRefreshToken();
1537
+ return { data: null, message: this.t("auth.success.logout") };
1538
+ }
1539
+ async getUserProfile(userData) {
1540
+ const lang = this.i18nService.getCurrentLanguage();
1541
+ return {
1542
+ ...userData,
1543
+ language: lang
1544
+ };
1545
+ }
1546
+ async forgotPassword(email2) {
1547
+ const user = await this.userService.findByEmail(email2);
1548
+ if (user) {
1549
+ const { token } = this.tokenService.generateResetToken(user.id);
1550
+ const resetLink = `${process.env.FRONTEND_URL || "http://localhost:3000"}/reset-password?token=${token}`;
1551
+ try {
1552
+ await this.emailService.sendHtml(email2, this.t("emails.passwordReset.subject"), passwordResetTemplate({
1553
+ resetLink,
1554
+ userName: user.name || email2
1555
+ }));
1556
+ } catch (error) {
1557
+ this.logger.warn("Password reset email failed", { email: email2, error });
1558
+ }
1559
+ }
1560
+ return { message: this.t("success.passwordResetSent") };
1561
+ }
1562
+ async resetPassword(token, newPassword) {
1563
+ const userId = this.tokenService.verifyResetToken(token);
1564
+ this.userValidator.validatePasswordStrength(newPassword);
1565
+ await this.userService.update(userId, { password: newPassword });
1566
+ await this.tokenService.revokeToken(userId);
1567
+ return { message: this.t("success.passwordReset") };
1568
+ }
1569
+ };
1570
+ __decorate11([
1571
+ I18n4("auth"),
1572
+ __metadata11("design:type", Object)
1573
+ ], AuthService.prototype, "t", void 0);
1574
+ __decorate11([
1575
+ Log(),
1576
+ __metadata11("design:type", Object)
1577
+ ], AuthService.prototype, "logger", void 0);
1578
+ AuthService = AuthService_1 = __decorate11([
1579
+ Injectable7(),
1580
+ __metadata11("design:paramtypes", [typeof (_a7 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a7 : Object, typeof (_b5 = typeof UserService !== "undefined" && UserService) === "function" ? _b5 : Object, typeof (_c3 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _c3 : Object, typeof (_d2 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _d2 : Object, typeof (_e2 = typeof I18nService2 !== "undefined" && I18nService2) === "function" ? _e2 : Object, typeof (_f2 = typeof EmailService !== "undefined" && EmailService) === "function" ? _f2 : Object])
1581
+ ], AuthService);
1582
+
1583
+ // src/auth/AuthGuard.ts
1584
+ import { Service as Service2, Inject as Inject7 } from "najm-core";
1585
+ import { Headers } from "najm-core";
1586
+ import { createGuard } from "najm-guard";
1587
+ var __decorate12 = function(decorators, target, key, desc) {
1588
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1589
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1590
+ 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;
1591
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1592
+ };
1593
+ var __metadata12 = function(k, v) {
1594
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1595
+ };
1596
+ var __param2 = function(paramIndex, decorator) {
1597
+ return function(target, key) {
1598
+ decorator(target, key, paramIndex);
1599
+ };
1600
+ };
1601
+ var _a8;
1602
+ var _b6;
1603
+ var AuthGuard = class AuthGuard2 {
1604
+ static {
1605
+ __name(this, "AuthGuard");
1606
+ }
1607
+ tokenService;
1608
+ async canActivate(auth2) {
1609
+ if (!auth2)
1610
+ return false;
1611
+ try {
1612
+ const user = await this.tokenService.getUser(auth2);
1613
+ if (!user)
1614
+ return false;
1615
+ return { user };
1616
+ } catch (error) {
1617
+ return false;
1618
+ }
1619
+ }
1620
+ };
1621
+ __decorate12([
1622
+ Inject7(TokenService),
1623
+ __metadata12("design:type", typeof (_a8 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a8 : Object)
1624
+ ], AuthGuard.prototype, "tokenService", void 0);
1625
+ __decorate12([
1626
+ __param2(0, Headers("authorization")),
1627
+ __metadata12("design:type", Function),
1628
+ __metadata12("design:paramtypes", [String]),
1629
+ __metadata12("design:returntype", typeof (_b6 = typeof Promise !== "undefined" && Promise) === "function" ? _b6 : Object)
1630
+ ], AuthGuard.prototype, "canActivate", null);
1631
+ AuthGuard = __decorate12([
1632
+ Service2()
1633
+ ], AuthGuard);
1634
+ var isAuth = createGuard(AuthGuard);
1635
+
1636
+ // src/auth/AuthController.ts
1637
+ import { Validate } from "najm-validation";
1638
+ import { RateLimit } from "najm-rate";
1639
+
1640
+ // src/users/UserDto.ts
1641
+ import { z } from "zod";
1642
+ var emailField = z.string().email("Invalid email format");
1643
+ var passwordField = z.string().min(8, "Password must be at least 8 characters");
1644
+ var nameField = z.string().min(2, "Name must be at least 2 characters").max(100, "Name too long");
1645
+ var optionalDateField = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").nullable().optional();
1646
+ var createUserDto = z.object({
1647
+ email: emailField,
1648
+ password: passwordField,
1649
+ username: nameField.max(50).optional(),
1650
+ roleId: z.string().min(1).optional(),
1651
+ image: z.union([z.string(), z.instanceof(File)]).optional(),
1652
+ emailVerified: z.boolean().default(false),
1653
+ status: z.enum(["active", "inactive", "pending"]).default("pending")
1654
+ });
1655
+ var updateUserDto = createUserDto.partial();
1656
+ var userIdParam = z.object({
1657
+ id: z.string().min(1, "User ID is required")
1658
+ });
1659
+ var loginDto = z.object({
1660
+ email: emailField,
1661
+ password: passwordField
1662
+ });
1663
+ var changePasswordDto = z.object({
1664
+ currentPassword: passwordField,
1665
+ newPassword: passwordField
1666
+ });
1667
+ var resetPasswordDto = z.object({
1668
+ email: emailField
1669
+ });
1670
+ var confirmResetPasswordDto = z.object({
1671
+ token: z.string().min(10, "Invalid reset token"),
1672
+ newPassword: passwordField
1673
+ });
1674
+ var languageParam = z.object({
1675
+ language: z.string().min(2)
1676
+ });
1677
+ var emailParam = z.object({
1678
+ email: emailField
1679
+ });
1680
+ var userIdInParam = z.object({
1681
+ userId: z.string().min(1, "User ID is required")
1682
+ });
1683
+ var assignRoleParams = z.object({
1684
+ userId: z.string().min(1, "User ID is required"),
1685
+ roleId: z.string().min(1)
1686
+ });
1687
+
1688
+ // src/auth/AuthController.ts
1689
+ var __decorate13 = function(decorators, target, key, desc) {
1690
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1691
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1692
+ 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;
1693
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1694
+ };
1695
+ var __metadata13 = function(k, v) {
1696
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1697
+ };
1698
+ var __param3 = function(paramIndex, decorator) {
1699
+ return function(target, key) {
1700
+ decorator(target, key, paramIndex);
1701
+ };
1702
+ };
1703
+ var _a9;
1704
+ var AuthController = class AuthController2 {
1705
+ static {
1706
+ __name(this, "AuthController");
1707
+ }
1708
+ authService;
1709
+ constructor(authService) {
1710
+ this.authService = authService;
1711
+ }
1712
+ async registerUser(body) {
1713
+ return this.authService.registerUser(body);
1714
+ }
1715
+ async loginUser(body) {
1716
+ return this.authService.loginUser(body);
1717
+ }
1718
+ async refreshTokens() {
1719
+ return this.authService.refreshTokens();
1720
+ }
1721
+ async logoutUser(userId, authorization) {
1722
+ return this.authService.logoutUser(userId, authorization);
1723
+ }
1724
+ async userProfile(user) {
1725
+ return this.authService.getUserProfile(user);
1726
+ }
1727
+ async forgotPassword(body) {
1728
+ return this.authService.forgotPassword(body.email);
1729
+ }
1730
+ async resetPassword(body) {
1731
+ return this.authService.resetPassword(body.token, body.newPassword);
1732
+ }
1733
+ };
1734
+ __decorate13([
1735
+ Post("/register"),
1736
+ RateLimit({ limit: 5, window: "15m", key: "ip" }),
1737
+ Validate(createUserDto),
1738
+ ResMsg("auth.success.register"),
1739
+ __param3(0, Body()),
1740
+ __metadata13("design:type", Function),
1741
+ __metadata13("design:paramtypes", [Object]),
1742
+ __metadata13("design:returntype", Promise)
1743
+ ], AuthController.prototype, "registerUser", null);
1744
+ __decorate13([
1745
+ Post("/login"),
1746
+ RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many login attempts. Please try again later." }),
1747
+ Validate(loginDto),
1748
+ ResMsg("auth.success.login"),
1749
+ __param3(0, Body()),
1750
+ __metadata13("design:type", Function),
1751
+ __metadata13("design:paramtypes", [Object]),
1752
+ __metadata13("design:returntype", Promise)
1753
+ ], AuthController.prototype, "loginUser", null);
1754
+ __decorate13([
1755
+ Get("/refresh"),
1756
+ RateLimit({ limit: 10, window: "15m", key: "ip" }),
1757
+ ResMsg("auth.success.tokenRefreshed"),
1758
+ __metadata13("design:type", Function),
1759
+ __metadata13("design:paramtypes", []),
1760
+ __metadata13("design:returntype", Promise)
1761
+ ], AuthController.prototype, "refreshTokens", null);
1762
+ __decorate13([
1763
+ Get("/logout"),
1764
+ isAuth(),
1765
+ __param3(0, User("id")),
1766
+ __param3(1, Headers2("authorization")),
1767
+ __metadata13("design:type", Function),
1768
+ __metadata13("design:paramtypes", [String, String]),
1769
+ __metadata13("design:returntype", Promise)
1770
+ ], AuthController.prototype, "logoutUser", null);
1771
+ __decorate13([
1772
+ Get("/me"),
1773
+ isAuth(),
1774
+ ResMsg("auth.users.success.retrieved"),
1775
+ __param3(0, User()),
1776
+ __metadata13("design:type", Function),
1777
+ __metadata13("design:paramtypes", [Object]),
1778
+ __metadata13("design:returntype", Promise)
1779
+ ], AuthController.prototype, "userProfile", null);
1780
+ __decorate13([
1781
+ Post("/forgot-password"),
1782
+ RateLimit({ limit: 3, window: "15m", key: "ip", message: "Too many password reset requests. Please try again later." }),
1783
+ Validate(resetPasswordDto),
1784
+ ResMsg("auth.success.passwordResetSent"),
1785
+ __param3(0, Body()),
1786
+ __metadata13("design:type", Function),
1787
+ __metadata13("design:paramtypes", [Object]),
1788
+ __metadata13("design:returntype", Promise)
1789
+ ], AuthController.prototype, "forgotPassword", null);
1790
+ __decorate13([
1791
+ Post("/reset-password"),
1792
+ RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many password reset attempts. Please try again later." }),
1793
+ Validate(confirmResetPasswordDto),
1794
+ ResMsg("auth.success.passwordReset"),
1795
+ __param3(0, Body()),
1796
+ __metadata13("design:type", Function),
1797
+ __metadata13("design:paramtypes", [Object]),
1798
+ __metadata13("design:returntype", Promise)
1799
+ ], AuthController.prototype, "resetPassword", null);
1800
+ AuthController = __decorate13([
1801
+ Controller("/auth"),
1802
+ __metadata13("design:paramtypes", [typeof (_a9 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a9 : Object])
1803
+ ], AuthController);
1804
+
1805
+ // src/auth/index.ts
1806
+ var AUTH_MODULE = [
1807
+ AuthService,
1808
+ CookieManager,
1809
+ EncryptionService,
1810
+ AuthGuard,
1811
+ AuthController
1812
+ ];
1813
+
1814
+ // src/users/index.ts
1815
+ var users_exports = {};
1816
+ __export(users_exports, {
1817
+ UserController: () => UserController,
1818
+ UserRepository: () => UserRepository,
1819
+ UserService: () => UserService,
1820
+ UserValidator: () => UserValidator,
1821
+ assignRoleParams: () => assignRoleParams,
1822
+ changePasswordDto: () => changePasswordDto,
1823
+ confirmResetPasswordDto: () => confirmResetPasswordDto,
1824
+ createUserDto: () => createUserDto,
1825
+ emailParam: () => emailParam,
1826
+ languageParam: () => languageParam,
1827
+ loginDto: () => loginDto,
1828
+ resetPasswordDto: () => resetPasswordDto,
1829
+ updateUserDto: () => updateUserDto,
1830
+ userIdInParam: () => userIdInParam,
1831
+ userIdParam: () => userIdParam
1832
+ });
1833
+
1834
+ // src/users/UserController.ts
1835
+ import { Controller as Controller3 } from "najm-core";
1836
+ import { Get as Get3, Post as Post3, Put as Put2, Delete as Delete2, ResMsg as ResMsg3 } from "najm-core";
1837
+ import { Params as Params2, Body as Body3 } from "najm-core";
1838
+
1839
+ // src/roles/index.ts
1840
+ var roles_exports = {};
1841
+ __export(roles_exports, {
1842
+ ROLES: () => ROLES,
1843
+ ROLE_GROUPS: () => ROLE_GROUPS,
1844
+ Role: () => Role,
1845
+ RoleController: () => RoleController,
1846
+ RoleGuard: () => RoleGuard,
1847
+ RoleRepository: () => RoleRepository,
1848
+ RoleService: () => RoleService,
1849
+ RoleValidator: () => RoleValidator,
1850
+ assignRoleDto: () => assignRoleDto,
1851
+ createRoleDto: () => createRoleDto,
1852
+ isAdmin: () => isAdmin,
1853
+ isAdministrator: () => isAdministrator,
1854
+ roleIdParam: () => roleIdParam,
1855
+ updateRoleDto: () => updateRoleDto
1856
+ });
1857
+
1858
+ // src/roles/RoleGuards.ts
1859
+ import { Service as Service3 } from "najm-core";
1860
+ import { GuardParams, User as User2 } from "najm-core";
1861
+ import { composeGuards, createGuard as createGuard2 } from "najm-guard";
1862
+ var __decorate14 = function(decorators, target, key, desc) {
1863
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1864
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1865
+ 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;
1866
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1867
+ };
1868
+ var __metadata14 = function(k, v) {
1869
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1870
+ };
1871
+ var __param4 = function(paramIndex, decorator) {
1872
+ return function(target, key) {
1873
+ decorator(target, key, paramIndex);
1874
+ };
1875
+ };
1876
+ var RoleGuard = class RoleGuard2 {
1877
+ static {
1878
+ __name(this, "RoleGuard");
1879
+ }
1880
+ canActivate(allowedRoles, userRole) {
1881
+ if (!userRole)
1882
+ return false;
1883
+ const requiredRoles = Array.isArray(allowedRoles) ? allowedRoles : [allowedRoles];
1884
+ const hasRole = requiredRoles.some((r) => r.toLowerCase() === userRole.toLowerCase());
1885
+ if (hasRole) {
1886
+ return { role: userRole };
1887
+ }
1888
+ return false;
1889
+ }
1890
+ };
1891
+ __decorate14([
1892
+ __param4(0, GuardParams()),
1893
+ __param4(1, User2("role")),
1894
+ __metadata14("design:type", Function),
1895
+ __metadata14("design:paramtypes", [Object, String]),
1896
+ __metadata14("design:returntype", void 0)
1897
+ ], RoleGuard.prototype, "canActivate", null);
1898
+ RoleGuard = __decorate14([
1899
+ Service3()
1900
+ ], RoleGuard);
1901
+ var Role = createGuard2(RoleGuard);
1902
+ var isAdmin = composeGuards(isAuth(), Role(ROLES.ADMIN));
1903
+ var isAdministrator = composeGuards(isAuth(), Role(ROLE_GROUPS.ADMINISTRATORS));
1904
+
1905
+ // src/roles/RoleController.ts
1906
+ import { Controller as Controller2 } from "najm-core";
1907
+ import { Get as Get2, Post as Post2, Put, Delete, ResMsg as ResMsg2 } from "najm-core";
1908
+ import { Params, Body as Body2 } from "najm-core";
1909
+ import { Validate as Validate2 } from "najm-validation";
1910
+
1911
+ // src/roles/RoleDto.ts
1912
+ import { z as z2 } from "zod";
1913
+ var nameField2 = z2.string().min(2, "Name must be at least 2 characters").max(50, "Name too long");
1914
+ var descriptionField = z2.string().max(255, "Description too long").optional();
1915
+ var createRoleDto = z2.object({
1916
+ name: nameField2,
1917
+ description: descriptionField
1918
+ });
1919
+ var updateRoleDto = createRoleDto.partial();
1920
+ var roleIdParam = z2.object({
1921
+ id: z2.string().length(5, "Role ID must be 5 characters")
1922
+ });
1923
+ var assignRoleDto = z2.object({
1924
+ userId: z2.string().length(8, "User ID must be 8 characters"),
1925
+ roleId: z2.string().length(5, "Role ID must be 5 characters")
1926
+ });
1927
+
1928
+ // src/roles/RoleController.ts
1929
+ var __decorate15 = function(decorators, target, key, desc) {
1930
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1931
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1932
+ 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;
1933
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1934
+ };
1935
+ var __metadata15 = function(k, v) {
1936
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1937
+ };
1938
+ var __param5 = function(paramIndex, decorator) {
1939
+ return function(target, key) {
1940
+ decorator(target, key, paramIndex);
1941
+ };
1942
+ };
1943
+ var _a10;
1944
+ var RoleController = class RoleController2 {
1945
+ static {
1946
+ __name(this, "RoleController");
1947
+ }
1948
+ roleService;
1949
+ constructor(roleService) {
1950
+ this.roleService = roleService;
1951
+ }
1952
+ async getRoles() {
1953
+ return this.roleService.getAll();
1954
+ }
1955
+ async getRole(params) {
1956
+ return this.roleService.getById(params.id);
1957
+ }
1958
+ async createRole(body) {
1959
+ return this.roleService.create(body);
1960
+ }
1961
+ async updateRole(params, body) {
1962
+ return this.roleService.update(params.id, body);
1963
+ }
1964
+ async deleteRole(params) {
1965
+ return this.roleService.delete(params.id);
1966
+ }
1967
+ };
1968
+ __decorate15([
1969
+ Get2(),
1970
+ isAdmin(),
1971
+ ResMsg2("roles.success.retrieved"),
1972
+ __metadata15("design:type", Function),
1973
+ __metadata15("design:paramtypes", []),
1974
+ __metadata15("design:returntype", Promise)
1975
+ ], RoleController.prototype, "getRoles", null);
1976
+ __decorate15([
1977
+ Get2("/:id"),
1978
+ isAdmin(),
1979
+ Validate2({ params: roleIdParam }),
1980
+ ResMsg2("roles.success.retrieved"),
1981
+ __param5(0, Params()),
1982
+ __metadata15("design:type", Function),
1983
+ __metadata15("design:paramtypes", [Object]),
1984
+ __metadata15("design:returntype", Promise)
1985
+ ], RoleController.prototype, "getRole", null);
1986
+ __decorate15([
1987
+ Post2(),
1988
+ isAdmin(),
1989
+ Validate2(createRoleDto),
1990
+ ResMsg2("roles.success.created"),
1991
+ __param5(0, Body2()),
1992
+ __metadata15("design:type", Function),
1993
+ __metadata15("design:paramtypes", [Object]),
1994
+ __metadata15("design:returntype", Promise)
1995
+ ], RoleController.prototype, "createRole", null);
1996
+ __decorate15([
1997
+ Put("/:id"),
1998
+ isAdmin(),
1999
+ Validate2({
2000
+ params: roleIdParam,
2001
+ body: updateRoleDto
2002
+ }),
2003
+ ResMsg2("roles.success.updated"),
2004
+ __param5(0, Params()),
2005
+ __param5(1, Body2()),
2006
+ __metadata15("design:type", Function),
2007
+ __metadata15("design:paramtypes", [Object, Object]),
2008
+ __metadata15("design:returntype", Promise)
2009
+ ], RoleController.prototype, "updateRole", null);
2010
+ __decorate15([
2011
+ Delete("/:id"),
2012
+ isAdmin(),
2013
+ Validate2({ params: roleIdParam }),
2014
+ ResMsg2("roles.success.deleted"),
2015
+ __param5(0, Params()),
2016
+ __metadata15("design:type", Function),
2017
+ __metadata15("design:paramtypes", [Object]),
2018
+ __metadata15("design:returntype", Promise)
2019
+ ], RoleController.prototype, "deleteRole", null);
2020
+ RoleController = __decorate15([
2021
+ Controller2("/roles"),
2022
+ __metadata15("design:paramtypes", [typeof (_a10 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a10 : Object])
2023
+ ], RoleController);
2024
+
2025
+ // src/users/UserController.ts
2026
+ import { Validate as Validate3 } from "najm-validation";
2027
+ var __decorate16 = function(decorators, target, key, desc) {
2028
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2029
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2030
+ 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;
2031
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2032
+ };
2033
+ var __metadata16 = function(k, v) {
2034
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2035
+ };
2036
+ var __param6 = function(paramIndex, decorator) {
2037
+ return function(target, key) {
2038
+ decorator(target, key, paramIndex);
2039
+ };
2040
+ };
2041
+ var _a11;
2042
+ var UserController = class UserController2 {
2043
+ static {
2044
+ __name(this, "UserController");
2045
+ }
2046
+ userService;
2047
+ constructor(userService) {
2048
+ this.userService = userService;
2049
+ }
2050
+ async getUsers() {
2051
+ return this.userService.getAll();
2052
+ }
2053
+ async getLang() {
2054
+ const language = await this.userService.getLang();
2055
+ return { language };
2056
+ }
2057
+ async updateLang(params) {
2058
+ return this.userService.updateLang(params.language);
2059
+ }
2060
+ async getUser(params) {
2061
+ return this.userService.getById(params.id);
2062
+ }
2063
+ async getByEmail(params) {
2064
+ return this.userService.getByEmail(params.email);
2065
+ }
2066
+ async getRole(params) {
2067
+ return this.userService.getRoleName(params.userId);
2068
+ }
2069
+ async create(body) {
2070
+ return this.userService.create(body);
2071
+ }
2072
+ async update(params, body) {
2073
+ return this.userService.update(params.id, body);
2074
+ }
2075
+ async delete(params) {
2076
+ return this.userService.delete(params.id);
2077
+ }
2078
+ async deleteAll() {
2079
+ return this.userService.deleteAll();
2080
+ }
2081
+ async assignRole(params) {
2082
+ return this.userService.assignRole(params.userId, params.roleId);
2083
+ }
2084
+ async removeRole(params) {
2085
+ return this.userService.removeRole(params.userId);
2086
+ }
2087
+ };
2088
+ __decorate16([
2089
+ Get3(),
2090
+ isAdmin(),
2091
+ ResMsg3("users.success.retrieved"),
2092
+ __metadata16("design:type", Function),
2093
+ __metadata16("design:paramtypes", []),
2094
+ __metadata16("design:returntype", Promise)
2095
+ ], UserController.prototype, "getUsers", null);
2096
+ __decorate16([
2097
+ Get3("/lang"),
2098
+ isAuth(),
2099
+ ResMsg3("users.success.retrieved"),
2100
+ __metadata16("design:type", Function),
2101
+ __metadata16("design:paramtypes", []),
2102
+ __metadata16("design:returntype", Promise)
2103
+ ], UserController.prototype, "getLang", null);
2104
+ __decorate16([
2105
+ Post3("/lang/:language"),
2106
+ isAuth(),
2107
+ Validate3({ params: languageParam }),
2108
+ ResMsg3("users.success.updated"),
2109
+ __param6(0, Params2()),
2110
+ __metadata16("design:type", Function),
2111
+ __metadata16("design:paramtypes", [Object]),
2112
+ __metadata16("design:returntype", Promise)
2113
+ ], UserController.prototype, "updateLang", null);
2114
+ __decorate16([
2115
+ Get3("/:id"),
2116
+ isAdmin(),
2117
+ Validate3({ params: userIdParam }),
2118
+ ResMsg3("users.success.retrieved"),
2119
+ __param6(0, Params2()),
2120
+ __metadata16("design:type", Function),
2121
+ __metadata16("design:paramtypes", [Object]),
2122
+ __metadata16("design:returntype", Promise)
2123
+ ], UserController.prototype, "getUser", null);
2124
+ __decorate16([
2125
+ Get3("/email/:email"),
2126
+ isAdmin(),
2127
+ Validate3({ params: emailParam }),
2128
+ ResMsg3("users.success.retrieved"),
2129
+ __param6(0, Params2()),
2130
+ __metadata16("design:type", Function),
2131
+ __metadata16("design:paramtypes", [Object]),
2132
+ __metadata16("design:returntype", Promise)
2133
+ ], UserController.prototype, "getByEmail", null);
2134
+ __decorate16([
2135
+ Get3("/role/:userId"),
2136
+ isAdmin(),
2137
+ Validate3({ params: userIdInParam }),
2138
+ ResMsg3("users.success.retrieved"),
2139
+ __param6(0, Params2()),
2140
+ __metadata16("design:type", Function),
2141
+ __metadata16("design:paramtypes", [Object]),
2142
+ __metadata16("design:returntype", Promise)
2143
+ ], UserController.prototype, "getRole", null);
2144
+ __decorate16([
2145
+ Post3(),
2146
+ isAdmin(),
2147
+ Validate3(createUserDto),
2148
+ ResMsg3("users.success.created"),
2149
+ __param6(0, Body3()),
2150
+ __metadata16("design:type", Function),
2151
+ __metadata16("design:paramtypes", [Object]),
2152
+ __metadata16("design:returntype", Promise)
2153
+ ], UserController.prototype, "create", null);
2154
+ __decorate16([
2155
+ Put2("/:id"),
2156
+ isAdmin(),
2157
+ Validate3({
2158
+ params: userIdParam,
2159
+ body: updateUserDto
2160
+ }),
2161
+ ResMsg3("users.success.updated"),
2162
+ __param6(0, Params2()),
2163
+ __param6(1, Body3()),
2164
+ __metadata16("design:type", Function),
2165
+ __metadata16("design:paramtypes", [Object, Object]),
2166
+ __metadata16("design:returntype", Promise)
2167
+ ], UserController.prototype, "update", null);
2168
+ __decorate16([
2169
+ Delete2("/:id"),
2170
+ isAdmin(),
2171
+ Validate3({ params: userIdParam }),
2172
+ ResMsg3("users.success.deleted"),
2173
+ __param6(0, Params2()),
2174
+ __metadata16("design:type", Function),
2175
+ __metadata16("design:paramtypes", [Object]),
2176
+ __metadata16("design:returntype", Promise)
2177
+ ], UserController.prototype, "delete", null);
2178
+ __decorate16([
2179
+ Delete2(),
2180
+ isAdmin(),
2181
+ ResMsg3("users.success.allDeleted"),
2182
+ __metadata16("design:type", Function),
2183
+ __metadata16("design:paramtypes", []),
2184
+ __metadata16("design:returntype", Promise)
2185
+ ], UserController.prototype, "deleteAll", null);
2186
+ __decorate16([
2187
+ Post3("/assign/:userId/:roleId"),
2188
+ isAdmin(),
2189
+ Validate3({ params: assignRoleParams }),
2190
+ ResMsg3("users.success.updated"),
2191
+ __param6(0, Params2()),
2192
+ __metadata16("design:type", Function),
2193
+ __metadata16("design:paramtypes", [Object]),
2194
+ __metadata16("design:returntype", Promise)
2195
+ ], UserController.prototype, "assignRole", null);
2196
+ __decorate16([
2197
+ Delete2("/remove/:userId"),
2198
+ isAdmin(),
2199
+ Validate3({ params: userIdInParam }),
2200
+ ResMsg3("users.success.updated"),
2201
+ __param6(0, Params2()),
2202
+ __metadata16("design:type", Function),
2203
+ __metadata16("design:paramtypes", [Object]),
2204
+ __metadata16("design:returntype", Promise)
2205
+ ], UserController.prototype, "removeRole", null);
2206
+ UserController = __decorate16([
2207
+ Controller3("/users"),
2208
+ __metadata16("design:paramtypes", [typeof (_a11 = typeof UserService !== "undefined" && UserService) === "function" ? _a11 : Object])
2209
+ ], UserController);
2210
+
2211
+ // src/permissions/index.ts
2212
+ var permissions_exports = {};
2213
+ __export(permissions_exports, {
2214
+ Can: () => Can,
2215
+ PermissionController: () => PermissionController,
2216
+ PermissionGuard: () => PermissionGuard,
2217
+ PermissionRepository: () => PermissionRepository,
2218
+ PermissionService: () => PermissionService,
2219
+ PermissionValidator: () => PermissionValidator,
2220
+ assignPermissionDto: () => assignPermissionDto,
2221
+ canCreate: () => canCreate,
2222
+ canDelete: () => canDelete,
2223
+ canManage: () => canManage,
2224
+ canRead: () => canRead,
2225
+ canUpdate: () => canUpdate,
2226
+ checkPermissionDto: () => checkPermissionDto,
2227
+ createPermissionDto: () => createPermissionDto,
2228
+ permissionIdParam: () => permissionIdParam,
2229
+ updatePermissionDto: () => updatePermissionDto
2230
+ });
2231
+
2232
+ // src/permissions/PermissionRepository.ts
2233
+ import { eq as eq5, and } from "drizzle-orm";
2234
+ import { Repository as Repository4, Inject as Inject8 } from "najm-core";
2235
+ import { DB as DB4 } from "najm-database";
2236
+ var __decorate17 = function(decorators, target, key, desc) {
2237
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2238
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2239
+ 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;
2240
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2241
+ };
2242
+ var __metadata17 = function(k, v) {
2243
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2244
+ };
2245
+ var PermissionRepository = class PermissionRepository2 {
2246
+ static {
2247
+ __name(this, "PermissionRepository");
2248
+ }
2249
+ db;
2250
+ schema;
2251
+ get permissions() {
2252
+ return this.schema.permissions;
2253
+ }
2254
+ get rolePermissions() {
2255
+ return this.schema.rolePermissions;
2256
+ }
2257
+ get roles() {
2258
+ return this.schema.roles;
2259
+ }
2260
+ async getAll() {
2261
+ return await this.db.select().from(this.permissions);
2262
+ }
2263
+ async getById(id) {
2264
+ const [existingPermission] = await this.db.select().from(this.permissions).where(eq5(this.permissions.id, id));
2265
+ return existingPermission;
2266
+ }
2267
+ async getByName(name) {
2268
+ const [existingPermission] = await this.db.select().from(this.permissions).where(eq5(this.permissions.name, name));
2269
+ return existingPermission;
2270
+ }
2271
+ async getByResource(resource) {
2272
+ return await this.db.select().from(this.permissions).where(eq5(this.permissions.resource, resource));
2273
+ }
2274
+ async create(data) {
2275
+ const [newPermission] = await this.db.insert(this.permissions).values(data).returning();
2276
+ return newPermission;
2277
+ }
2278
+ async update(id, data) {
2279
+ const [updatedPermission] = await this.db.update(this.permissions).set(data).where(eq5(this.permissions.id, id)).returning();
2280
+ return updatedPermission;
2281
+ }
2282
+ async delete(id) {
2283
+ const [deletedPermission] = await this.db.delete(this.permissions).where(eq5(this.permissions.id, id)).returning();
2284
+ return deletedPermission;
2285
+ }
2286
+ async getPermissionsByRole(roleId) {
2287
+ return await this.db.select({
2288
+ id: this.permissions.id,
2289
+ name: this.permissions.name,
2290
+ description: this.permissions.description,
2291
+ resource: this.permissions.resource,
2292
+ action: this.permissions.action
2293
+ }).from(this.rolePermissions).leftJoin(this.permissions, eq5(this.rolePermissions.permissionId, this.permissions.id)).where(eq5(this.rolePermissions.roleId, roleId));
2294
+ }
2295
+ async getRolesByPermission(permissionId) {
2296
+ return await this.db.select({
2297
+ id: this.roles.id,
2298
+ name: this.roles.name,
2299
+ description: this.roles.description
2300
+ }).from(this.rolePermissions).leftJoin(this.roles, eq5(this.rolePermissions.roleId, this.roles.id)).where(eq5(this.rolePermissions.permissionId, permissionId));
2301
+ }
2302
+ async assignPermissionToRole(roleId, permissionId) {
2303
+ const [newRolePermission] = await this.db.insert(this.rolePermissions).values({ roleId, permissionId }).returning();
2304
+ return newRolePermission;
2305
+ }
2306
+ async removePermissionFromRole(roleId, permissionId) {
2307
+ const [deletedRolePermission] = await this.db.delete(this.rolePermissions).where(and(eq5(this.rolePermissions.roleId, roleId), eq5(this.rolePermissions.permissionId, permissionId))).returning();
2308
+ return deletedRolePermission;
2309
+ }
2310
+ async checkRoleHasPermission(roleId, permissionId) {
2311
+ const [rolePermission] = await this.db.select().from(this.rolePermissions).where(and(eq5(this.rolePermissions.roleId, roleId), eq5(this.rolePermissions.permissionId, permissionId)));
2312
+ return !!rolePermission;
2313
+ }
2314
+ async deleteAll() {
2315
+ await this.db.delete(this.rolePermissions);
2316
+ const deletedPermissions = await this.db.delete(this.permissions).returning();
2317
+ return deletedPermissions;
2318
+ }
2319
+ };
2320
+ __decorate17([
2321
+ DB4(),
2322
+ __metadata17("design:type", Object)
2323
+ ], PermissionRepository.prototype, "db", void 0);
2324
+ __decorate17([
2325
+ Inject8(AUTH_SCHEMA),
2326
+ __metadata17("design:type", Object)
2327
+ ], PermissionRepository.prototype, "schema", void 0);
2328
+ PermissionRepository = __decorate17([
2329
+ Repository4()
2330
+ ], PermissionRepository);
2331
+
2332
+ // src/permissions/PermissionGuards.ts
2333
+ import { Injectable as Injectable8 } from "najm-core";
2334
+ import { GuardParams as GuardParams2, User as User3 } from "najm-core";
2335
+ import { createGuard as createGuard3, composeGuards as composeGuards2 } from "najm-guard";
2336
+ var __decorate18 = function(decorators, target, key, desc) {
2337
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2338
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2339
+ 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;
2340
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2341
+ };
2342
+ var __metadata18 = function(k, v) {
2343
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2344
+ };
2345
+ var __param7 = function(paramIndex, decorator) {
2346
+ return function(target, key) {
2347
+ decorator(target, key, paramIndex);
2348
+ };
2349
+ };
2350
+ var PermissionGuard = class PermissionGuard2 {
2351
+ static {
2352
+ __name(this, "PermissionGuard");
2353
+ }
2354
+ canActivate(requiredPermission, permissions) {
2355
+ if (!permissions || !Array.isArray(permissions))
2356
+ return false;
2357
+ const hasPermission = this.checkPermission(permissions, requiredPermission);
2358
+ if (hasPermission) {
2359
+ return { permissions };
2360
+ }
2361
+ return false;
2362
+ }
2363
+ checkPermission(permissions, required) {
2364
+ if (permissions.includes(required))
2365
+ return true;
2366
+ if (permissions.includes("*:*"))
2367
+ return true;
2368
+ const [action, resource] = required.split(":");
2369
+ if (action && resource) {
2370
+ if (permissions.includes(`${action}:*`))
2371
+ return true;
2372
+ if (permissions.includes(`*:${resource}`))
2373
+ return true;
2374
+ }
2375
+ return false;
2376
+ }
2377
+ };
2378
+ __decorate18([
2379
+ __param7(0, GuardParams2()),
2380
+ __param7(1, User3("permissions")),
2381
+ __metadata18("design:type", Function),
2382
+ __metadata18("design:paramtypes", [String, Array]),
2383
+ __metadata18("design:returntype", Object)
2384
+ ], PermissionGuard.prototype, "canActivate", null);
2385
+ PermissionGuard = __decorate18([
2386
+ Injectable8()
2387
+ ], PermissionGuard);
2388
+ var Permission = createGuard3(PermissionGuard);
2389
+ var Can = /* @__PURE__ */ __name((permission) => composeGuards2(isAuth(), Permission(permission))(), "Can");
2390
+ var canCreate = /* @__PURE__ */ __name((resource) => Can(`create:${resource}`), "canCreate");
2391
+ var canRead = /* @__PURE__ */ __name((resource) => Can(`read:${resource}`), "canRead");
2392
+ var canUpdate = /* @__PURE__ */ __name((resource) => Can(`update:${resource}`), "canUpdate");
2393
+ var canDelete = /* @__PURE__ */ __name((resource) => Can(`delete:${resource}`), "canDelete");
2394
+ var canManage = /* @__PURE__ */ __name((resource) => Can(`*:${resource}`), "canManage");
2395
+
2396
+ // src/permissions/PermissionController.ts
2397
+ import { Controller as Controller4 } from "najm-core";
2398
+ import { Get as Get4, Post as Post4, Put as Put3, Delete as Delete3, ResMsg as ResMsg4 } from "najm-core";
2399
+ import { Params as Params3, Body as Body4 } from "najm-core";
2400
+
2401
+ // src/permissions/PermissionService.ts
2402
+ import { Injectable as Injectable10 } from "najm-core";
2403
+
2404
+ // src/permissions/PermissionValidator.ts
2405
+ import { Injectable as Injectable9 } from "najm-core";
2406
+ import { I18n as I18n5 } from "najm-i18n";
2407
+ import { Err as Err7 } from "najm-core";
2408
+ var __decorate19 = function(decorators, target, key, desc) {
2409
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2410
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2411
+ 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;
2412
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2413
+ };
2414
+ var __metadata19 = function(k, v) {
2415
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2416
+ };
2417
+ var _a12;
2418
+ var _b7;
2419
+ var PermissionValidator = class PermissionValidator2 {
2420
+ static {
2421
+ __name(this, "PermissionValidator");
2422
+ }
2423
+ permissionRepository;
2424
+ roleValidator;
2425
+ t;
2426
+ constructor(permissionRepository, roleValidator) {
2427
+ this.permissionRepository = permissionRepository;
2428
+ this.roleValidator = roleValidator;
2429
+ }
2430
+ /**
2431
+ * Check if permission exists by ID
2432
+ */
2433
+ async checkPermissionExists(id) {
2434
+ const permission = await this.permissionRepository.getById(id);
2435
+ if (!permission) {
2436
+ Err7(this.t("errors.notFound"), 404);
2437
+ }
2438
+ return permission;
2439
+ }
2440
+ /**
2441
+ * Check if permission exists by name
2442
+ */
2443
+ async checkPermissionExistsByName(name) {
2444
+ const permission = await this.permissionRepository.getByName(name);
2445
+ if (!permission) {
2446
+ Err7(this.t("errors.notFound"), 404);
2447
+ }
2448
+ return permission;
2449
+ }
2450
+ /**
2451
+ * Check if permission name is unique
2452
+ */
2453
+ async checkPermissionNameUnique(name, excludeId) {
2454
+ if (!name)
2455
+ return;
2456
+ const existingPermission = await this.permissionRepository.getByName(name);
2457
+ if (existingPermission && existingPermission.id !== excludeId) {
2458
+ Err7(this.t("errors.nameExists"), 409);
2459
+ }
2460
+ }
2461
+ /**
2462
+ * Check if role exists (delegates to RoleValidator)
2463
+ */
2464
+ async checkRoleExists(id) {
2465
+ return await this.roleValidator.checkRoleExists(id);
2466
+ }
2467
+ /**
2468
+ * Check if role exists by name (delegates to RoleValidator)
2469
+ */
2470
+ async checkRoleExistsByName(name) {
2471
+ return await this.roleValidator.checkRoleExistsByName(name);
2472
+ }
2473
+ /**
2474
+ * Check if role already has permission
2475
+ */
2476
+ async checkRoleHasPermission(roleId, permissionId) {
2477
+ await this.roleValidator.checkRoleExists(roleId);
2478
+ await this.checkPermissionExists(permissionId);
2479
+ const hasPermission = await this.permissionRepository.checkRoleHasPermission(roleId, permissionId);
2480
+ if (hasPermission) {
2481
+ Err7(this.t("errors.roleAlreadyHasPermission"), 409);
2482
+ }
2483
+ }
2484
+ };
2485
+ __decorate19([
2486
+ I18n5("permissions"),
2487
+ __metadata19("design:type", Object)
2488
+ ], PermissionValidator.prototype, "t", void 0);
2489
+ PermissionValidator = __decorate19([
2490
+ Injectable9(),
2491
+ __metadata19("design:paramtypes", [typeof (_a12 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a12 : Object, typeof (_b7 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b7 : Object])
2492
+ ], PermissionValidator);
2493
+
2494
+ // src/permissions/PermissionService.ts
2495
+ var __decorate20 = function(decorators, target, key, desc) {
2496
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2497
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2498
+ 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;
2499
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2500
+ };
2501
+ var __metadata20 = function(k, v) {
2502
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2503
+ };
2504
+ var _a13;
2505
+ var _b8;
2506
+ var _c4;
2507
+ var PermissionService = class PermissionService2 {
2508
+ static {
2509
+ __name(this, "PermissionService");
2510
+ }
2511
+ permissionRepository;
2512
+ permissionValidator;
2513
+ roleService;
2514
+ constructor(permissionRepository, permissionValidator, roleService) {
2515
+ this.permissionRepository = permissionRepository;
2516
+ this.permissionValidator = permissionValidator;
2517
+ this.roleService = roleService;
2518
+ }
2519
+ async getAll() {
2520
+ return await this.permissionRepository.getAll();
2521
+ }
2522
+ async getById(id) {
2523
+ await this.permissionValidator.checkPermissionExists(id);
2524
+ return await this.permissionRepository.getById(id);
2525
+ }
2526
+ async getByName(name) {
2527
+ return await this.permissionRepository.getByName(name);
2528
+ }
2529
+ async getByResource(resource) {
2530
+ return await this.permissionRepository.getByResource(resource);
2531
+ }
2532
+ async create(data) {
2533
+ await this.permissionValidator.checkPermissionNameUnique(data.name);
2534
+ return await this.permissionRepository.create(data);
2535
+ }
2536
+ async update(id, data) {
2537
+ await this.permissionValidator.checkPermissionExists(id);
2538
+ await this.permissionValidator.checkPermissionNameUnique(data.name, id);
2539
+ return await this.permissionRepository.update(id, data);
2540
+ }
2541
+ async delete(id) {
2542
+ await this.permissionValidator.checkPermissionExists(id);
2543
+ return await this.permissionRepository.delete(id);
2544
+ }
2545
+ async getPermissionsByRole(roleId) {
2546
+ return await this.permissionRepository.getPermissionsByRole(roleId);
2547
+ }
2548
+ async getRolesByPermission(permissionId) {
2549
+ await this.permissionValidator.checkPermissionExists(permissionId);
2550
+ return await this.permissionRepository.getRolesByPermission(permissionId);
2551
+ }
2552
+ async assignPermissionToRole(roleId, permissionId) {
2553
+ await this.permissionValidator.checkRoleHasPermission(roleId, permissionId);
2554
+ return await this.permissionRepository.assignPermissionToRole(roleId, permissionId);
2555
+ }
2556
+ async removePermissionFromRole(roleId, permissionId) {
2557
+ return await this.permissionRepository.removePermissionFromRole(roleId, permissionId);
2558
+ }
2559
+ async seedDefaultPermissions(defaultPermissions) {
2560
+ const created = [];
2561
+ const skipped = [];
2562
+ for (const permission of defaultPermissions) {
2563
+ try {
2564
+ const entity = await this.create(permission);
2565
+ created.push(entity);
2566
+ } catch (error) {
2567
+ skipped.push({
2568
+ permission: permission.name,
2569
+ reason: error instanceof Error ? error.message : String(error)
2570
+ });
2571
+ }
2572
+ }
2573
+ return { created, skipped };
2574
+ }
2575
+ async seedDefaultRolePermissions(defaultRolePermissions) {
2576
+ const assigned = [];
2577
+ const skipped = [];
2578
+ for (const { roleName, permissions } of defaultRolePermissions) {
2579
+ try {
2580
+ await this.permissionValidator.checkRoleExistsByName(roleName);
2581
+ const role = await this.roleService.getByName(roleName);
2582
+ for (const permissionName of permissions) {
2583
+ try {
2584
+ await this.permissionValidator.checkPermissionExistsByName(permissionName);
2585
+ const permission = await this.getByName(permissionName);
2586
+ await this.permissionValidator.checkRoleHasPermission(role.id, permission.id);
2587
+ await this.assignPermissionToRole(role.id, permission.id);
2588
+ assigned.push({ role: roleName, permission: permissionName });
2589
+ } catch (error) {
2590
+ skipped.push({
2591
+ role: roleName,
2592
+ permission: permissionName,
2593
+ reason: error instanceof Error ? error.message : String(error)
2594
+ });
2595
+ }
2596
+ }
2597
+ } catch (error) {
2598
+ skipped.push({
2599
+ role: roleName,
2600
+ permission: "all",
2601
+ reason: error instanceof Error ? error.message : String(error)
2602
+ });
2603
+ }
2604
+ }
2605
+ return { assigned, skipped };
2606
+ }
2607
+ async deleteAll() {
2608
+ return await this.permissionRepository.deleteAll();
2609
+ }
2610
+ };
2611
+ PermissionService = __decorate20([
2612
+ Injectable10(),
2613
+ __metadata20("design:paramtypes", [typeof (_a13 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a13 : Object, typeof (_b8 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b8 : Object, typeof (_c4 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c4 : Object])
2614
+ ], PermissionService);
2615
+
2616
+ // src/permissions/PermissionController.ts
2617
+ import { Validate as Validate4 } from "najm-validation";
2618
+
2619
+ // src/permissions/PermissionDto.ts
2620
+ import { z as z3 } from "zod";
2621
+ var nameField3 = z3.string().min(2, "Name must be at least 2 characters").max(50, "Name too long");
2622
+ var descriptionField2 = z3.string().max(255, "Description too long").optional();
2623
+ var resourceField = z3.string().min(1, "Resource is required").max(50, "Resource too long");
2624
+ var actionField = z3.string().min(1, "Action is required").max(50, "Action too long");
2625
+ var createPermissionDto = z3.object({
2626
+ name: nameField3,
2627
+ description: descriptionField2,
2628
+ resource: resourceField,
2629
+ action: actionField
2630
+ });
2631
+ var updatePermissionDto = createPermissionDto.partial();
2632
+ var permissionIdParam = z3.object({
2633
+ id: z3.string().length(5, "Permission ID must be 5 characters")
2634
+ });
2635
+ var assignPermissionDto = z3.object({
2636
+ roleId: z3.string().length(5, "Role ID must be 5 characters"),
2637
+ permissionId: z3.string().length(5, "Permission ID must be 5 characters")
2638
+ });
2639
+ var checkPermissionDto = z3.object({
2640
+ userId: z3.string().length(8, "User ID must be 8 characters"),
2641
+ resource: resourceField,
2642
+ action: actionField
2643
+ });
2644
+
2645
+ // src/permissions/PermissionController.ts
2646
+ var __decorate21 = function(decorators, target, key, desc) {
2647
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2648
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2649
+ 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;
2650
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2651
+ };
2652
+ var __metadata21 = function(k, v) {
2653
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2654
+ };
2655
+ var __param8 = function(paramIndex, decorator) {
2656
+ return function(target, key) {
2657
+ decorator(target, key, paramIndex);
2658
+ };
2659
+ };
2660
+ var _a14;
2661
+ var PermissionController = class PermissionController2 {
2662
+ static {
2663
+ __name(this, "PermissionController");
2664
+ }
2665
+ permissionService;
2666
+ constructor(permissionService) {
2667
+ this.permissionService = permissionService;
2668
+ }
2669
+ // ============================================================================
2670
+ // Option 1: @ResMsg with i18n key (recommended)
2671
+ // ============================================================================
2672
+ async getPermissions() {
2673
+ return this.permissionService.getAll();
2674
+ }
2675
+ async getPermission(params) {
2676
+ return this.permissionService.getById(params.id);
2677
+ }
2678
+ // ============================================================================
2679
+ // Option 2: @ResMsg with plain text
2680
+ // ============================================================================
2681
+ async create(body) {
2682
+ return this.permissionService.create(body);
2683
+ }
2684
+ async update(params, body) {
2685
+ return this.permissionService.update(params.id, body);
2686
+ }
2687
+ async delete(params) {
2688
+ return this.permissionService.delete(params.id);
2689
+ }
2690
+ async getByRole(params) {
2691
+ return this.permissionService.getPermissionsByRole(params.id);
2692
+ }
2693
+ async getRolesByPermission(params) {
2694
+ return this.permissionService.getRolesByPermission(params.id);
2695
+ }
2696
+ async assignToRole(params) {
2697
+ return this.permissionService.assignPermissionToRole(params.roleId, params.permissionId);
2698
+ }
2699
+ async removeFromRole(params) {
2700
+ return this.permissionService.removePermissionFromRole(params.roleId, params.permissionId);
2701
+ }
2702
+ async deleteAll() {
2703
+ return this.permissionService.deleteAll();
2704
+ }
2705
+ };
2706
+ __decorate21([
2707
+ Get4(),
2708
+ ResMsg4("permissions.success.retrieved"),
2709
+ __metadata21("design:type", Function),
2710
+ __metadata21("design:paramtypes", []),
2711
+ __metadata21("design:returntype", Promise)
2712
+ ], PermissionController.prototype, "getPermissions", null);
2713
+ __decorate21([
2714
+ Get4("/:id"),
2715
+ Validate4({ params: permissionIdParam }),
2716
+ ResMsg4("permissions.success.retrieved"),
2717
+ __param8(0, Params3()),
2718
+ __metadata21("design:type", Function),
2719
+ __metadata21("design:paramtypes", [Object]),
2720
+ __metadata21("design:returntype", Promise)
2721
+ ], PermissionController.prototype, "getPermission", null);
2722
+ __decorate21([
2723
+ Post4(),
2724
+ Validate4(createPermissionDto),
2725
+ ResMsg4({ message: "Permission created successfully", status: 201 }),
2726
+ __param8(0, Body4()),
2727
+ __metadata21("design:type", Function),
2728
+ __metadata21("design:paramtypes", [Object]),
2729
+ __metadata21("design:returntype", Promise)
2730
+ ], PermissionController.prototype, "create", null);
2731
+ __decorate21([
2732
+ Put3("/:id"),
2733
+ Validate4({
2734
+ params: permissionIdParam,
2735
+ body: updatePermissionDto
2736
+ }),
2737
+ ResMsg4("permissions.success.updated"),
2738
+ __param8(0, Params3()),
2739
+ __param8(1, Body4()),
2740
+ __metadata21("design:type", Function),
2741
+ __metadata21("design:paramtypes", [Object, Object]),
2742
+ __metadata21("design:returntype", Promise)
2743
+ ], PermissionController.prototype, "update", null);
2744
+ __decorate21([
2745
+ Delete3("/:id"),
2746
+ Validate4({ params: permissionIdParam }),
2747
+ ResMsg4("permissions.success.deleted"),
2748
+ __param8(0, Params3()),
2749
+ __metadata21("design:type", Function),
2750
+ __metadata21("design:paramtypes", [Object]),
2751
+ __metadata21("design:returntype", Promise)
2752
+ ], PermissionController.prototype, "delete", null);
2753
+ __decorate21([
2754
+ Get4("/role/:id"),
2755
+ Validate4({ params: roleIdParam }),
2756
+ ResMsg4("permissions.success.retrieved"),
2757
+ __param8(0, Params3()),
2758
+ __metadata21("design:type", Function),
2759
+ __metadata21("design:paramtypes", [Object]),
2760
+ __metadata21("design:returntype", Promise)
2761
+ ], PermissionController.prototype, "getByRole", null);
2762
+ __decorate21([
2763
+ Get4("/roles/:id"),
2764
+ Validate4({ params: permissionIdParam }),
2765
+ ResMsg4("permissions.success.retrieved"),
2766
+ __param8(0, Params3()),
2767
+ __metadata21("design:type", Function),
2768
+ __metadata21("design:paramtypes", [Object]),
2769
+ __metadata21("design:returntype", Promise)
2770
+ ], PermissionController.prototype, "getRolesByPermission", null);
2771
+ __decorate21([
2772
+ Post4("/assign/:roleId/:permissionId"),
2773
+ Validate4({ params: assignPermissionDto }),
2774
+ ResMsg4("permissions.success.assigned"),
2775
+ __param8(0, Params3()),
2776
+ __metadata21("design:type", Function),
2777
+ __metadata21("design:paramtypes", [Object]),
2778
+ __metadata21("design:returntype", Promise)
2779
+ ], PermissionController.prototype, "assignToRole", null);
2780
+ __decorate21([
2781
+ Delete3("/remove/:roleId/:permissionId"),
2782
+ Validate4({ params: assignPermissionDto }),
2783
+ ResMsg4("permissions.success.removed"),
2784
+ __param8(0, Params3()),
2785
+ __metadata21("design:type", Function),
2786
+ __metadata21("design:paramtypes", [Object]),
2787
+ __metadata21("design:returntype", Promise)
2788
+ ], PermissionController.prototype, "removeFromRole", null);
2789
+ __decorate21([
2790
+ Delete3(),
2791
+ isAdmin(),
2792
+ ResMsg4("permissions.success.allDeleted"),
2793
+ __metadata21("design:type", Function),
2794
+ __metadata21("design:paramtypes", []),
2795
+ __metadata21("design:returntype", Promise)
2796
+ ], PermissionController.prototype, "deleteAll", null);
2797
+ PermissionController = __decorate21([
2798
+ Controller4("/permissions"),
2799
+ isAdmin(),
2800
+ __metadata21("design:paramtypes", [typeof (_a14 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a14 : Object])
2801
+ ], PermissionController);
2802
+
2803
+ // src/tokens/index.ts
2804
+ var tokens_exports = {};
2805
+ __export(tokens_exports, {
2806
+ TokenRepository: () => TokenRepository,
2807
+ TokenService: () => TokenService,
2808
+ createTokenDto: () => createTokenDto,
2809
+ refreshTokenDto: () => refreshTokenDto,
2810
+ revokeTokenDto: () => revokeTokenDto,
2811
+ tokenIdParam: () => tokenIdParam,
2812
+ updateTokenDto: () => updateTokenDto,
2813
+ verifyTokenDto: () => verifyTokenDto
2814
+ });
2815
+
2816
+ // src/tokens/TokenDto.ts
2817
+ import { z as z4 } from "zod";
2818
+ var tokenField = z4.string().min(1, "Token is required");
2819
+ var userIdField = z4.string().length(8, "User ID must be 8 characters");
2820
+ var expiresAtField = z4.string().datetime("Invalid datetime format");
2821
+ var createTokenDto = z4.object({
2822
+ userId: userIdField,
2823
+ token: tokenField,
2824
+ type: z4.enum(["access", "refresh"]).default("refresh"),
2825
+ status: z4.enum(["active", "revoked", "expired"]).default("active"),
2826
+ expiresAt: expiresAtField
2827
+ });
2828
+ var updateTokenDto = z4.object({
2829
+ status: z4.enum(["active", "revoked", "expired"])
2830
+ });
2831
+ var tokenIdParam = z4.object({
2832
+ id: z4.string().length(10, "Token ID must be 10 characters")
2833
+ });
2834
+ var verifyTokenDto = z4.object({
2835
+ token: tokenField
2836
+ });
2837
+ var refreshTokenDto = z4.object({
2838
+ refreshToken: tokenField
2839
+ });
2840
+ var revokeTokenDto = z4.object({
2841
+ userId: userIdField
2842
+ });
2843
+
2844
+ // src/AuthPlugin.ts
2845
+ import { cookies } from "najm-cookies";
2846
+ import { i18n, I18N_CONTRIBUTIONS } from "najm-i18n";
2847
+ import { guards } from "najm-guard";
2848
+ import { validation } from "najm-validation";
2849
+ import { rateLimit } from "najm-rate";
2850
+ import { email } from "najm-email";
2851
+
2852
+ // src/locales/en.json
2853
+ var en_default = {
2854
+ auth: {
2855
+ errors: {
2856
+ invalidCredentials: "Invalid email or password",
2857
+ emailExists: "Email already registered",
2858
+ accessDenied: "Access denied",
2859
+ tokenExpired: "Token has expired",
2860
+ tokenInvalid: "Invalid token",
2861
+ tokenMissing: "Authorization token is missing",
2862
+ tokenVerificationFailed: "Token verification failed",
2863
+ tokenRevoked: "Token has been revoked",
2864
+ refreshTokenMissing: "Refresh token is missing",
2865
+ refreshTokenInvalid: "Invalid refresh token",
2866
+ invalidResetToken: "Invalid password reset token",
2867
+ resetTokenExpired: "Password reset token has expired",
2868
+ unauthorized: "Unauthorized access",
2869
+ sessionExpired: "Session has expired"
2870
+ },
2871
+ success: {
2872
+ login: "Login successful",
2873
+ logout: "Logout successful",
2874
+ passwordChanged: "Password changed successfully",
2875
+ tokenRefreshed: "Token refreshed successfully"
2876
+ }
2877
+ },
2878
+ users: {
2879
+ errors: {
2880
+ notFound: "User not found",
2881
+ idExists: "User ID already exists",
2882
+ emailRequired: "Email is required",
2883
+ passwordRequired: "Password is required",
2884
+ invalidEmail: "Invalid email format",
2885
+ weakPassword: "Password is too weak",
2886
+ adminRoleNotFound: "Admin role not found in system"
2887
+ },
2888
+ success: {
2889
+ created: "User created successfully",
2890
+ updated: "User updated successfully",
2891
+ deleted: "User deleted successfully",
2892
+ retrieved: "User retrieved successfully"
2893
+ }
2894
+ },
2895
+ roles: {
2896
+ errors: {
2897
+ notFound: "Role not found",
2898
+ exists: "Role already exists",
2899
+ nameRequired: "Role name is required",
2900
+ cannotDeleteSystem: "Cannot delete system role"
2901
+ },
2902
+ success: {
2903
+ created: "Role created successfully",
2904
+ updated: "Role updated successfully",
2905
+ deleted: "Role deleted successfully",
2906
+ assigned: "Role assigned successfully",
2907
+ retrieved: "Role retrieved successfully"
2908
+ }
2909
+ },
2910
+ permissions: {
2911
+ errors: {
2912
+ notFound: "Permission not found",
2913
+ nameExists: "Permission name already exists",
2914
+ roleAlreadyHasPermission: "Role already has this permission",
2915
+ cannotRemoveRequired: "Cannot remove required permission"
2916
+ },
2917
+ success: {
2918
+ created: "Permission created successfully",
2919
+ updated: "Permission updated successfully",
2920
+ deleted: "Permission deleted successfully",
2921
+ granted: "Permission granted successfully",
2922
+ revoked: "Permission revoked successfully",
2923
+ retrieved: "Permissions retrieved successfully",
2924
+ assigned: "Permission assigned to role successfully",
2925
+ removed: "Permission removed from role successfully",
2926
+ allDeleted: "All permissions deleted successfully"
2927
+ }
2928
+ }
2929
+ };
2930
+
2931
+ // src/locales/index.ts
2932
+ var AUTH_LOCALES = {
2933
+ en: en_default
2934
+ };
2935
+ function getAuthLocale(lang) {
2936
+ return AUTH_LOCALES[lang] ?? AUTH_LOCALES.en;
2937
+ }
2938
+ __name(getAuthLocale, "getAuthLocale");
2939
+ var AUTH_SUPPORTED_LANGUAGES = Object.keys(AUTH_LOCALES);
2940
+
2941
+ // src/AuthPlugin.ts
2942
+ var DEFAULT_JWT = {
2943
+ accessSecret: process.env.JWT_ACCESS_SECRET || "",
2944
+ accessExpiresIn: process.env.ACCESS_EXPIRES_IN || "1h",
2945
+ refreshSecret: process.env.JWT_REFRESH_SECRET || "",
2946
+ refreshExpiresIn: process.env.REFRESH_EXPIRES_IN || "7d"
2947
+ };
2948
+ var mergeConfig = /* @__PURE__ */ __name((config) => {
2949
+ const finalConfig = {
2950
+ jwt: {
2951
+ ...DEFAULT_JWT,
2952
+ ...config?.jwt
2953
+ },
2954
+ refreshCookieName: config?.refreshCookieName ?? "refreshToken",
2955
+ database: config?.database ?? "default",
2956
+ blacklistPrefix: config?.blacklistPrefix ?? "auth:blacklist:",
2957
+ defaultRole: config?.defaultRole ?? null
2958
+ };
2959
+ if (!finalConfig.jwt.accessSecret) {
2960
+ throw Err8.configRequired("auth", "JWT_ACCESS_SECRET");
2961
+ }
2962
+ if (!finalConfig.jwt.refreshSecret) {
2963
+ throw Err8.configRequired("auth", "JWT_REFRESH_SECRET");
2964
+ }
2965
+ return finalConfig;
2966
+ }, "mergeConfig");
2967
+ var selectSchema = /* @__PURE__ */ __name((config) => {
2968
+ if (config?.schema)
2969
+ return config.schema;
2970
+ const dialect = config?.dialect ?? "pg";
2971
+ switch (dialect) {
2972
+ case "sqlite":
2973
+ return authSchema2;
2974
+ case "mysql":
2975
+ return authSchema3;
2976
+ case "pg":
2977
+ default:
2978
+ return authSchema;
2979
+ }
2980
+ }, "selectSchema");
2981
+ var auth = /* @__PURE__ */ __name((config) => plugin("auth").version("1.0.0").depends(cache(), cookies(), i18n(), guards(), validation(config?.validation), rateLimit(config?.rateLimit), email()).requires("database").contributes(I18N_CONTRIBUTIONS, AUTH_LOCALES).services(auth_exports, users_exports, roles_exports, permissions_exports, tokens_exports).config(AUTH_CONFIG, mergeConfig(config)).set(AUTH_SCHEMA, selectSchema(config)).build(), "auth");
2982
+
2983
+ // src/seed.ts
2984
+ import { hash } from "bcryptjs";
2985
+ var toSeedId = /* @__PURE__ */ __name((prefix, value) => {
2986
+ const normalized = value.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 48);
2987
+ return `${prefix}_${normalized || "item"}`;
2988
+ }, "toSeedId");
2989
+ var authSeed = /* @__PURE__ */ __name((config) => ({
2990
+ roles: {
2991
+ schema: createRoleDto,
2992
+ rows: (config.roles ?? [
2993
+ { name: "admin", description: "System administrator with full access" },
2994
+ { name: "user", description: "Regular user with limited access" }
2995
+ ]).map((role) => ({
2996
+ id: toSeedId("role", role.name),
2997
+ ...role
2998
+ }))
2999
+ },
3000
+ permissions: {
3001
+ schema: createPermissionDto,
3002
+ by: ["name"],
3003
+ onConflict: "replace",
3004
+ // Permissions are code-defined, always sync
3005
+ rows: config.permissions ?? [
3006
+ { action: "read", resource: "users", name: "read:users", description: "View user information" },
3007
+ { action: "create", resource: "users", name: "create:users", description: "Create new users" },
3008
+ { action: "update", resource: "users", name: "update:users", description: "Update user information" },
3009
+ { action: "delete", resource: "users", name: "delete:users", description: "Delete users" },
3010
+ { action: "manage", resource: "roles", name: "manage:roles", description: "Manage roles and permissions" }
3011
+ ]
3012
+ },
3013
+ rolePermissions: {
3014
+ by: ["roleId", "permissionId"],
3015
+ rows: /* @__PURE__ */ __name((seeded) => {
3016
+ const admin = seeded.roles.find((r) => r.name === "admin");
3017
+ return seeded.permissions.map((p) => ({
3018
+ roleId: admin.id,
3019
+ permissionId: p.id
3020
+ }));
3021
+ }, "rows")
3022
+ },
3023
+ // No schema on entry — validation + hashing handled inside resolver
3024
+ users: {
3025
+ by: ["email"],
3026
+ rows: /* @__PURE__ */ __name(async (seeded) => {
3027
+ createUserDto.pick({ email: true, password: true }).parse({
3028
+ email: config.adminEmail,
3029
+ password: config.adminPass
3030
+ });
3031
+ const adminRole = seeded.roles.find((r) => r.name === "admin");
3032
+ const users = [
3033
+ {
3034
+ email: config.adminEmail,
3035
+ password: await hash(config.adminPass, 10),
3036
+ roleId: adminRole.id,
3037
+ emailVerified: true,
3038
+ status: "active",
3039
+ image: void 0,
3040
+ username: void 0
3041
+ }
3042
+ ];
3043
+ if (config.additionalUsers) {
3044
+ for (const user of config.additionalUsers) {
3045
+ createUserDto.pick({ email: true, password: true }).parse({
3046
+ email: user.email,
3047
+ password: user.password
3048
+ });
3049
+ const role = seeded.roles.find((r) => r.name === user.roleName);
3050
+ if (!role) {
3051
+ throw new Error(`Role '${user.roleName}' not found for user ${user.email}`);
3052
+ }
3053
+ users.push({
3054
+ email: user.email,
3055
+ password: await hash(user.password, 10),
3056
+ roleId: role.id,
3057
+ emailVerified: user.emailVerified ?? true,
3058
+ status: user.status ?? "active",
3059
+ image: user.image,
3060
+ username: user.username
3061
+ });
3062
+ }
3063
+ }
3064
+ return users;
3065
+ }, "rows")
3066
+ }
3067
+ }), "authSeed");
3068
+
3069
+ // src/seedAuthData.ts
3070
+ import { Server } from "najm-core";
3071
+ import { database, SeedService } from "najm-database";
3072
+ async function seedAuthData(config) {
3073
+ let server = null;
3074
+ try {
3075
+ server = new Server({ isolated: true }).use(database({ default: config.db }));
3076
+ await server.init();
3077
+ const seeder = server.container.get(SeedService);
3078
+ const report = await seeder.run(authSeed({
3079
+ adminEmail: config.adminEmail,
3080
+ adminPass: config.adminPassword,
3081
+ roles: config.roles,
3082
+ permissions: config.permissions,
3083
+ additionalUsers: config.users
3084
+ }), {
3085
+ verbose: config.verbose ?? false,
3086
+ onConflict: config.onConflict ?? "skip",
3087
+ transaction: false
3088
+ // Disable transaction for now to test
3089
+ });
3090
+ return {
3091
+ inserted: report.inserted,
3092
+ skipped: report.skipped,
3093
+ failed: report.failed,
3094
+ users: [],
3095
+ // Users can query db directly if needed
3096
+ roles: []
3097
+ // Users can query db directly if needed
3098
+ };
3099
+ } finally {
3100
+ if (server) {
3101
+ await server.stop();
3102
+ }
3103
+ }
3104
+ }
3105
+ __name(seedAuthData, "seedAuthData");
3106
+ export {
3107
+ AUTH_CONFIG,
3108
+ en_default as AUTH_EN,
3109
+ AUTH_LOCALES,
3110
+ AUTH_MODULE,
3111
+ AUTH_PERMISSIONS,
3112
+ AUTH_ROLE,
3113
+ AUTH_SCHEMA,
3114
+ AUTH_SUPPORTED_LANGUAGES,
3115
+ AUTH_USER,
3116
+ AuthController,
3117
+ AuthGuard,
3118
+ AuthQueries,
3119
+ AuthService,
3120
+ Can,
3121
+ CookieManager,
3122
+ EncryptionService,
3123
+ PermissionController,
3124
+ PermissionGuard,
3125
+ PermissionRepository,
3126
+ PermissionService,
3127
+ PermissionValidator,
3128
+ ROLES,
3129
+ ROLE_GROUPS,
3130
+ Role,
3131
+ RoleController,
3132
+ RoleGuard,
3133
+ RoleRepository,
3134
+ RoleService,
3135
+ RoleValidator,
3136
+ TOKEN_STATUS,
3137
+ TOKEN_TYPE,
3138
+ TokenRepository,
3139
+ TokenService,
3140
+ USER_STATUS,
3141
+ UserController,
3142
+ UserRepository,
3143
+ UserService,
3144
+ UserValidator,
3145
+ assignPermissionDto,
3146
+ assignRoleDto,
3147
+ assignRoleParams,
3148
+ auth,
3149
+ authSchema,
3150
+ authSeed,
3151
+ avatarsPath,
3152
+ baseFields,
3153
+ calculateAge,
3154
+ calculateYearsOfExperience,
3155
+ canCreate,
3156
+ canDelete,
3157
+ canManage,
3158
+ canRead,
3159
+ canUpdate,
3160
+ changePasswordDto,
3161
+ checkPermissionDto,
3162
+ clean,
3163
+ confirmResetPasswordDto,
3164
+ createPermissionDto,
3165
+ createRoleDto,
3166
+ createTokenDto,
3167
+ createUserDto,
3168
+ emailParam,
3169
+ formatDate,
3170
+ getAuthLocale,
3171
+ getAvatarFile,
3172
+ isAdmin,
3173
+ isAdministrator,
3174
+ isAuth,
3175
+ isEmpty,
3176
+ isFile,
3177
+ isPath,
3178
+ languageParam,
3179
+ loginDto,
3180
+ parseSchema,
3181
+ permissionIdParam,
3182
+ permissionsTable,
3183
+ pickProps,
3184
+ refreshTokenDto,
3185
+ resetPasswordDto,
3186
+ revokeTokenDto,
3187
+ roleIdParam,
3188
+ rolePermissionsTable,
3189
+ rolesTable,
3190
+ seedAuthData,
3191
+ tokenIdParam,
3192
+ tokensTable,
3193
+ updatePermissionDto,
3194
+ updateRoleDto,
3195
+ updateTokenDto,
3196
+ updateUserDto,
3197
+ userIdInParam,
3198
+ userIdParam,
3199
+ usersTable,
3200
+ verifyTokenDto
3201
+ };