najm-auth 1.1.44 → 2.0.2

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 CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/AuthPlugin.ts
9
- import { Err as Err8, plugin } from "najm-core";
9
+ import { Err as Err10, plugin } from "najm-core";
10
10
  import { cache } from "najm-cache";
11
11
 
12
12
  // src/auth.tokens.ts
@@ -18,7 +18,7 @@ var AUTH_PERMISSIONS = /* @__PURE__ */ Symbol.for("najm:auth:permissions");
18
18
  var AUTH_ENCRYPTION_KEY = /* @__PURE__ */ Symbol.for("najm:auth:encryption-key");
19
19
 
20
20
  // src/schema/pg.ts
21
- import { pgTable, text, boolean, timestamp, pgEnum, primaryKey, integer, index } from "drizzle-orm/pg-core";
21
+ import { pgTable, text, boolean, timestamp, pgEnum, primaryKey, integer, index, uniqueIndex } from "drizzle-orm/pg-core";
22
22
  import { sql } from "drizzle-orm";
23
23
  import { nanoid } from "nanoid";
24
24
 
@@ -58,6 +58,16 @@ var usersTable = pgTable("users", {
58
58
  }, (table) => ({
59
59
  roleIdx: index("users_role_id_idx").on(table.roleId)
60
60
  }));
61
+ var oauthAccountsTable = pgTable("oauth_accounts", {
62
+ ...baseFields(10),
63
+ userId: text("user_id").notNull().references(() => usersTable.id, { onDelete: "cascade" }),
64
+ provider: text("provider").notNull(),
65
+ providerAccountId: text("provider_account_id").notNull()
66
+ }, (table) => ({
67
+ providerAccountUnique: uniqueIndex("oauth_accounts_provider_account_unique").on(table.provider, table.providerAccountId),
68
+ userProviderUnique: uniqueIndex("oauth_accounts_user_provider_unique").on(table.userId, table.provider),
69
+ userIdIdx: index("oauth_accounts_user_id_idx").on(table.userId)
70
+ }));
61
71
  var permissionsTable = pgTable("permissions", {
62
72
  ...baseFields(5),
63
73
  name: text("name").notNull().unique(),
@@ -89,6 +99,7 @@ var rolePermissionsTable = pgTable("role_permissions", {
89
99
  }));
90
100
  var authSchema = {
91
101
  users: usersTable,
102
+ oauthAccounts: oauthAccountsTable,
92
103
  tokens: tokensTable,
93
104
  roles: rolesTable,
94
105
  permissions: permissionsTable,
@@ -96,7 +107,7 @@ var authSchema = {
96
107
  };
97
108
 
98
109
  // src/schema/sqlite.ts
99
- import { sqliteTable, text as text2, integer as integer2, uniqueIndex, index as index2 } from "drizzle-orm/sqlite-core";
110
+ import { sqliteTable, text as text2, integer as integer2, uniqueIndex as uniqueIndex2, index as index2 } from "drizzle-orm/sqlite-core";
100
111
  import { sql as sql2 } from "drizzle-orm";
101
112
  import { nanoid as nanoid2 } from "nanoid";
102
113
  var baseFields2 = /* @__PURE__ */ __name((idLength = 5) => ({
@@ -126,6 +137,16 @@ var usersTable2 = sqliteTable("users", {
126
137
  }, (table) => ({
127
138
  roleIdx: index2("users_role_id_idx").on(table.roleId)
128
139
  }));
140
+ var oauthAccountsTable2 = sqliteTable("oauth_accounts", {
141
+ ...baseFields2(10),
142
+ userId: text2("user_id").notNull().references(() => usersTable2.id, { onDelete: "cascade" }),
143
+ provider: text2("provider").notNull(),
144
+ providerAccountId: text2("provider_account_id").notNull()
145
+ }, (table) => ({
146
+ providerAccountUnique: uniqueIndex2("oauth_accounts_provider_account_unique").on(table.provider, table.providerAccountId),
147
+ userProviderUnique: uniqueIndex2("oauth_accounts_user_provider_unique").on(table.userId, table.provider),
148
+ userIdIdx: index2("oauth_accounts_user_id_idx").on(table.userId)
149
+ }));
129
150
  var permissionsTable2 = sqliteTable("permissions", {
130
151
  ...baseFields2(5),
131
152
  name: text2("name").notNull().unique(),
@@ -153,10 +174,11 @@ var rolePermissionsTable2 = sqliteTable("role_permissions", {
153
174
  roleId: text2("role_id").notNull().references(() => rolesTable2.id, { onDelete: "cascade" }),
154
175
  permissionId: text2("permission_id").notNull().references(() => permissionsTable2.id, { onDelete: "cascade" })
155
176
  }, (table) => ({
156
- uniq: uniqueIndex("role_permission_unique").on(table.roleId, table.permissionId)
177
+ uniq: uniqueIndex2("role_permission_unique").on(table.roleId, table.permissionId)
157
178
  }));
158
179
  var authSchema2 = {
159
180
  users: usersTable2,
181
+ oauthAccounts: oauthAccountsTable2,
160
182
  tokens: tokensTable2,
161
183
  roles: rolesTable2,
162
184
  permissions: permissionsTable2,
@@ -290,6 +312,9 @@ var CookieManager = class CookieManager2 {
290
312
  get cookieName() {
291
313
  return this.config.refreshCookieName || "refreshToken";
292
314
  }
315
+ get refreshCookiePath() {
316
+ return this.config.refreshCookiePath || "/";
317
+ }
293
318
  get sessionCookieName() {
294
319
  return this.config.session.name;
295
320
  }
@@ -304,10 +329,10 @@ var CookieManager = class CookieManager2 {
304
329
  // =========================================================================
305
330
  setRefreshToken(refreshToken) {
306
331
  const maxAge = timestring(this.config.jwt.refreshExpiresIn, "s");
307
- this.cookieService.set(this.cookieName, refreshToken, { maxAge });
332
+ this.cookieService.set(this.cookieName, refreshToken, { maxAge, path: this.refreshCookiePath });
308
333
  }
309
334
  clearRefreshToken() {
310
- this.cookieService.delete(this.cookieName);
335
+ this.cookieService.delete(this.cookieName, { path: this.refreshCookiePath });
311
336
  }
312
337
  getRefreshToken() {
313
338
  return this.cookieService.get(this.cookieName);
@@ -373,14 +398,14 @@ CookieManager = __decorate2([
373
398
  ], CookieManager);
374
399
 
375
400
  // src/auth/AuthController.ts
376
- import { Controller as Controller2 } from "najm-core";
377
- import { Get as Get2, Post as Post2, ResMsg as ResMsg2 } from "najm-core";
378
- import { Body as Body2, User as User3, Headers } from "najm-core";
401
+ import { Controller } from "najm-core";
402
+ import { Get, Post, ResMsg } from "najm-core";
403
+ import { Body, User as User3, Headers } from "najm-core";
379
404
 
380
405
  // src/auth/AuthService.ts
381
- import { Injectable as Injectable7, Inject as Inject8 } from "najm-core";
382
- import { Err as Err6, Log } from "najm-core";
383
- import { I18n as I18n5, I18nService as I18nService2 } from "najm-i18n";
406
+ import { Injectable as Injectable8, Inject as Inject8 } from "najm-core";
407
+ import { Err as Err8, Log } from "najm-core";
408
+ import { I18n as I18n6, I18nService as I18nService2 } from "najm-i18n";
384
409
  import { EmailService, passwordResetTemplate, accountInviteTemplate } from "najm-email";
385
410
  import { nanoid as nanoid5 } from "nanoid";
386
411
 
@@ -388,7 +413,7 @@ import { nanoid as nanoid5 } from "nanoid";
388
413
  import { Injectable as Injectable5, Inject as Inject5 } from "najm-core";
389
414
  import { Transaction } from "najm-database";
390
415
  import { I18nService } from "najm-i18n";
391
- import { I18n as I18n3 } from "najm-i18n";
416
+ import { I18n as I18n4 } from "najm-i18n";
392
417
 
393
418
  // src/users/UserRepository.ts
394
419
  import { eq as eq2, ne, sql as sql3 } from "drizzle-orm";
@@ -548,6 +573,15 @@ var UserRepository = class UserRepository2 {
548
573
  }).from(this.users).leftJoin(this.roles, eq2(this.users.roleId, this.roles.id)).where(eq2(this.users.email, email2));
549
574
  return existingUser;
550
575
  }
576
+ async getByEmailInsensitive(email2) {
577
+ const [existingUser] = await this.db.select({
578
+ ...this.q.userSelection(),
579
+ password: this.users.password,
580
+ failedLoginAttempts: this.users.failedLoginAttempts,
581
+ lockoutUntil: this.users.lockoutUntil
582
+ }).from(this.users).leftJoin(this.roles, eq2(this.users.roleId, this.roles.id)).where(sql3`lower(${this.users.email}) = ${email2.trim().toLowerCase()}`).limit(1);
583
+ return existingUser;
584
+ }
551
585
  async create(data) {
552
586
  const [newUser] = await this.db.insert(this.users).values(data).returning();
553
587
  return newUser;
@@ -758,7 +792,8 @@ UserValidator = __decorate4([
758
792
  ], UserValidator);
759
793
 
760
794
  // src/roles/RoleService.ts
761
- import { Injectable as Injectable4 } from "najm-core";
795
+ import { Injectable as Injectable4, Err as Err3 } from "najm-core";
796
+ import { I18n as I18n3 } from "najm-i18n";
762
797
 
763
798
  // src/roles/RoleRepository.ts
764
799
  import { eq as eq3 } from "drizzle-orm";
@@ -782,6 +817,14 @@ var RoleRepository = class RoleRepository2 {
782
817
  get roles() {
783
818
  return this.schema.roles;
784
819
  }
820
+ get users() {
821
+ return this.schema.users;
822
+ }
823
+ /** True if any user currently references this role (blocks deletion). */
824
+ async hasUsers(roleId) {
825
+ const rows = await this.db.select({ id: this.users.id }).from(this.users).where(eq3(this.users.roleId, roleId)).limit(1);
826
+ return rows.length > 0;
827
+ }
785
828
  async getAll() {
786
829
  return await this.db.select().from(this.roles);
787
830
  }
@@ -917,6 +960,7 @@ var RoleService = class RoleService2 {
917
960
  }
918
961
  roleRepository;
919
962
  roleValidator;
963
+ t;
920
964
  constructor(roleRepository, roleValidator) {
921
965
  this.roleRepository = roleRepository;
922
966
  this.roleValidator = roleValidator;
@@ -936,12 +980,21 @@ var RoleService = class RoleService2 {
936
980
  return await this.roleRepository.create(data);
937
981
  }
938
982
  async update(id, data) {
939
- await this.roleValidator.checkRoleExists(id);
983
+ const role = await this.roleValidator.checkRoleExists(id);
984
+ if (role.name === ROLES.ADMIN && data.name && data.name !== ROLES.ADMIN) {
985
+ Err3(this.t("errors.cannotRenameSystem"), 403);
986
+ }
940
987
  await this.roleValidator.checkNameUnique(data.name, id);
941
988
  return await this.roleRepository.update(id, data);
942
989
  }
943
990
  async delete(id) {
944
- await this.roleValidator.checkRoleExists(id);
991
+ const role = await this.roleValidator.checkRoleExists(id);
992
+ if (role.name === ROLES.ADMIN) {
993
+ Err3(this.t("errors.cannotDeleteSystem"), 403);
994
+ }
995
+ if (await this.roleRepository.hasUsers(id)) {
996
+ Err3(this.t("errors.roleInUse"), 409);
997
+ }
945
998
  return await this.roleRepository.delete(id);
946
999
  }
947
1000
  async seedDefaultRoles(defaultRoles) {
@@ -960,6 +1013,10 @@ var RoleService = class RoleService2 {
960
1013
  return role?.id;
961
1014
  }
962
1015
  };
1016
+ __decorate7([
1017
+ I18n3("roles"),
1018
+ __metadata7("design:type", Object)
1019
+ ], RoleService.prototype, "t", void 0);
963
1020
  RoleService = __decorate7([
964
1021
  Injectable4(),
965
1022
  __metadata7("design:paramtypes", [typeof (_a4 = typeof RoleRepository !== "undefined" && RoleRepository) === "function" ? _a4 : Object, typeof (_b2 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b2 : Object])
@@ -972,7 +1029,7 @@ import { nanoid as nanoid3 } from "nanoid";
972
1029
  import * as fs from "fs/promises";
973
1030
  import * as path from "path";
974
1031
  import _isEmpty from "lodash.isempty";
975
- import { Err as Err3 } from "najm-core";
1032
+ import { Err as Err4 } from "najm-core";
976
1033
  var avatarsPath = path.join(process.cwd(), "avatars");
977
1034
  var parseSchema = /* @__PURE__ */ __name(async (schema, data) => {
978
1035
  try {
@@ -980,7 +1037,7 @@ var parseSchema = /* @__PURE__ */ __name(async (schema, data) => {
980
1037
  } catch (error) {
981
1038
  const errors = error.issues || error.errors || [];
982
1039
  const errorMessage = errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
983
- Err3(errorMessage);
1040
+ Err4(errorMessage);
984
1041
  }
985
1042
  }, "parseSchema");
986
1043
  var clean = /* @__PURE__ */ __name((obj) => {
@@ -1066,7 +1123,7 @@ var isPath = /* @__PURE__ */ __name((img) => typeof img === "string" && img.trim
1066
1123
  var isFile = /* @__PURE__ */ __name((img) => !!img && typeof img !== "string" && img instanceof File, "isFile");
1067
1124
 
1068
1125
  // src/users/UserService.ts
1069
- import { Err as Err4 } from "najm-core";
1126
+ import { Err as Err5 } from "najm-core";
1070
1127
  var __decorate8 = function(decorators, target, key, desc) {
1071
1128
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1072
1129
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1121,7 +1178,7 @@ var UserService = class UserService2 {
1121
1178
  }
1122
1179
  requireUser(user) {
1123
1180
  if (!user) {
1124
- Err4(this.t("errors.notFound"), 404);
1181
+ Err5(this.t("errors.notFound"), 404);
1125
1182
  }
1126
1183
  return user;
1127
1184
  }
@@ -1135,12 +1192,12 @@ var UserService = class UserService2 {
1135
1192
  if (roleByName) {
1136
1193
  return roleByName.id;
1137
1194
  }
1138
- Err4(`Role '${roleName}' not found`);
1195
+ Err5(`Role '${roleName}' not found`);
1139
1196
  }
1140
1197
  if (this.authConfig.defaultRole) {
1141
1198
  const defaultRole = await this.roleService.getByName(this.authConfig.defaultRole);
1142
1199
  if (!defaultRole) {
1143
- Err4(`Default role '${this.authConfig.defaultRole}' not found. Create it first or set defaultRole to null in auth config.`);
1200
+ Err5(`Default role '${this.authConfig.defaultRole}' not found. Create it first or set defaultRole to null in auth config.`);
1144
1201
  }
1145
1202
  return defaultRole.id;
1146
1203
  }
@@ -1167,13 +1224,16 @@ var UserService = class UserService2 {
1167
1224
  async findByEmail(email2) {
1168
1225
  return await this.userRepository.getByEmail(email2);
1169
1226
  }
1227
+ async findByEmailInsensitive(email2) {
1228
+ return await this.userRepository.getByEmailInsensitive(email2);
1229
+ }
1170
1230
  async getAuthRecordById(id) {
1171
1231
  return await this.userRepository.getRawById(id);
1172
1232
  }
1173
1233
  async create(data) {
1174
1234
  const { id, email: email2, name, image, emailVerified, password, roleId, role } = data;
1175
1235
  if (!password || typeof password !== "string" || password.trim().length === 0) {
1176
- Err4("Password is required");
1236
+ Err5("Password is required");
1177
1237
  }
1178
1238
  this.userValidator.validatePasswordStrength(password);
1179
1239
  let userId = id || nanoid3(10);
@@ -1247,10 +1307,10 @@ var UserService = class UserService2 {
1247
1307
  }
1248
1308
  async seedAdminUser(config) {
1249
1309
  if (!config?.email || !config?.password) {
1250
- Err4("Admin email and password must be provided via config parameter");
1310
+ Err5("Admin email and password must be provided via config parameter");
1251
1311
  }
1252
1312
  if (config.password.length < 12) {
1253
- Err4("Admin password must be at least 12 characters");
1313
+ Err5("Admin password must be at least 12 characters");
1254
1314
  }
1255
1315
  const adminRole = await this.roleValidator.checkAdminRoleExists();
1256
1316
  const existingUser = await this.userRepository.getByEmail(config.email);
@@ -1279,7 +1339,7 @@ var UserService = class UserService2 {
1279
1339
  }
1280
1340
  };
1281
1341
  __decorate8([
1282
- I18n3("users"),
1342
+ I18n4("users"),
1283
1343
  __metadata8("design:type", Object)
1284
1344
  ], UserService.prototype, "t", void 0);
1285
1345
  __decorate8([
@@ -1296,7 +1356,7 @@ UserService = __decorate8([
1296
1356
 
1297
1357
  // src/tokens/TokenService.ts
1298
1358
  import { Injectable as Injectable6, Inject as Inject7 } from "najm-core";
1299
- import { I18n as I18n4 } from "najm-i18n";
1359
+ import { I18n as I18n5 } from "najm-i18n";
1300
1360
  import { CacheService } from "najm-cache";
1301
1361
  import { createHash } from "crypto";
1302
1362
  import jwt from "jsonwebtoken";
@@ -1413,7 +1473,7 @@ TokenRepository = __decorate9([
1413
1473
 
1414
1474
  // src/tokens/TokenService.ts
1415
1475
  import timestring2 from "timestring";
1416
- import { Err as Err5 } from "najm-core";
1476
+ import { Err as Err6 } from "najm-core";
1417
1477
  var __decorate10 = function(decorators, target, key, desc) {
1418
1478
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1419
1479
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1482,7 +1542,7 @@ var TokenService = class TokenService2 {
1482
1542
  if (authorization?.startsWith("Bearer ")) {
1483
1543
  return authorization.split(" ")[1];
1484
1544
  }
1485
- Err5(this.t("errors.tokenMissing"));
1545
+ Err6(this.t("errors.tokenMissing"));
1486
1546
  }
1487
1547
  /**
1488
1548
  * Verify access token and check blacklist
@@ -1493,7 +1553,7 @@ var TokenService = class TokenService2 {
1493
1553
  try {
1494
1554
  payload = jwt.verify(token, this.config.jwt.accessSecret);
1495
1555
  } catch {
1496
- Err5(this.t("errors.tokenVerificationFailed"));
1556
+ Err6(this.t("errors.tokenVerificationFailed"));
1497
1557
  }
1498
1558
  const sessionKey = this.sessionVersionKey(payload.userId);
1499
1559
  const blacklistKey = payload.jti ? `${this.blacklistPrefix}${payload.jti}` : null;
@@ -1506,15 +1566,15 @@ var TokenService = class TokenService2 {
1506
1566
  const values = await this.getCacheValues(keys);
1507
1567
  const valueByKey = new Map(keys.map((key, i) => [key, values[i]]));
1508
1568
  if (blacklistKey && valueByKey.get(blacklistKey) != null) {
1509
- Err5(this.t("errors.tokenRevoked"));
1569
+ Err6(this.t("errors.tokenRevoked"));
1510
1570
  }
1511
1571
  if (familyKey && valueByKey.get(familyKey) != null) {
1512
- Err5(this.t("errors.tokenRevoked"));
1572
+ Err6(this.t("errors.tokenRevoked"));
1513
1573
  }
1514
1574
  const activeSessionVersion = this.parseSessionVersion(valueByKey.get(sessionKey) ?? null);
1515
1575
  const tokenSessionVersion = payload.sessionVersion ?? 0;
1516
1576
  if (tokenSessionVersion !== activeSessionVersion) {
1517
- Err5(this.t("errors.tokenRevoked"));
1577
+ Err6(this.t("errors.tokenRevoked"));
1518
1578
  }
1519
1579
  return payload;
1520
1580
  }
@@ -1523,13 +1583,13 @@ var TokenService = class TokenService2 {
1523
1583
  try {
1524
1584
  decoded = jwt.verify(token, this.config.jwt.refreshSecret);
1525
1585
  } catch {
1526
- Err5(this.t("errors.tokenVerificationFailed"));
1586
+ Err6(this.t("errors.tokenVerificationFailed"));
1527
1587
  }
1528
1588
  if (decoded.type && decoded.type !== "refresh") {
1529
- Err5(this.t("errors.tokenVerificationFailed"));
1589
+ Err6(this.t("errors.tokenVerificationFailed"));
1530
1590
  }
1531
1591
  if (!decoded.tokenFamily) {
1532
- Err5(this.t("errors.tokenVerificationFailed"));
1592
+ Err6(this.t("errors.tokenVerificationFailed"));
1533
1593
  }
1534
1594
  return { userId: decoded.userId, tokenFamily: decoded.tokenFamily };
1535
1595
  }
@@ -1548,12 +1608,12 @@ var TokenService = class TokenService2 {
1548
1608
  async resolveUserFromCookie() {
1549
1609
  const refreshToken = this.cookieManager.getRefreshToken();
1550
1610
  if (!refreshToken) {
1551
- Err5(this.t("errors.refreshTokenMissing"));
1611
+ Err6(this.t("errors.refreshTokenMissing"));
1552
1612
  }
1553
1613
  const { userId, tokenFamily } = this.verifyRefreshToken(refreshToken);
1554
1614
  const stored = await this.tokenRepository.getByFamily(tokenFamily);
1555
1615
  if (!stored || stored.userId !== userId) {
1556
- Err5(this.t("errors.refreshTokenInvalid"));
1616
+ Err6(this.t("errors.refreshTokenInvalid"));
1557
1617
  }
1558
1618
  const presentedHash = this.hashToken(refreshToken);
1559
1619
  if (presentedHash === stored.token) {
@@ -1563,7 +1623,7 @@ var TokenService = class TokenService2 {
1563
1623
  if (canRecover) {
1564
1624
  return userId;
1565
1625
  }
1566
- Err5(this.t("errors.refreshTokenInvalid"));
1626
+ Err6(this.t("errors.refreshTokenInvalid"));
1567
1627
  }
1568
1628
  // ============ USER RETRIEVAL (MAIN METHOD) ============
1569
1629
  async getUser(auth2) {
@@ -1604,7 +1664,15 @@ var TokenService = class TokenService2 {
1604
1664
  await this.cache.set(this.sessionVersionKey(data.userId), String(sessionVersion), this.accessTokenTtlMs());
1605
1665
  }
1606
1666
  const token = jwt.sign({ ...data, jti, sessionVersion, exp: expiresAt }, this.config.jwt.accessSecret);
1607
- return { token, expiresAt };
1667
+ return { token, expiresAt, sessionVersion };
1668
+ }
1669
+ /**
1670
+ * Current per-user session version (0 when never invalidated). The signed
1671
+ * session cookie stamps this so a fast-path reader can reject a cookie whose
1672
+ * session was invalidated after it was written.
1673
+ */
1674
+ async getSessionVersion(userId) {
1675
+ return this.getUserSessionVersion(userId);
1608
1676
  }
1609
1677
  /**
1610
1678
  * Generate access token with unique jti for blacklist support.
@@ -1643,6 +1711,7 @@ var TokenService = class TokenService2 {
1643
1711
  tokenFamily: family,
1644
1712
  roles: accessTokenData.roles,
1645
1713
  permissions: accessTokenData.permissions,
1714
+ sessionVersion: access.sessionVersion,
1646
1715
  accessToken: access.token,
1647
1716
  refreshToken: refresh.token,
1648
1717
  accessTokenExpiresAt: access.expiresAt,
@@ -1710,12 +1779,12 @@ var TokenService = class TokenService2 {
1710
1779
  async refreshTokens() {
1711
1780
  const refreshToken = this.cookieManager.getRefreshToken();
1712
1781
  if (!refreshToken) {
1713
- Err5(this.t("errors.refreshTokenMissing"));
1782
+ Err6(this.t("errors.refreshTokenMissing"));
1714
1783
  }
1715
1784
  const { userId, tokenFamily } = this.verifyRefreshToken(refreshToken);
1716
1785
  const stored = await this.tokenRepository.getByFamily(tokenFamily);
1717
1786
  if (!stored || stored.userId !== userId) {
1718
- Err5(this.t("errors.refreshTokenInvalid"));
1787
+ Err6(this.t("errors.refreshTokenInvalid"));
1719
1788
  }
1720
1789
  const presentedHash = this.hashToken(refreshToken);
1721
1790
  if (presentedHash === stored.token) {
@@ -1725,12 +1794,12 @@ var TokenService = class TokenService2 {
1725
1794
  if (canRecover) {
1726
1795
  const claimed = await this.tokenRepository.markPreviousUsed(tokenFamily, presentedHash);
1727
1796
  if (!claimed?.length) {
1728
- Err5(this.t("errors.refreshTokenInvalid"));
1797
+ Err6(this.t("errors.refreshTokenInvalid"));
1729
1798
  }
1730
1799
  return this.generateTokens(userId, tokenFamily);
1731
1800
  }
1732
1801
  await this.revokeSuspectRefreshFamily(userId, tokenFamily);
1733
- Err5(this.t("errors.refreshTokenInvalid"));
1802
+ Err6(this.t("errors.refreshTokenInvalid"));
1734
1803
  }
1735
1804
  /** Revoke every refresh session for a user (password change/reset, logout-all). */
1736
1805
  async revokeAllForUser(userId) {
@@ -1762,7 +1831,7 @@ var TokenService = class TokenService2 {
1762
1831
  const userId = await this.resolveUserFromCookie();
1763
1832
  const user = await this.getUserById(userId);
1764
1833
  if (!user) {
1765
- Err5(this.t("errors.refreshTokenInvalid"));
1834
+ Err6(this.t("errors.refreshTokenInvalid"));
1766
1835
  }
1767
1836
  return user;
1768
1837
  }
@@ -1904,15 +1973,15 @@ var TokenService = class TokenService2 {
1904
1973
  try {
1905
1974
  decoded = jwt.verify(token, this.config.jwt.refreshSecret);
1906
1975
  } catch {
1907
- Err5(this.t("errors.resetTokenExpired"));
1976
+ Err6(this.t("errors.resetTokenExpired"));
1908
1977
  }
1909
1978
  if (decoded.type !== "reset" && decoded.type !== "invite" || !decoded.jti) {
1910
- Err5(this.t("errors.invalidResetToken"));
1979
+ Err6(this.t("errors.invalidResetToken"));
1911
1980
  }
1912
1981
  const key = `${this.resetTokenPrefix}${decoded.userId}`;
1913
1982
  const storedJti = await this.cache.get(key);
1914
1983
  if (!storedJti || storedJti !== decoded.jti) {
1915
- Err5(this.t("errors.invalidResetToken"));
1984
+ Err6(this.t("errors.invalidResetToken"));
1916
1985
  }
1917
1986
  await this.cache.del(key);
1918
1987
  return decoded.userId;
@@ -1926,7 +1995,7 @@ __decorate10([
1926
1995
  __metadata10("design:type", Object)
1927
1996
  ], TokenService.prototype, "config", void 0);
1928
1997
  __decorate10([
1929
- I18n4("auth"),
1998
+ I18n5("auth"),
1930
1999
  __metadata10("design:type", Object)
1931
2000
  ], TokenService.prototype, "t", void 0);
1932
2001
  TokenService = TokenService_1 = __decorate10([
@@ -1936,6 +2005,10 @@ TokenService = TokenService_1 = __decorate10([
1936
2005
 
1937
2006
  // src/auth/AuthService.ts
1938
2007
  import timestring3 from "timestring";
2008
+
2009
+ // src/auth/AuthSessionService.ts
2010
+ import { Injectable as Injectable7 } from "najm-core";
2011
+ import { Err as Err7 } from "najm-core";
1939
2012
  var __decorate11 = function(decorators, target, key, desc) {
1940
2013
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1941
2014
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1948,10 +2021,66 @@ var __metadata11 = function(k, v) {
1948
2021
  var _a7;
1949
2022
  var _b5;
1950
2023
  var _c3;
2024
+ var AuthSessionService = class AuthSessionService2 {
2025
+ static {
2026
+ __name(this, "AuthSessionService");
2027
+ }
2028
+ tokenService;
2029
+ userService;
2030
+ cookieManager;
2031
+ constructor(tokenService, userService, cookieManager) {
2032
+ this.tokenService = tokenService;
2033
+ this.userService = userService;
2034
+ this.cookieManager = cookieManager;
2035
+ }
2036
+ async establish(user) {
2037
+ if (user.status !== "active") {
2038
+ Err7("oauth_account_inactive", 403);
2039
+ }
2040
+ await this.tokenService.deleteExpiredSessions();
2041
+ const generated = await this.tokenService.generateTokens(user.id);
2042
+ this.cookieManager.setRefreshToken(generated.refreshToken);
2043
+ await this.userService.updateLastLogin(user.id);
2044
+ const { roles, permissions, sessionVersion } = generated;
2045
+ this.cookieManager.setSessionCookie({
2046
+ user: {
2047
+ id: user.id,
2048
+ email: user.email,
2049
+ name: user.name,
2050
+ role: user.role ?? void 0,
2051
+ status: user.status ?? void 0
2052
+ },
2053
+ roles,
2054
+ permissions,
2055
+ sessionVersion
2056
+ });
2057
+ const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sessionVersion, ...tokens } = generated;
2058
+ return { ...tokens, user };
2059
+ }
2060
+ };
2061
+ AuthSessionService = __decorate11([
2062
+ Injectable7(),
2063
+ __metadata11("design:paramtypes", [typeof (_a7 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a7 : Object, typeof (_b5 = typeof UserService !== "undefined" && UserService) === "function" ? _b5 : Object, typeof (_c3 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c3 : Object])
2064
+ ], AuthSessionService);
2065
+
2066
+ // src/auth/AuthService.ts
2067
+ var __decorate12 = function(decorators, target, key, desc) {
2068
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2069
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2070
+ 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;
2071
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2072
+ };
2073
+ var __metadata12 = function(k, v) {
2074
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2075
+ };
2076
+ var _a8;
2077
+ var _b6;
2078
+ var _c4;
1951
2079
  var _d2;
1952
2080
  var _e2;
1953
2081
  var _f2;
1954
2082
  var _g2;
2083
+ var _h2;
1955
2084
  var AuthService = class AuthService2 {
1956
2085
  static {
1957
2086
  __name(this, "AuthService");
@@ -1963,11 +2092,12 @@ var AuthService = class AuthService2 {
1963
2092
  cookieManager;
1964
2093
  i18nService;
1965
2094
  emailService;
2095
+ authSessionService;
1966
2096
  config;
1967
2097
  t;
1968
2098
  logger;
1969
2099
  dummyHash;
1970
- constructor(tokenService, userService, userValidator, encryptionService, cookieManager, i18nService, emailService) {
2100
+ constructor(tokenService, userService, userValidator, encryptionService, cookieManager, i18nService, emailService, authSessionService) {
1971
2101
  this.tokenService = tokenService;
1972
2102
  this.userService = userService;
1973
2103
  this.userValidator = userValidator;
@@ -1975,6 +2105,7 @@ var AuthService = class AuthService2 {
1975
2105
  this.cookieManager = cookieManager;
1976
2106
  this.i18nService = i18nService;
1977
2107
  this.emailService = emailService;
2108
+ this.authSessionService = authSessionService;
1978
2109
  }
1979
2110
  isLockoutActive(lockoutUntil) {
1980
2111
  if (!lockoutUntil)
@@ -1993,7 +2124,13 @@ var AuthService = class AuthService2 {
1993
2124
  await this.getDummyHash();
1994
2125
  }
1995
2126
  async registerUser(body) {
1996
- return await this.userService.create(body);
2127
+ return await this.userService.create({
2128
+ name: body.name,
2129
+ email: body.email,
2130
+ password: body.password,
2131
+ image: body.image,
2132
+ emailVerified: false
2133
+ });
1997
2134
  }
1998
2135
  /**
1999
2136
  * Admin-initiated account creation. The user is created with a random,
@@ -2019,15 +2156,17 @@ var AuthService = class AuthService2 {
2019
2156
  });
2020
2157
  const { token } = await this.tokenService.generateInviteToken(user.id);
2021
2158
  const inviteLink = `${this.config.frontendUrl}/reset-password?token=${token}`;
2159
+ let emailSent = false;
2022
2160
  try {
2023
2161
  await this.emailService.sendHtml(body.email, this.t("emails.accountInvite.subject"), accountInviteTemplate({
2024
2162
  inviteLink,
2025
2163
  userName: user.name || body.email
2026
2164
  }));
2165
+ emailSent = true;
2027
2166
  } catch (error) {
2028
2167
  this.logger.warn("Account invite email failed", { email: body.email, error });
2029
2168
  }
2030
- return user;
2169
+ return { ...user, emailSent };
2031
2170
  }
2032
2171
  /**
2033
2172
  * Create a login for a person record. The branch is intentional and is the
@@ -2062,7 +2201,7 @@ var AuthService = class AuthService2 {
2062
2201
  user.lockoutUntil = null;
2063
2202
  }
2064
2203
  if (user && this.isLockoutActive(user.lockoutUntil)) {
2065
- Err6(this.t("errors.accountLocked"), 423);
2204
+ Err8(this.t("errors.accountLocked"), 423);
2066
2205
  }
2067
2206
  const storedHash = user?.password ?? await this.getDummyHash();
2068
2207
  const isValid = await this.userValidator.comparePassword(password, storedHash);
@@ -2071,30 +2210,23 @@ var AuthService = class AuthService2 {
2071
2210
  const attempts = await this.userService.incrementFailedAttempts(user.id);
2072
2211
  if (attempts >= this.config.lockout.maxAttempts) {
2073
2212
  await this.userService.setLockout(user.id, this.nextLockoutUntil());
2074
- Err6(this.t("errors.accountLocked"), 423);
2213
+ Err8(this.t("errors.accountLocked"), 423);
2075
2214
  }
2076
2215
  }
2077
- Err6(this.t("errors.invalidCredentials"));
2216
+ Err8(this.t("errors.invalidCredentials"));
2078
2217
  }
2079
2218
  if (user.status !== "active") {
2080
- Err6(this.t("errors.accountInactive"));
2219
+ Err8(this.t("errors.accountInactive"));
2220
+ }
2221
+ if (this.config.requireVerifiedEmail && !user.emailVerified) {
2222
+ Err8(this.t("errors.emailNotVerified"), 403);
2081
2223
  }
2082
2224
  if ((user.failedLoginAttempts ?? 0) > 0 || user.lockoutUntil) {
2083
2225
  await this.userService.resetFailedAttempts(user.id);
2084
2226
  }
2085
- await this.tokenService.deleteExpiredSessions();
2086
- const generated = await this.tokenService.generateTokens(user.id);
2087
- this.cookieManager.setRefreshToken(generated.refreshToken);
2088
- await this.userService.updateLastLogin(user.id);
2089
2227
  const { password: _, failedLoginAttempts: __, lockoutUntil: ___, ...sanitized } = user;
2090
- const { roles, permissions } = generated;
2091
- this.cookieManager.setSessionCookie({
2092
- user: { id: sanitized.id, email: sanitized.email, name: sanitized.name, role: sanitized.role, status: sanitized.status ?? void 0 },
2093
- roles,
2094
- permissions
2095
- });
2096
- const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, ...tokens } = generated;
2097
- return { ...tokens, user: sanitized };
2228
+ this.authSessionService ??= new AuthSessionService(this.tokenService, this.userService, this.cookieManager);
2229
+ return this.authSessionService.establish(sanitized);
2098
2230
  }
2099
2231
  async refreshTokens() {
2100
2232
  const generated = await this.tokenService.refreshTokens();
@@ -2104,10 +2236,11 @@ var AuthService = class AuthService2 {
2104
2236
  this.cookieManager.setSessionCookie({
2105
2237
  user: { id: user.id, email: user.email, name: user.name, role: user.role, status: user.status ?? void 0 },
2106
2238
  roles: generated.roles,
2107
- permissions: generated.permissions
2239
+ permissions: generated.permissions,
2240
+ sessionVersion: generated.sessionVersion
2108
2241
  });
2109
2242
  }
2110
- const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, ...tokens } = generated;
2243
+ const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sv, ...tokens } = generated;
2111
2244
  return tokens;
2112
2245
  }
2113
2246
  async logoutUser(userId, authorization) {
@@ -2153,7 +2286,7 @@ var AuthService = class AuthService2 {
2153
2286
  const lang = this.i18nService.getCurrentLanguage();
2154
2287
  result = { ...user, language: lang };
2155
2288
  const token = this.tokenService.decodeAccessToken(authorization.replace(/^Bearer\s+/i, ""));
2156
- cachePayload = { roles: token?.roles ?? [], permissions: token?.permissions ?? [] };
2289
+ cachePayload = { roles: token?.roles ?? [], permissions: token?.permissions ?? [], sessionVersion: token?.sessionVersion ?? 0 };
2157
2290
  } else {
2158
2291
  result = await this.getUserFromCookie();
2159
2292
  }
@@ -2164,7 +2297,8 @@ var AuthService = class AuthService2 {
2164
2297
  this.cookieManager.setSessionCookie({
2165
2298
  user: { id: result.id, email: result.email, name: result.name, role: result.role, status: result.status ?? void 0 },
2166
2299
  roles: cachePayload.roles,
2167
- permissions: cachePayload.permissions
2300
+ permissions: cachePayload.permissions,
2301
+ sessionVersion: cachePayload.sessionVersion
2168
2302
  });
2169
2303
  }
2170
2304
  return result;
@@ -2188,11 +2322,11 @@ var AuthService = class AuthService2 {
2188
2322
  async changePassword(userId, currentPassword, newPassword) {
2189
2323
  const user = await this.userService.getAuthRecordById(userId);
2190
2324
  if (!user?.password) {
2191
- Err6(this.t("errors.invalidCredentials"));
2325
+ Err8(this.t("errors.invalidCredentials"));
2192
2326
  }
2193
2327
  const isValid = await this.userValidator.comparePassword(currentPassword, user.password);
2194
2328
  if (!isValid) {
2195
- Err6(this.t("errors.invalidCredentials"));
2329
+ Err8(this.t("errors.invalidCredentials"));
2196
2330
  }
2197
2331
  this.userValidator.validatePasswordStrength(newPassword);
2198
2332
  await this.userService.update(userId, { password: newPassword });
@@ -2213,33 +2347,33 @@ var AuthService = class AuthService2 {
2213
2347
  return { message: this.t("success.passwordReset") };
2214
2348
  }
2215
2349
  };
2216
- __decorate11([
2350
+ __decorate12([
2217
2351
  Inject8(AUTH_CONFIG),
2218
- __metadata11("design:type", Object)
2352
+ __metadata12("design:type", Object)
2219
2353
  ], AuthService.prototype, "config", void 0);
2220
- __decorate11([
2221
- I18n5("auth"),
2222
- __metadata11("design:type", Object)
2354
+ __decorate12([
2355
+ I18n6("auth"),
2356
+ __metadata12("design:type", Object)
2223
2357
  ], AuthService.prototype, "t", void 0);
2224
- __decorate11([
2358
+ __decorate12([
2225
2359
  Log(),
2226
- __metadata11("design:type", Object)
2360
+ __metadata12("design:type", Object)
2227
2361
  ], AuthService.prototype, "logger", void 0);
2228
- AuthService = __decorate11([
2229
- Injectable7(),
2230
- __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 EncryptionService !== "undefined" && EncryptionService) === "function" ? _d2 : Object, typeof (_e2 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _e2 : Object, typeof (_f2 = typeof I18nService2 !== "undefined" && I18nService2) === "function" ? _f2 : Object, typeof (_g2 = typeof EmailService !== "undefined" && EmailService) === "function" ? _g2 : Object])
2362
+ AuthService = __decorate12([
2363
+ Injectable8(),
2364
+ __metadata12("design:paramtypes", [typeof (_a8 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a8 : Object, typeof (_b6 = typeof UserService !== "undefined" && UserService) === "function" ? _b6 : Object, typeof (_c4 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _c4 : Object, typeof (_d2 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _d2 : Object, typeof (_e2 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _e2 : Object, typeof (_f2 = typeof I18nService2 !== "undefined" && I18nService2) === "function" ? _f2 : Object, typeof (_g2 = typeof EmailService !== "undefined" && EmailService) === "function" ? _g2 : Object, typeof (_h2 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _h2 : Object])
2231
2365
  ], AuthService);
2232
2366
 
2233
2367
  // src/auth/AuthGuard.ts
2234
2368
  import { Service as Service2, User } from "najm-core";
2235
2369
  import { createGuard } from "najm-guard";
2236
- var __decorate12 = function(decorators, target, key, desc) {
2370
+ var __decorate13 = function(decorators, target, key, desc) {
2237
2371
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2238
2372
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2239
2373
  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
2374
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2241
2375
  };
2242
- var __metadata12 = function(k, v) {
2376
+ var __metadata13 = function(k, v) {
2243
2377
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2244
2378
  };
2245
2379
  var __param3 = function(paramIndex, decorator) {
@@ -2255,51 +2389,28 @@ var AuthGuard = class AuthGuard2 {
2255
2389
  return !!user;
2256
2390
  }
2257
2391
  };
2258
- __decorate12([
2392
+ __decorate13([
2259
2393
  __param3(0, User()),
2260
- __metadata12("design:type", Function),
2261
- __metadata12("design:paramtypes", [Object]),
2262
- __metadata12("design:returntype", Boolean)
2394
+ __metadata13("design:type", Function),
2395
+ __metadata13("design:paramtypes", [Object]),
2396
+ __metadata13("design:returntype", Boolean)
2263
2397
  ], AuthGuard.prototype, "canActivate", null);
2264
- AuthGuard = __decorate12([
2398
+ AuthGuard = __decorate13([
2265
2399
  Service2()
2266
2400
  ], AuthGuard);
2267
2401
  var isAuth = createGuard(AuthGuard);
2268
2402
 
2269
- // src/roles/index.ts
2270
- var roles_exports = {};
2271
- __export(roles_exports, {
2272
- ROLES: () => ROLES,
2273
- ROLE_GROUPS: () => ROLE_GROUPS,
2274
- Role: () => Role,
2275
- RoleController: () => RoleController,
2276
- RoleGuard: () => RoleGuard,
2277
- RoleRepository: () => RoleRepository,
2278
- RoleService: () => RoleService,
2279
- RoleValidator: () => RoleValidator,
2280
- assignRoleDto: () => assignRoleDto,
2281
- createRoleDto: () => createRoleDto,
2282
- defineRoles: () => defineRoles,
2283
- isAdmin: () => isAdmin,
2284
- isAdministrator: () => isAdministrator,
2285
- roleIdParam: () => roleIdParam,
2286
- updateRoleDto: () => updateRoleDto
2287
- });
2288
-
2289
- // src/roles/defineRoles.ts
2290
- import { composeGuards as composeGuards2, createGuard as createGuard3 } from "najm-guard";
2291
-
2292
2403
  // src/roles/RoleGuards.ts
2293
2404
  import { Service as Service3 } from "najm-core";
2294
2405
  import { GuardParams, User as User2 } from "najm-core";
2295
2406
  import { composeGuards, createGuard as createGuard2 } from "najm-guard";
2296
- var __decorate13 = function(decorators, target, key, desc) {
2407
+ var __decorate14 = function(decorators, target, key, desc) {
2297
2408
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2298
2409
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2299
2410
  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;
2300
2411
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2301
2412
  };
2302
- var __metadata13 = function(k, v) {
2413
+ var __metadata14 = function(k, v) {
2303
2414
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2304
2415
  };
2305
2416
  var __param4 = function(paramIndex, decorator) {
@@ -2322,86 +2433,96 @@ var RoleGuard = class RoleGuard2 {
2322
2433
  return false;
2323
2434
  }
2324
2435
  };
2325
- __decorate13([
2436
+ __decorate14([
2326
2437
  __param4(0, GuardParams()),
2327
2438
  __param4(1, User2("role")),
2328
- __metadata13("design:type", Function),
2329
- __metadata13("design:paramtypes", [Object, String]),
2330
- __metadata13("design:returntype", void 0)
2439
+ __metadata14("design:type", Function),
2440
+ __metadata14("design:paramtypes", [Object, String]),
2441
+ __metadata14("design:returntype", void 0)
2331
2442
  ], RoleGuard.prototype, "canActivate", null);
2332
- RoleGuard = __decorate13([
2443
+ RoleGuard = __decorate14([
2333
2444
  Service3()
2334
2445
  ], RoleGuard);
2335
2446
  var Role = createGuard2(RoleGuard);
2336
2447
  var isAdmin = composeGuards(isAuth(), Role(ROLES.ADMIN));
2337
2448
  var isAdministrator = composeGuards(isAuth(), Role(ROLE_GROUPS.ADMINISTRATORS));
2338
2449
 
2339
- // src/roles/defineRoles.ts
2340
- var Role2 = createGuard3(RoleGuard);
2341
- function defineRoles(roles, options) {
2342
- const ROLES2 = roles;
2343
- const superRoleKeys = options?.superRoles ?? [];
2344
- function resolveRoleValues(keys) {
2345
- return Array.from(new Set([...keys, ...superRoleKeys].map((key) => roles[key])));
2346
- }
2347
- __name(resolveRoleValues, "resolveRoleValues");
2348
- const guards2 = {};
2349
- for (const [key, value] of Object.entries(roles)) {
2350
- const name = `is${key.charAt(0).toUpperCase()}${key.slice(1).toLowerCase()}`;
2351
- const allowedValues = resolveRoleValues([key]);
2352
- guards2[name] = composeGuards2(isAuth(), Role2(allowedValues.length === 1 ? value : allowedValues));
2353
- }
2354
- function createGroupGuard(keys) {
2355
- const values = resolveRoleValues(keys);
2356
- return composeGuards2(isAuth(), Role2(values));
2357
- }
2358
- __name(createGroupGuard, "createGroupGuard");
2359
- function hasRole(userRole, ...keys) {
2360
- if (!userRole)
2361
- return false;
2362
- const normalized = userRole.toLowerCase();
2363
- return resolveRoleValues(keys).some((role) => role === normalized);
2364
- }
2365
- __name(hasRole, "hasRole");
2366
- function isInGroup(userRole, keys) {
2367
- return hasRole(userRole, ...keys);
2368
- }
2369
- __name(isInGroup, "isInGroup");
2370
- return { ROLES: ROLES2, createGroupGuard, hasRole, isInGroup, ...guards2 };
2371
- }
2372
- __name(defineRoles, "defineRoles");
2373
-
2374
- // src/roles/RoleController.ts
2375
- import { Controller } from "najm-core";
2376
- import { Get, Post, Put, Delete, ResMsg } from "najm-core";
2377
- import { Params, Body } from "najm-core";
2450
+ // src/auth/AuthController.ts
2378
2451
  import { Validate } from "najm-validation";
2452
+ import { RateLimit } from "najm-rate";
2453
+ import { createHash as createHash2 } from "crypto";
2379
2454
 
2380
- // src/roles/RoleDto.ts
2455
+ // src/users/UserDto.ts
2381
2456
  import { z } from "zod";
2382
- var nameField = z.string().min(2, "Name must be at least 2 characters").max(50, "Name too long");
2383
- var descriptionField = z.string().max(255, "Description too long").optional();
2384
- var createRoleDto = z.object({
2385
- name: nameField,
2386
- description: descriptionField
2457
+ var emailField = z.string().email("Invalid email format");
2458
+ var passwordField = z.string().min(8, "Password must be at least 8 characters").refine((v) => new TextEncoder().encode(v).length <= 72, "Password must be at most 72 bytes").regex(/[A-Z]/, "Password must contain at least one uppercase letter").regex(/[a-z]/, "Password must contain at least one lowercase letter").regex(/\d/, "Password must contain at least one number");
2459
+ var optionalDateField = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").nullable().optional();
2460
+ var createUserDto = z.object({
2461
+ name: z.string().max(100).optional(),
2462
+ email: emailField,
2463
+ password: passwordField,
2464
+ roleId: z.string().min(1).optional(),
2465
+ image: z.string().nullish(),
2466
+ emailVerified: z.boolean().default(false),
2467
+ status: z.enum(["active", "inactive", "pending"]).optional()
2387
2468
  });
2388
- var updateRoleDto = createRoleDto.partial();
2389
- var roleIdParam = z.object({
2390
- id: z.string().length(5, "Role ID must be 5 characters")
2469
+ var updateUserDto = createUserDto.partial();
2470
+ var registerDto = z.object({
2471
+ name: z.string().max(100).optional(),
2472
+ email: emailField,
2473
+ password: passwordField,
2474
+ image: z.string().nullish()
2475
+ });
2476
+ var inviteUserDto = z.object({
2477
+ name: z.string().max(100).optional(),
2478
+ email: emailField,
2479
+ roleId: z.string().min(1).optional(),
2480
+ image: z.string().nullish()
2481
+ });
2482
+ var userIdParam = z.object({
2483
+ id: z.string().min(1, "User ID is required")
2484
+ });
2485
+ var loginDto = z.object({
2486
+ email: emailField,
2487
+ password: passwordField
2488
+ });
2489
+ var changePasswordDto = z.object({
2490
+ currentPassword: passwordField,
2491
+ newPassword: passwordField
2492
+ });
2493
+ var resetPasswordDto = z.object({
2494
+ email: emailField
2495
+ });
2496
+ var confirmResetPasswordDto = z.object({
2497
+ token: z.string().min(10, "Invalid reset token"),
2498
+ newPassword: passwordField
2499
+ });
2500
+ var languageParam = z.object({
2501
+ language: z.string().min(2)
2502
+ });
2503
+ var emailParam = z.object({
2504
+ email: emailField
2505
+ });
2506
+ var userIdInParam = z.object({
2507
+ userId: z.string().min(1, "User ID is required")
2391
2508
  });
2392
- var assignRoleDto = z.object({
2393
- userId: z.string().length(8, "User ID must be 8 characters"),
2394
- roleId: z.string().length(5, "Role ID must be 5 characters")
2509
+ var assignRoleParams = z.object({
2510
+ userId: z.string().min(1, "User ID is required"),
2511
+ roleId: z.string().min(1)
2512
+ });
2513
+ var userListQuery = z.object({
2514
+ limit: z.coerce.number().int().min(1).max(100).default(50),
2515
+ offset: z.coerce.number().int().min(0).default(0)
2395
2516
  });
2396
2517
 
2397
- // src/roles/RoleController.ts
2398
- var __decorate14 = function(decorators, target, key, desc) {
2518
+ // src/auth/AuthController.ts
2519
+ var __decorate15 = function(decorators, target, key, desc) {
2399
2520
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2400
2521
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2401
2522
  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;
2402
2523
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2403
2524
  };
2404
- var __metadata14 = function(k, v) {
2525
+ var __metadata15 = function(k, v) {
2405
2526
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2406
2527
  };
2407
2528
  var __param5 = function(paramIndex, decorator) {
@@ -2409,202 +2530,43 @@ var __param5 = function(paramIndex, decorator) {
2409
2530
  decorator(target, key, paramIndex);
2410
2531
  };
2411
2532
  };
2412
- var _a8;
2413
- var RoleController = class RoleController2 {
2414
- static {
2415
- __name(this, "RoleController");
2533
+ var _a9;
2534
+ var hashKeyPart = /* @__PURE__ */ __name((value) => createHash2("sha256").update(value).digest("base64url").slice(0, 32), "hashKeyPart");
2535
+ var cookieFingerprint = /* @__PURE__ */ __name(() => (ctx) => {
2536
+ const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
2537
+ const cookie = ctx.req.raw.headers.get("cookie") ?? "";
2538
+ const fingerprint = cookie ? hashKeyPart(cookie) : "none";
2539
+ return `${ip}:${fingerprint}`;
2540
+ }, "cookieFingerprint");
2541
+ var ipAndEmail = /* @__PURE__ */ __name(async (ctx) => {
2542
+ const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
2543
+ try {
2544
+ const body = await ctx.req.json();
2545
+ if (body?.email && typeof body.email === "string") {
2546
+ const normalizedEmail = body.email.trim().toLowerCase();
2547
+ if (normalizedEmail)
2548
+ return `${ip}:${hashKeyPart(normalizedEmail)}`;
2549
+ }
2550
+ } catch {
2416
2551
  }
2417
- roleService;
2418
- constructor(roleService) {
2419
- this.roleService = roleService;
2552
+ return ip;
2553
+ }, "ipAndEmail");
2554
+ var AuthController = class AuthController2 {
2555
+ static {
2556
+ __name(this, "AuthController");
2420
2557
  }
2421
- async getRoles() {
2422
- return this.roleService.getAll();
2558
+ authService;
2559
+ constructor(authService) {
2560
+ this.authService = authService;
2423
2561
  }
2424
- async getRole(params) {
2425
- return this.roleService.getById(params.id);
2562
+ async registerUser(body) {
2563
+ return this.authService.registerUser(body);
2426
2564
  }
2427
- async createRole(body) {
2428
- return this.roleService.create(body);
2565
+ async loginUser(body) {
2566
+ return this.authService.loginUser(body);
2429
2567
  }
2430
- async updateRole(params, body) {
2431
- return this.roleService.update(params.id, body);
2432
- }
2433
- async deleteRole(params) {
2434
- return this.roleService.delete(params.id);
2435
- }
2436
- };
2437
- __decorate14([
2438
- Get(),
2439
- isAdmin(),
2440
- ResMsg("roles.success.retrieved"),
2441
- __metadata14("design:type", Function),
2442
- __metadata14("design:paramtypes", []),
2443
- __metadata14("design:returntype", Promise)
2444
- ], RoleController.prototype, "getRoles", null);
2445
- __decorate14([
2446
- Get("/:id"),
2447
- isAdmin(),
2448
- Validate({ params: roleIdParam }),
2449
- ResMsg("roles.success.retrieved"),
2450
- __param5(0, Params()),
2451
- __metadata14("design:type", Function),
2452
- __metadata14("design:paramtypes", [Object]),
2453
- __metadata14("design:returntype", Promise)
2454
- ], RoleController.prototype, "getRole", null);
2455
- __decorate14([
2456
- Post(),
2457
- isAdmin(),
2458
- Validate(createRoleDto),
2459
- ResMsg("roles.success.created"),
2460
- __param5(0, Body()),
2461
- __metadata14("design:type", Function),
2462
- __metadata14("design:paramtypes", [Object]),
2463
- __metadata14("design:returntype", Promise)
2464
- ], RoleController.prototype, "createRole", null);
2465
- __decorate14([
2466
- Put("/:id"),
2467
- isAdmin(),
2468
- Validate({
2469
- params: roleIdParam,
2470
- body: updateRoleDto
2471
- }),
2472
- ResMsg("roles.success.updated"),
2473
- __param5(0, Params()),
2474
- __param5(1, Body()),
2475
- __metadata14("design:type", Function),
2476
- __metadata14("design:paramtypes", [Object, Object]),
2477
- __metadata14("design:returntype", Promise)
2478
- ], RoleController.prototype, "updateRole", null);
2479
- __decorate14([
2480
- Delete("/:id"),
2481
- isAdmin(),
2482
- Validate({ params: roleIdParam }),
2483
- ResMsg("roles.success.deleted"),
2484
- __param5(0, Params()),
2485
- __metadata14("design:type", Function),
2486
- __metadata14("design:paramtypes", [Object]),
2487
- __metadata14("design:returntype", Promise)
2488
- ], RoleController.prototype, "deleteRole", null);
2489
- RoleController = __decorate14([
2490
- Controller("/roles"),
2491
- __metadata14("design:paramtypes", [typeof (_a8 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a8 : Object])
2492
- ], RoleController);
2493
-
2494
- // src/auth/AuthController.ts
2495
- import { Validate as Validate2 } from "najm-validation";
2496
- import { RateLimit } from "najm-rate";
2497
- import { createHash as createHash2 } from "crypto";
2498
-
2499
- // src/users/UserDto.ts
2500
- import { z as z2 } from "zod";
2501
- var emailField = z2.string().email("Invalid email format");
2502
- var passwordField = z2.string().min(8, "Password must be at least 8 characters");
2503
- var optionalDateField = z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").nullable().optional();
2504
- var createUserDto = z2.object({
2505
- name: z2.string().max(100).optional(),
2506
- email: emailField,
2507
- password: passwordField,
2508
- roleId: z2.string().min(1).optional(),
2509
- image: z2.string().nullish(),
2510
- emailVerified: z2.boolean().default(false),
2511
- status: z2.enum(["active", "inactive", "pending"]).optional()
2512
- });
2513
- var updateUserDto = createUserDto.partial();
2514
- var inviteUserDto = z2.object({
2515
- name: z2.string().max(100).optional(),
2516
- email: emailField,
2517
- roleId: z2.string().min(1).optional(),
2518
- image: z2.string().nullish()
2519
- });
2520
- var userIdParam = z2.object({
2521
- id: z2.string().min(1, "User ID is required")
2522
- });
2523
- var loginDto = z2.object({
2524
- email: emailField,
2525
- password: passwordField
2526
- });
2527
- var changePasswordDto = z2.object({
2528
- currentPassword: passwordField,
2529
- newPassword: passwordField
2530
- });
2531
- var resetPasswordDto = z2.object({
2532
- email: emailField
2533
- });
2534
- var confirmResetPasswordDto = z2.object({
2535
- token: z2.string().min(10, "Invalid reset token"),
2536
- newPassword: passwordField
2537
- });
2538
- var languageParam = z2.object({
2539
- language: z2.string().min(2)
2540
- });
2541
- var emailParam = z2.object({
2542
- email: emailField
2543
- });
2544
- var userIdInParam = z2.object({
2545
- userId: z2.string().min(1, "User ID is required")
2546
- });
2547
- var assignRoleParams = z2.object({
2548
- userId: z2.string().min(1, "User ID is required"),
2549
- roleId: z2.string().min(1)
2550
- });
2551
- var userListQuery = z2.object({
2552
- limit: z2.coerce.number().int().min(1).max(100).default(50),
2553
- offset: z2.coerce.number().int().min(0).default(0)
2554
- });
2555
-
2556
- // src/auth/AuthController.ts
2557
- var __decorate15 = function(decorators, target, key, desc) {
2558
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2559
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2560
- 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;
2561
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2562
- };
2563
- var __metadata15 = function(k, v) {
2564
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2565
- };
2566
- var __param6 = function(paramIndex, decorator) {
2567
- return function(target, key) {
2568
- decorator(target, key, paramIndex);
2569
- };
2570
- };
2571
- var _a9;
2572
- var hashKeyPart = /* @__PURE__ */ __name((value) => createHash2("sha256").update(value).digest("base64url").slice(0, 32), "hashKeyPart");
2573
- var cookieFingerprint = /* @__PURE__ */ __name(() => (ctx) => {
2574
- const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
2575
- const cookie = ctx.req.raw.headers.get("cookie") ?? "";
2576
- const fingerprint = cookie ? hashKeyPart(cookie) : "none";
2577
- return `${ip}:${fingerprint}`;
2578
- }, "cookieFingerprint");
2579
- var ipAndEmail = /* @__PURE__ */ __name(async (ctx) => {
2580
- const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
2581
- try {
2582
- const body = await ctx.req.json();
2583
- if (body?.email && typeof body.email === "string") {
2584
- const normalizedEmail = body.email.trim().toLowerCase();
2585
- if (normalizedEmail)
2586
- return `${ip}:${hashKeyPart(normalizedEmail)}`;
2587
- }
2588
- } catch {
2589
- }
2590
- return ip;
2591
- }, "ipAndEmail");
2592
- var AuthController = class AuthController2 {
2593
- static {
2594
- __name(this, "AuthController");
2595
- }
2596
- authService;
2597
- constructor(authService) {
2598
- this.authService = authService;
2599
- }
2600
- async registerUser(body) {
2601
- return this.authService.registerUser(body);
2602
- }
2603
- async loginUser(body) {
2604
- return this.authService.loginUser(body);
2605
- }
2606
- async inviteUser(body) {
2607
- return this.authService.inviteUser(body);
2568
+ async inviteUser(body) {
2569
+ return this.authService.inviteUser(body);
2608
2570
  }
2609
2571
  async refreshTokens() {
2610
2572
  return this.authService.refreshTokens();
@@ -2626,96 +2588,96 @@ var AuthController = class AuthController2 {
2626
2588
  }
2627
2589
  };
2628
2590
  __decorate15([
2629
- Post2("/register"),
2591
+ Post("/register"),
2630
2592
  RateLimit({ limit: 5, window: "15m", key: ipAndEmail }),
2631
- Validate2(createUserDto),
2632
- ResMsg2("auth.success.register"),
2633
- __param6(0, Body2()),
2593
+ Validate(registerDto),
2594
+ ResMsg("auth.success.register"),
2595
+ __param5(0, Body()),
2634
2596
  __metadata15("design:type", Function),
2635
2597
  __metadata15("design:paramtypes", [Object]),
2636
2598
  __metadata15("design:returntype", Promise)
2637
2599
  ], AuthController.prototype, "registerUser", null);
2638
2600
  __decorate15([
2639
- Post2("/login"),
2601
+ Post("/login"),
2640
2602
  RateLimit({ limit: 5, window: "15m", key: ipAndEmail, message: "Too many login attempts. Please try again later." }),
2641
- Validate2(loginDto),
2642
- ResMsg2("auth.success.login"),
2643
- __param6(0, Body2()),
2603
+ Validate(loginDto),
2604
+ ResMsg("auth.success.login"),
2605
+ __param5(0, Body()),
2644
2606
  __metadata15("design:type", Function),
2645
2607
  __metadata15("design:paramtypes", [Object]),
2646
2608
  __metadata15("design:returntype", Promise)
2647
2609
  ], AuthController.prototype, "loginUser", null);
2648
2610
  __decorate15([
2649
- Post2("/invite"),
2611
+ Post("/invite"),
2650
2612
  isAdmin(),
2651
2613
  RateLimit({ limit: 20, window: "15m", key: "user" }),
2652
- Validate2(inviteUserDto),
2653
- ResMsg2("auth.success.accountInviteSent"),
2654
- __param6(0, Body2()),
2614
+ Validate(inviteUserDto),
2615
+ ResMsg("auth.success.accountInviteSent"),
2616
+ __param5(0, Body()),
2655
2617
  __metadata15("design:type", Function),
2656
2618
  __metadata15("design:paramtypes", [Object]),
2657
2619
  __metadata15("design:returntype", Promise)
2658
2620
  ], AuthController.prototype, "inviteUser", null);
2659
2621
  __decorate15([
2660
- Post2("/refresh"),
2622
+ Post("/refresh"),
2661
2623
  RateLimit({ limit: 15, window: "15m", key: cookieFingerprint() }),
2662
- ResMsg2("auth.success.tokenRefreshed"),
2624
+ ResMsg("auth.success.tokenRefreshed"),
2663
2625
  __metadata15("design:type", Function),
2664
2626
  __metadata15("design:paramtypes", []),
2665
2627
  __metadata15("design:returntype", Promise)
2666
2628
  ], AuthController.prototype, "refreshTokens", null);
2667
2629
  __decorate15([
2668
- Post2("/logout"),
2630
+ Post("/logout"),
2669
2631
  isAuth(),
2670
2632
  RateLimit({ limit: 10, window: "15m", key: "user" }),
2671
- __param6(0, User3("id")),
2672
- __param6(1, Headers("authorization")),
2633
+ __param5(0, User3("id")),
2634
+ __param5(1, Headers("authorization")),
2673
2635
  __metadata15("design:type", Function),
2674
2636
  __metadata15("design:paramtypes", [String, String]),
2675
2637
  __metadata15("design:returntype", Promise)
2676
2638
  ], AuthController.prototype, "logoutUser", null);
2677
2639
  __decorate15([
2678
- Post2("/change-password"),
2640
+ Post("/change-password"),
2679
2641
  isAuth(),
2680
- Validate2(changePasswordDto),
2681
- ResMsg2("auth.success.passwordChanged"),
2682
- __param6(0, User3("id")),
2683
- __param6(1, Body2()),
2642
+ Validate(changePasswordDto),
2643
+ ResMsg("auth.success.passwordChanged"),
2644
+ __param5(0, User3("id")),
2645
+ __param5(1, Body()),
2684
2646
  __metadata15("design:type", Function),
2685
2647
  __metadata15("design:paramtypes", [String, Object]),
2686
2648
  __metadata15("design:returntype", Promise)
2687
2649
  ], AuthController.prototype, "changePassword", null);
2688
2650
  __decorate15([
2689
- Get2("/me"),
2651
+ Get("/me"),
2690
2652
  RateLimit({ limit: 30, window: "1m", key: cookieFingerprint() }),
2691
- ResMsg2("auth.users.success.retrieved"),
2692
- __param6(0, Headers("authorization")),
2653
+ ResMsg("auth.users.success.retrieved"),
2654
+ __param5(0, Headers("authorization")),
2693
2655
  __metadata15("design:type", Function),
2694
2656
  __metadata15("design:paramtypes", [String]),
2695
2657
  __metadata15("design:returntype", Promise)
2696
2658
  ], AuthController.prototype, "userProfile", null);
2697
2659
  __decorate15([
2698
- Post2("/forgot-password"),
2660
+ Post("/forgot-password"),
2699
2661
  RateLimit({ limit: 3, window: "15m", key: ipAndEmail, message: "Too many password reset requests. Please try again later." }),
2700
- Validate2(resetPasswordDto),
2701
- ResMsg2("auth.success.passwordResetSent"),
2702
- __param6(0, Body2()),
2662
+ Validate(resetPasswordDto),
2663
+ ResMsg("auth.success.passwordResetSent"),
2664
+ __param5(0, Body()),
2703
2665
  __metadata15("design:type", Function),
2704
2666
  __metadata15("design:paramtypes", [Object]),
2705
2667
  __metadata15("design:returntype", Promise)
2706
2668
  ], AuthController.prototype, "forgotPassword", null);
2707
2669
  __decorate15([
2708
- Post2("/reset-password"),
2670
+ Post("/reset-password"),
2709
2671
  RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many password reset attempts. Please try again later." }),
2710
- Validate2(confirmResetPasswordDto),
2711
- ResMsg2("auth.success.passwordReset"),
2712
- __param6(0, Body2()),
2672
+ Validate(confirmResetPasswordDto),
2673
+ ResMsg("auth.success.passwordReset"),
2674
+ __param5(0, Body()),
2713
2675
  __metadata15("design:type", Function),
2714
2676
  __metadata15("design:paramtypes", [Object]),
2715
2677
  __metadata15("design:returntype", Promise)
2716
2678
  ], AuthController.prototype, "resetPassword", null);
2717
2679
  AuthController = __decorate15([
2718
- Controller2("/auth"),
2680
+ Controller("/auth"),
2719
2681
  __metadata15("design:paramtypes", [typeof (_a9 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a9 : Object])
2720
2682
  ], AuthController);
2721
2683
 
@@ -2778,6 +2740,10 @@ var AuthResolver = class AuthResolver2 {
2778
2740
  const session = cookieManager.getSessionCookie();
2779
2741
  if (!session)
2780
2742
  return false;
2743
+ const tokenService = await this.container.resolve(TokenService);
2744
+ const currentVersion = await tokenService.getSessionVersion(session.user.id);
2745
+ if ((session.sessionVersion ?? 0) !== currentVersion)
2746
+ return false;
2781
2747
  return {
2782
2748
  user: { ...session.user, permissions: session.permissions },
2783
2749
  role: session.user.role ?? session.roles[0],
@@ -2886,6 +2852,7 @@ __name(runAsUser, "runAsUser");
2886
2852
  // src/auth/index.ts
2887
2853
  var AUTH_MODULE = [
2888
2854
  AuthService,
2855
+ AuthSessionService,
2889
2856
  CookieManager,
2890
2857
  EncryptionService,
2891
2858
  AuthGuard,
@@ -2908,6 +2875,7 @@ __export(users_exports, {
2908
2875
  inviteUserDto: () => inviteUserDto,
2909
2876
  languageParam: () => languageParam,
2910
2877
  loginDto: () => loginDto,
2878
+ registerDto: () => registerDto,
2911
2879
  resetPasswordDto: () => resetPasswordDto,
2912
2880
  updateUserDto: () => updateUserDto,
2913
2881
  userIdInParam: () => userIdInParam,
@@ -2919,7 +2887,87 @@ __export(users_exports, {
2919
2887
  import { Controller as Controller3 } from "najm-core";
2920
2888
  import { Get as Get3, Post as Post3, Put as Put2, Delete as Delete2, ResMsg as ResMsg3 } from "najm-core";
2921
2889
  import { Params as Params2, Body as Body3, Query } from "najm-core";
2922
- import { Validate as Validate3 } from "najm-validation";
2890
+
2891
+ // src/roles/index.ts
2892
+ var roles_exports = {};
2893
+ __export(roles_exports, {
2894
+ ROLES: () => ROLES,
2895
+ ROLE_GROUPS: () => ROLE_GROUPS,
2896
+ Role: () => Role,
2897
+ RoleController: () => RoleController,
2898
+ RoleGuard: () => RoleGuard,
2899
+ RoleRepository: () => RoleRepository,
2900
+ RoleService: () => RoleService,
2901
+ RoleValidator: () => RoleValidator,
2902
+ assignRoleDto: () => assignRoleDto,
2903
+ createRoleDto: () => createRoleDto,
2904
+ defineRoles: () => defineRoles,
2905
+ isAdmin: () => isAdmin,
2906
+ isAdministrator: () => isAdministrator,
2907
+ roleIdParam: () => roleIdParam,
2908
+ updateRoleDto: () => updateRoleDto
2909
+ });
2910
+
2911
+ // src/roles/defineRoles.ts
2912
+ import { composeGuards as composeGuards2, createGuard as createGuard3 } from "najm-guard";
2913
+ var Role2 = createGuard3(RoleGuard);
2914
+ function defineRoles(roles, options) {
2915
+ const ROLES2 = roles;
2916
+ const superRoleKeys = options?.superRoles ?? [];
2917
+ function resolveRoleValues(keys) {
2918
+ return Array.from(new Set([...keys, ...superRoleKeys].map((key) => roles[key])));
2919
+ }
2920
+ __name(resolveRoleValues, "resolveRoleValues");
2921
+ const guards2 = {};
2922
+ for (const [key, value] of Object.entries(roles)) {
2923
+ const name = `is${key.charAt(0).toUpperCase()}${key.slice(1).toLowerCase()}`;
2924
+ const allowedValues = resolveRoleValues([key]);
2925
+ guards2[name] = composeGuards2(isAuth(), Role2(allowedValues.length === 1 ? value : allowedValues));
2926
+ }
2927
+ function createGroupGuard(keys) {
2928
+ const values = resolveRoleValues(keys);
2929
+ return composeGuards2(isAuth(), Role2(values));
2930
+ }
2931
+ __name(createGroupGuard, "createGroupGuard");
2932
+ function hasRole(userRole, ...keys) {
2933
+ if (!userRole)
2934
+ return false;
2935
+ const normalized = userRole.toLowerCase();
2936
+ return resolveRoleValues(keys).some((role) => role === normalized);
2937
+ }
2938
+ __name(hasRole, "hasRole");
2939
+ function isInGroup(userRole, keys) {
2940
+ return hasRole(userRole, ...keys);
2941
+ }
2942
+ __name(isInGroup, "isInGroup");
2943
+ return { ROLES: ROLES2, createGroupGuard, hasRole, isInGroup, ...guards2 };
2944
+ }
2945
+ __name(defineRoles, "defineRoles");
2946
+
2947
+ // src/roles/RoleController.ts
2948
+ import { Controller as Controller2 } from "najm-core";
2949
+ import { Get as Get2, Post as Post2, Put, Delete, ResMsg as ResMsg2 } from "najm-core";
2950
+ import { Params, Body as Body2 } from "najm-core";
2951
+ import { Validate as Validate2 } from "najm-validation";
2952
+
2953
+ // src/roles/RoleDto.ts
2954
+ import { z as z2 } from "zod";
2955
+ var nameField = z2.string().min(2, "Name must be at least 2 characters").max(50, "Name too long");
2956
+ var descriptionField = z2.string().max(255, "Description too long").optional();
2957
+ var createRoleDto = z2.object({
2958
+ name: nameField,
2959
+ description: descriptionField
2960
+ });
2961
+ var updateRoleDto = createRoleDto.partial();
2962
+ var roleIdParam = z2.object({
2963
+ id: z2.string().length(5, "Role ID must be 5 characters")
2964
+ });
2965
+ var assignRoleDto = z2.object({
2966
+ userId: z2.string().length(8, "User ID must be 8 characters"),
2967
+ roleId: z2.string().length(5, "Role ID must be 5 characters")
2968
+ });
2969
+
2970
+ // src/roles/RoleController.ts
2923
2971
  var __decorate17 = function(decorators, target, key, desc) {
2924
2972
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2925
2973
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -2929,12 +2977,110 @@ var __decorate17 = function(decorators, target, key, desc) {
2929
2977
  var __metadata17 = function(k, v) {
2930
2978
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2931
2979
  };
2932
- var __param7 = function(paramIndex, decorator) {
2980
+ var __param6 = function(paramIndex, decorator) {
2933
2981
  return function(target, key) {
2934
2982
  decorator(target, key, paramIndex);
2935
2983
  };
2936
2984
  };
2937
2985
  var _a11;
2986
+ var RoleController = class RoleController2 {
2987
+ static {
2988
+ __name(this, "RoleController");
2989
+ }
2990
+ roleService;
2991
+ constructor(roleService) {
2992
+ this.roleService = roleService;
2993
+ }
2994
+ async getRoles() {
2995
+ return this.roleService.getAll();
2996
+ }
2997
+ async getRole(params) {
2998
+ return this.roleService.getById(params.id);
2999
+ }
3000
+ async createRole(body) {
3001
+ return this.roleService.create(body);
3002
+ }
3003
+ async updateRole(params, body) {
3004
+ return this.roleService.update(params.id, body);
3005
+ }
3006
+ async deleteRole(params) {
3007
+ return this.roleService.delete(params.id);
3008
+ }
3009
+ };
3010
+ __decorate17([
3011
+ Get2(),
3012
+ isAdmin(),
3013
+ ResMsg2("roles.success.retrieved"),
3014
+ __metadata17("design:type", Function),
3015
+ __metadata17("design:paramtypes", []),
3016
+ __metadata17("design:returntype", Promise)
3017
+ ], RoleController.prototype, "getRoles", null);
3018
+ __decorate17([
3019
+ Get2("/:id"),
3020
+ isAdmin(),
3021
+ Validate2({ params: roleIdParam }),
3022
+ ResMsg2("roles.success.retrieved"),
3023
+ __param6(0, Params()),
3024
+ __metadata17("design:type", Function),
3025
+ __metadata17("design:paramtypes", [Object]),
3026
+ __metadata17("design:returntype", Promise)
3027
+ ], RoleController.prototype, "getRole", null);
3028
+ __decorate17([
3029
+ Post2(),
3030
+ isAdmin(),
3031
+ Validate2(createRoleDto),
3032
+ ResMsg2("roles.success.created"),
3033
+ __param6(0, Body2()),
3034
+ __metadata17("design:type", Function),
3035
+ __metadata17("design:paramtypes", [Object]),
3036
+ __metadata17("design:returntype", Promise)
3037
+ ], RoleController.prototype, "createRole", null);
3038
+ __decorate17([
3039
+ Put("/:id"),
3040
+ isAdmin(),
3041
+ Validate2({
3042
+ params: roleIdParam,
3043
+ body: updateRoleDto
3044
+ }),
3045
+ ResMsg2("roles.success.updated"),
3046
+ __param6(0, Params()),
3047
+ __param6(1, Body2()),
3048
+ __metadata17("design:type", Function),
3049
+ __metadata17("design:paramtypes", [Object, Object]),
3050
+ __metadata17("design:returntype", Promise)
3051
+ ], RoleController.prototype, "updateRole", null);
3052
+ __decorate17([
3053
+ Delete("/:id"),
3054
+ isAdmin(),
3055
+ Validate2({ params: roleIdParam }),
3056
+ ResMsg2("roles.success.deleted"),
3057
+ __param6(0, Params()),
3058
+ __metadata17("design:type", Function),
3059
+ __metadata17("design:paramtypes", [Object]),
3060
+ __metadata17("design:returntype", Promise)
3061
+ ], RoleController.prototype, "deleteRole", null);
3062
+ RoleController = __decorate17([
3063
+ Controller2("/roles"),
3064
+ __metadata17("design:paramtypes", [typeof (_a11 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a11 : Object])
3065
+ ], RoleController);
3066
+
3067
+ // src/users/UserController.ts
3068
+ import { Validate as Validate3 } from "najm-validation";
3069
+ var __decorate18 = function(decorators, target, key, desc) {
3070
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3071
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3072
+ 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;
3073
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3074
+ };
3075
+ var __metadata18 = function(k, v) {
3076
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3077
+ };
3078
+ var __param7 = function(paramIndex, decorator) {
3079
+ return function(target, key) {
3080
+ decorator(target, key, paramIndex);
3081
+ };
3082
+ };
3083
+ var _a12;
2938
3084
  var UserController = class UserController2 {
2939
3085
  static {
2940
3086
  __name(this, "UserController");
@@ -2981,75 +3127,75 @@ var UserController = class UserController2 {
2981
3127
  return this.userService.removeRole(params.userId);
2982
3128
  }
2983
3129
  };
2984
- __decorate17([
3130
+ __decorate18([
2985
3131
  Get3(),
2986
3132
  isAdmin(),
2987
3133
  Validate3({ query: userListQuery }),
2988
3134
  ResMsg3("users.success.retrieved"),
2989
3135
  __param7(0, Query()),
2990
- __metadata17("design:type", Function),
2991
- __metadata17("design:paramtypes", [Object]),
2992
- __metadata17("design:returntype", Promise)
3136
+ __metadata18("design:type", Function),
3137
+ __metadata18("design:paramtypes", [Object]),
3138
+ __metadata18("design:returntype", Promise)
2993
3139
  ], UserController.prototype, "getUsers", null);
2994
- __decorate17([
3140
+ __decorate18([
2995
3141
  Get3("/lang"),
2996
3142
  isAuth(),
2997
3143
  ResMsg3("users.success.retrieved"),
2998
- __metadata17("design:type", Function),
2999
- __metadata17("design:paramtypes", []),
3000
- __metadata17("design:returntype", Promise)
3144
+ __metadata18("design:type", Function),
3145
+ __metadata18("design:paramtypes", []),
3146
+ __metadata18("design:returntype", Promise)
3001
3147
  ], UserController.prototype, "getLang", null);
3002
- __decorate17([
3148
+ __decorate18([
3003
3149
  Post3("/lang/:language"),
3004
3150
  isAuth(),
3005
3151
  Validate3({ params: languageParam }),
3006
3152
  ResMsg3("users.success.updated"),
3007
3153
  __param7(0, Params2()),
3008
- __metadata17("design:type", Function),
3009
- __metadata17("design:paramtypes", [Object]),
3010
- __metadata17("design:returntype", Promise)
3154
+ __metadata18("design:type", Function),
3155
+ __metadata18("design:paramtypes", [Object]),
3156
+ __metadata18("design:returntype", Promise)
3011
3157
  ], UserController.prototype, "updateLang", null);
3012
- __decorate17([
3158
+ __decorate18([
3013
3159
  Get3("/:id"),
3014
3160
  isAdmin(),
3015
3161
  Validate3({ params: userIdParam }),
3016
3162
  ResMsg3("users.success.retrieved"),
3017
3163
  __param7(0, Params2()),
3018
- __metadata17("design:type", Function),
3019
- __metadata17("design:paramtypes", [Object]),
3020
- __metadata17("design:returntype", Promise)
3164
+ __metadata18("design:type", Function),
3165
+ __metadata18("design:paramtypes", [Object]),
3166
+ __metadata18("design:returntype", Promise)
3021
3167
  ], UserController.prototype, "getUser", null);
3022
- __decorate17([
3168
+ __decorate18([
3023
3169
  Get3("/email/:email"),
3024
3170
  isAdmin(),
3025
3171
  Validate3({ params: emailParam }),
3026
3172
  ResMsg3("users.success.retrieved"),
3027
3173
  __param7(0, Params2()),
3028
- __metadata17("design:type", Function),
3029
- __metadata17("design:paramtypes", [Object]),
3030
- __metadata17("design:returntype", Promise)
3174
+ __metadata18("design:type", Function),
3175
+ __metadata18("design:paramtypes", [Object]),
3176
+ __metadata18("design:returntype", Promise)
3031
3177
  ], UserController.prototype, "getByEmail", null);
3032
- __decorate17([
3178
+ __decorate18([
3033
3179
  Get3("/role/:userId"),
3034
3180
  isAdmin(),
3035
3181
  Validate3({ params: userIdInParam }),
3036
3182
  ResMsg3("users.success.retrieved"),
3037
3183
  __param7(0, Params2()),
3038
- __metadata17("design:type", Function),
3039
- __metadata17("design:paramtypes", [Object]),
3040
- __metadata17("design:returntype", Promise)
3184
+ __metadata18("design:type", Function),
3185
+ __metadata18("design:paramtypes", [Object]),
3186
+ __metadata18("design:returntype", Promise)
3041
3187
  ], UserController.prototype, "getRole", null);
3042
- __decorate17([
3188
+ __decorate18([
3043
3189
  Post3(),
3044
3190
  isAdmin(),
3045
3191
  Validate3(createUserDto),
3046
3192
  ResMsg3("users.success.created"),
3047
3193
  __param7(0, Body3()),
3048
- __metadata17("design:type", Function),
3049
- __metadata17("design:paramtypes", [Object]),
3050
- __metadata17("design:returntype", Promise)
3194
+ __metadata18("design:type", Function),
3195
+ __metadata18("design:paramtypes", [Object]),
3196
+ __metadata18("design:returntype", Promise)
3051
3197
  ], UserController.prototype, "create", null);
3052
- __decorate17([
3198
+ __decorate18([
3053
3199
  Put2("/:id"),
3054
3200
  isAdmin(),
3055
3201
  Validate3({
@@ -3059,51 +3205,51 @@ __decorate17([
3059
3205
  ResMsg3("users.success.updated"),
3060
3206
  __param7(0, Params2()),
3061
3207
  __param7(1, Body3()),
3062
- __metadata17("design:type", Function),
3063
- __metadata17("design:paramtypes", [Object, Object]),
3064
- __metadata17("design:returntype", Promise)
3208
+ __metadata18("design:type", Function),
3209
+ __metadata18("design:paramtypes", [Object, Object]),
3210
+ __metadata18("design:returntype", Promise)
3065
3211
  ], UserController.prototype, "update", null);
3066
- __decorate17([
3212
+ __decorate18([
3067
3213
  Delete2("/:id"),
3068
3214
  isAdmin(),
3069
3215
  Validate3({ params: userIdParam }),
3070
3216
  ResMsg3("users.success.deleted"),
3071
3217
  __param7(0, Params2()),
3072
- __metadata17("design:type", Function),
3073
- __metadata17("design:paramtypes", [Object]),
3074
- __metadata17("design:returntype", Promise)
3218
+ __metadata18("design:type", Function),
3219
+ __metadata18("design:paramtypes", [Object]),
3220
+ __metadata18("design:returntype", Promise)
3075
3221
  ], UserController.prototype, "delete", null);
3076
- __decorate17([
3222
+ __decorate18([
3077
3223
  Delete2(),
3078
3224
  isAdmin(),
3079
3225
  ResMsg3("users.success.allDeleted"),
3080
- __metadata17("design:type", Function),
3081
- __metadata17("design:paramtypes", []),
3082
- __metadata17("design:returntype", Promise)
3226
+ __metadata18("design:type", Function),
3227
+ __metadata18("design:paramtypes", []),
3228
+ __metadata18("design:returntype", Promise)
3083
3229
  ], UserController.prototype, "deleteAll", null);
3084
- __decorate17([
3230
+ __decorate18([
3085
3231
  Post3("/assign/:userId/:roleId"),
3086
3232
  isAdmin(),
3087
3233
  Validate3({ params: assignRoleParams }),
3088
3234
  ResMsg3("users.success.updated"),
3089
3235
  __param7(0, Params2()),
3090
- __metadata17("design:type", Function),
3091
- __metadata17("design:paramtypes", [Object]),
3092
- __metadata17("design:returntype", Promise)
3236
+ __metadata18("design:type", Function),
3237
+ __metadata18("design:paramtypes", [Object]),
3238
+ __metadata18("design:returntype", Promise)
3093
3239
  ], UserController.prototype, "assignRole", null);
3094
- __decorate17([
3240
+ __decorate18([
3095
3241
  Delete2("/remove/:userId"),
3096
3242
  isAdmin(),
3097
3243
  Validate3({ params: userIdInParam }),
3098
3244
  ResMsg3("users.success.updated"),
3099
3245
  __param7(0, Params2()),
3100
- __metadata17("design:type", Function),
3101
- __metadata17("design:paramtypes", [Object]),
3102
- __metadata17("design:returntype", Promise)
3246
+ __metadata18("design:type", Function),
3247
+ __metadata18("design:paramtypes", [Object]),
3248
+ __metadata18("design:returntype", Promise)
3103
3249
  ], UserController.prototype, "removeRole", null);
3104
- UserController = __decorate17([
3250
+ UserController = __decorate18([
3105
3251
  Controller3("/users"),
3106
- __metadata17("design:paramtypes", [typeof (_a11 = typeof UserService !== "undefined" && UserService) === "function" ? _a11 : Object])
3252
+ __metadata18("design:paramtypes", [typeof (_a12 = typeof UserService !== "undefined" && UserService) === "function" ? _a12 : Object])
3107
3253
  ], UserController);
3108
3254
 
3109
3255
  // src/permissions/index.ts
@@ -3126,13 +3272,13 @@ __export(permissions_exports, {
3126
3272
  import { eq as eq5, and as and2 } from "drizzle-orm";
3127
3273
  import { Repository as Repository4, Inject as Inject10 } from "najm-core";
3128
3274
  import { DB as DB4 } from "najm-database";
3129
- var __decorate18 = function(decorators, target, key, desc) {
3275
+ var __decorate19 = function(decorators, target, key, desc) {
3130
3276
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3131
3277
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3132
3278
  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;
3133
3279
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3134
3280
  };
3135
- var __metadata18 = function(k, v) {
3281
+ var __metadata19 = function(k, v) {
3136
3282
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3137
3283
  };
3138
3284
  var PermissionRepository = class PermissionRepository2 {
@@ -3210,29 +3356,29 @@ var PermissionRepository = class PermissionRepository2 {
3210
3356
  return deletedPermissions;
3211
3357
  }
3212
3358
  };
3213
- __decorate18([
3359
+ __decorate19([
3214
3360
  DB4(),
3215
- __metadata18("design:type", Object)
3361
+ __metadata19("design:type", Object)
3216
3362
  ], PermissionRepository.prototype, "db", void 0);
3217
- __decorate18([
3363
+ __decorate19([
3218
3364
  Inject10(AUTH_SCHEMA),
3219
- __metadata18("design:type", Object)
3365
+ __metadata19("design:type", Object)
3220
3366
  ], PermissionRepository.prototype, "schema", void 0);
3221
- PermissionRepository = __decorate18([
3367
+ PermissionRepository = __decorate19([
3222
3368
  Repository4()
3223
3369
  ], PermissionRepository);
3224
3370
 
3225
3371
  // src/permissions/PermissionGuards.ts
3226
- import { Injectable as Injectable8 } from "najm-core";
3372
+ import { Injectable as Injectable9 } from "najm-core";
3227
3373
  import { GuardParams as GuardParams2, User as User4 } from "najm-core";
3228
3374
  import { createGuard as createGuard4, composeGuards as composeGuards3 } from "najm-guard";
3229
- var __decorate19 = function(decorators, target, key, desc) {
3375
+ var __decorate20 = function(decorators, target, key, desc) {
3230
3376
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3231
3377
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3232
3378
  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;
3233
3379
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3234
3380
  };
3235
- var __metadata19 = function(k, v) {
3381
+ var __metadata20 = function(k, v) {
3236
3382
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3237
3383
  };
3238
3384
  var __param8 = function(paramIndex, decorator) {
@@ -3268,15 +3414,15 @@ var PermissionGuard = class PermissionGuard2 {
3268
3414
  return false;
3269
3415
  }
3270
3416
  };
3271
- __decorate19([
3417
+ __decorate20([
3272
3418
  __param8(0, GuardParams2()),
3273
3419
  __param8(1, User4("permissions")),
3274
- __metadata19("design:type", Function),
3275
- __metadata19("design:paramtypes", [String, Array]),
3276
- __metadata19("design:returntype", Object)
3420
+ __metadata20("design:type", Function),
3421
+ __metadata20("design:paramtypes", [String, Array]),
3422
+ __metadata20("design:returntype", Object)
3277
3423
  ], PermissionGuard.prototype, "canActivate", null);
3278
- PermissionGuard = __decorate19([
3279
- Injectable8()
3424
+ PermissionGuard = __decorate20([
3425
+ Injectable9()
3280
3426
  ], PermissionGuard);
3281
3427
  var Permission = createGuard4(PermissionGuard);
3282
3428
  var Can = /* @__PURE__ */ __name((permission) => composeGuards3(isAuth(), Permission(permission))(), "Can");
@@ -3287,23 +3433,23 @@ import { Get as Get4, Post as Post4, Put as Put3, Delete as Delete3, ResMsg as R
3287
3433
  import { Params as Params3, Body as Body4 } from "najm-core";
3288
3434
 
3289
3435
  // src/permissions/PermissionService.ts
3290
- import { Injectable as Injectable10 } from "najm-core";
3436
+ import { Injectable as Injectable11 } from "najm-core";
3291
3437
 
3292
3438
  // src/permissions/PermissionValidator.ts
3293
- import { Injectable as Injectable9 } from "najm-core";
3294
- import { I18n as I18n6 } from "najm-i18n";
3295
- import { Err as Err7 } from "najm-core";
3296
- var __decorate20 = function(decorators, target, key, desc) {
3439
+ import { Injectable as Injectable10 } from "najm-core";
3440
+ import { I18n as I18n7 } from "najm-i18n";
3441
+ import { Err as Err9 } from "najm-core";
3442
+ var __decorate21 = function(decorators, target, key, desc) {
3297
3443
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3298
3444
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3299
3445
  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;
3300
3446
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3301
3447
  };
3302
- var __metadata20 = function(k, v) {
3448
+ var __metadata21 = function(k, v) {
3303
3449
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3304
3450
  };
3305
- var _a12;
3306
- var _b6;
3451
+ var _a13;
3452
+ var _b7;
3307
3453
  var PermissionValidator = class PermissionValidator2 {
3308
3454
  static {
3309
3455
  __name(this, "PermissionValidator");
@@ -3321,7 +3467,7 @@ var PermissionValidator = class PermissionValidator2 {
3321
3467
  async checkPermissionExists(id) {
3322
3468
  const permission = await this.permissionRepository.getById(id);
3323
3469
  if (!permission) {
3324
- Err7(this.t("errors.notFound"), 404);
3470
+ Err9(this.t("errors.notFound"), 404);
3325
3471
  }
3326
3472
  return permission;
3327
3473
  }
@@ -3331,7 +3477,7 @@ var PermissionValidator = class PermissionValidator2 {
3331
3477
  async checkPermissionExistsByName(name) {
3332
3478
  const permission = await this.permissionRepository.getByName(name);
3333
3479
  if (!permission) {
3334
- Err7(this.t("errors.notFound"), 404);
3480
+ Err9(this.t("errors.notFound"), 404);
3335
3481
  }
3336
3482
  return permission;
3337
3483
  }
@@ -3343,7 +3489,7 @@ var PermissionValidator = class PermissionValidator2 {
3343
3489
  return;
3344
3490
  const existingPermission = await this.permissionRepository.getByName(name);
3345
3491
  if (existingPermission && existingPermission.id !== excludeId) {
3346
- Err7(this.t("errors.nameExists"), 409);
3492
+ Err9(this.t("errors.nameExists"), 409);
3347
3493
  }
3348
3494
  }
3349
3495
  /**
@@ -3366,32 +3512,32 @@ var PermissionValidator = class PermissionValidator2 {
3366
3512
  await this.checkPermissionExists(permissionId);
3367
3513
  const hasPermission = await this.permissionRepository.checkRoleHasPermission(roleId, permissionId);
3368
3514
  if (hasPermission) {
3369
- Err7(this.t("errors.roleAlreadyHasPermission"), 409);
3515
+ Err9(this.t("errors.roleAlreadyHasPermission"), 409);
3370
3516
  }
3371
3517
  }
3372
3518
  };
3373
- __decorate20([
3374
- I18n6("permissions"),
3375
- __metadata20("design:type", Object)
3519
+ __decorate21([
3520
+ I18n7("permissions"),
3521
+ __metadata21("design:type", Object)
3376
3522
  ], PermissionValidator.prototype, "t", void 0);
3377
- PermissionValidator = __decorate20([
3378
- Injectable9(),
3379
- __metadata20("design:paramtypes", [typeof (_a12 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a12 : Object, typeof (_b6 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b6 : Object])
3523
+ PermissionValidator = __decorate21([
3524
+ Injectable10(),
3525
+ __metadata21("design:paramtypes", [typeof (_a13 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a13 : Object, typeof (_b7 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b7 : Object])
3380
3526
  ], PermissionValidator);
3381
3527
 
3382
3528
  // src/permissions/PermissionService.ts
3383
- var __decorate21 = function(decorators, target, key, desc) {
3529
+ var __decorate22 = function(decorators, target, key, desc) {
3384
3530
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3385
3531
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3386
3532
  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;
3387
3533
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3388
3534
  };
3389
- var __metadata21 = function(k, v) {
3535
+ var __metadata22 = function(k, v) {
3390
3536
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3391
3537
  };
3392
- var _a13;
3393
- var _b7;
3394
- var _c4;
3538
+ var _a14;
3539
+ var _b8;
3540
+ var _c5;
3395
3541
  var PermissionService = class PermissionService2 {
3396
3542
  static {
3397
3543
  __name(this, "PermissionService");
@@ -3496,9 +3642,9 @@ var PermissionService = class PermissionService2 {
3496
3642
  return await this.permissionRepository.deleteAll();
3497
3643
  }
3498
3644
  };
3499
- PermissionService = __decorate21([
3500
- Injectable10(),
3501
- __metadata21("design:paramtypes", [typeof (_a13 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a13 : Object, typeof (_b7 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b7 : Object, typeof (_c4 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c4 : Object])
3645
+ PermissionService = __decorate22([
3646
+ Injectable11(),
3647
+ __metadata22("design:paramtypes", [typeof (_a14 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a14 : Object, typeof (_b8 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b8 : Object, typeof (_c5 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c5 : Object])
3502
3648
  ], PermissionService);
3503
3649
 
3504
3650
  // src/permissions/PermissionController.ts
@@ -3531,13 +3677,13 @@ var checkPermissionDto = z3.object({
3531
3677
  });
3532
3678
 
3533
3679
  // src/permissions/PermissionController.ts
3534
- var __decorate22 = function(decorators, target, key, desc) {
3680
+ var __decorate23 = function(decorators, target, key, desc) {
3535
3681
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3536
3682
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3537
3683
  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;
3538
3684
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3539
3685
  };
3540
- var __metadata22 = function(k, v) {
3686
+ var __metadata23 = function(k, v) {
3541
3687
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3542
3688
  };
3543
3689
  var __param9 = function(paramIndex, decorator) {
@@ -3545,7 +3691,7 @@ var __param9 = function(paramIndex, decorator) {
3545
3691
  decorator(target, key, paramIndex);
3546
3692
  };
3547
3693
  };
3548
- var _a14;
3694
+ var _a15;
3549
3695
  var PermissionController = class PermissionController2 {
3550
3696
  static {
3551
3697
  __name(this, "PermissionController");
@@ -3591,32 +3737,32 @@ var PermissionController = class PermissionController2 {
3591
3737
  return this.permissionService.deleteAll();
3592
3738
  }
3593
3739
  };
3594
- __decorate22([
3740
+ __decorate23([
3595
3741
  Get4(),
3596
3742
  ResMsg4("permissions.success.retrieved"),
3597
- __metadata22("design:type", Function),
3598
- __metadata22("design:paramtypes", []),
3599
- __metadata22("design:returntype", Promise)
3743
+ __metadata23("design:type", Function),
3744
+ __metadata23("design:paramtypes", []),
3745
+ __metadata23("design:returntype", Promise)
3600
3746
  ], PermissionController.prototype, "getPermissions", null);
3601
- __decorate22([
3747
+ __decorate23([
3602
3748
  Get4("/:id"),
3603
3749
  Validate4({ params: permissionIdParam }),
3604
3750
  ResMsg4("permissions.success.retrieved"),
3605
3751
  __param9(0, Params3()),
3606
- __metadata22("design:type", Function),
3607
- __metadata22("design:paramtypes", [Object]),
3608
- __metadata22("design:returntype", Promise)
3752
+ __metadata23("design:type", Function),
3753
+ __metadata23("design:paramtypes", [Object]),
3754
+ __metadata23("design:returntype", Promise)
3609
3755
  ], PermissionController.prototype, "getPermission", null);
3610
- __decorate22([
3756
+ __decorate23([
3611
3757
  Post4(),
3612
3758
  Validate4(createPermissionDto),
3613
3759
  ResMsg4({ message: "Permission created successfully", status: 201 }),
3614
3760
  __param9(0, Body4()),
3615
- __metadata22("design:type", Function),
3616
- __metadata22("design:paramtypes", [Object]),
3617
- __metadata22("design:returntype", Promise)
3761
+ __metadata23("design:type", Function),
3762
+ __metadata23("design:paramtypes", [Object]),
3763
+ __metadata23("design:returntype", Promise)
3618
3764
  ], PermissionController.prototype, "create", null);
3619
- __decorate22([
3765
+ __decorate23([
3620
3766
  Put3("/:id"),
3621
3767
  Validate4({
3622
3768
  params: permissionIdParam,
@@ -3625,67 +3771,67 @@ __decorate22([
3625
3771
  ResMsg4("permissions.success.updated"),
3626
3772
  __param9(0, Params3()),
3627
3773
  __param9(1, Body4()),
3628
- __metadata22("design:type", Function),
3629
- __metadata22("design:paramtypes", [Object, Object]),
3630
- __metadata22("design:returntype", Promise)
3774
+ __metadata23("design:type", Function),
3775
+ __metadata23("design:paramtypes", [Object, Object]),
3776
+ __metadata23("design:returntype", Promise)
3631
3777
  ], PermissionController.prototype, "update", null);
3632
- __decorate22([
3778
+ __decorate23([
3633
3779
  Delete3("/:id"),
3634
3780
  Validate4({ params: permissionIdParam }),
3635
3781
  ResMsg4("permissions.success.deleted"),
3636
3782
  __param9(0, Params3()),
3637
- __metadata22("design:type", Function),
3638
- __metadata22("design:paramtypes", [Object]),
3639
- __metadata22("design:returntype", Promise)
3783
+ __metadata23("design:type", Function),
3784
+ __metadata23("design:paramtypes", [Object]),
3785
+ __metadata23("design:returntype", Promise)
3640
3786
  ], PermissionController.prototype, "delete", null);
3641
- __decorate22([
3787
+ __decorate23([
3642
3788
  Get4("/role/:id"),
3643
3789
  Validate4({ params: roleIdParam }),
3644
3790
  ResMsg4("permissions.success.retrieved"),
3645
3791
  __param9(0, Params3()),
3646
- __metadata22("design:type", Function),
3647
- __metadata22("design:paramtypes", [Object]),
3648
- __metadata22("design:returntype", Promise)
3792
+ __metadata23("design:type", Function),
3793
+ __metadata23("design:paramtypes", [Object]),
3794
+ __metadata23("design:returntype", Promise)
3649
3795
  ], PermissionController.prototype, "getByRole", null);
3650
- __decorate22([
3796
+ __decorate23([
3651
3797
  Get4("/roles/:id"),
3652
3798
  Validate4({ params: permissionIdParam }),
3653
3799
  ResMsg4("permissions.success.retrieved"),
3654
3800
  __param9(0, Params3()),
3655
- __metadata22("design:type", Function),
3656
- __metadata22("design:paramtypes", [Object]),
3657
- __metadata22("design:returntype", Promise)
3801
+ __metadata23("design:type", Function),
3802
+ __metadata23("design:paramtypes", [Object]),
3803
+ __metadata23("design:returntype", Promise)
3658
3804
  ], PermissionController.prototype, "getRolesByPermission", null);
3659
- __decorate22([
3805
+ __decorate23([
3660
3806
  Post4("/assign/:roleId/:permissionId"),
3661
3807
  Validate4({ params: assignPermissionDto }),
3662
3808
  ResMsg4("permissions.success.assigned"),
3663
3809
  __param9(0, Params3()),
3664
- __metadata22("design:type", Function),
3665
- __metadata22("design:paramtypes", [Object]),
3666
- __metadata22("design:returntype", Promise)
3810
+ __metadata23("design:type", Function),
3811
+ __metadata23("design:paramtypes", [Object]),
3812
+ __metadata23("design:returntype", Promise)
3667
3813
  ], PermissionController.prototype, "assignToRole", null);
3668
- __decorate22([
3814
+ __decorate23([
3669
3815
  Delete3("/remove/:roleId/:permissionId"),
3670
3816
  Validate4({ params: assignPermissionDto }),
3671
3817
  ResMsg4("permissions.success.removed"),
3672
3818
  __param9(0, Params3()),
3673
- __metadata22("design:type", Function),
3674
- __metadata22("design:paramtypes", [Object]),
3675
- __metadata22("design:returntype", Promise)
3819
+ __metadata23("design:type", Function),
3820
+ __metadata23("design:paramtypes", [Object]),
3821
+ __metadata23("design:returntype", Promise)
3676
3822
  ], PermissionController.prototype, "removeFromRole", null);
3677
- __decorate22([
3823
+ __decorate23([
3678
3824
  Delete3(),
3679
3825
  isAdmin(),
3680
3826
  ResMsg4("permissions.success.allDeleted"),
3681
- __metadata22("design:type", Function),
3682
- __metadata22("design:paramtypes", []),
3683
- __metadata22("design:returntype", Promise)
3827
+ __metadata23("design:type", Function),
3828
+ __metadata23("design:paramtypes", []),
3829
+ __metadata23("design:returntype", Promise)
3684
3830
  ], PermissionController.prototype, "deleteAll", null);
3685
- PermissionController = __decorate22([
3831
+ PermissionController = __decorate23([
3686
3832
  Controller4("/permissions"),
3687
3833
  isAdmin(),
3688
- __metadata22("design:paramtypes", [typeof (_a14 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a14 : Object])
3834
+ __metadata23("design:paramtypes", [typeof (_a15 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a15 : Object])
3689
3835
  ], PermissionController);
3690
3836
 
3691
3837
  // src/tokens/index.ts
@@ -3892,15 +4038,15 @@ function own(table, opts) {
3892
4038
  __name(own, "own");
3893
4039
 
3894
4040
  // src/ownership/configureOwnership.ts
3895
- import { Injectable as Injectable11, Inject as Inject11, User as User5, Body as Body5, Params as Params4 } from "najm-core";
4041
+ import { Injectable as Injectable12, Inject as Inject11, User as User5, Body as Body5, Params as Params4 } from "najm-core";
3896
4042
  import { createGuard as createGuard5, composeGuards as composeGuards4 } from "najm-guard";
3897
- var __decorate23 = function(decorators, target, key, desc) {
4043
+ var __decorate24 = function(decorators, target, key, desc) {
3898
4044
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3899
4045
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3900
4046
  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;
3901
4047
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3902
4048
  };
3903
- var __metadata23 = function(k, v) {
4049
+ var __metadata24 = function(k, v) {
3904
4050
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3905
4051
  };
3906
4052
  var __param10 = function(paramIndex, decorator) {
@@ -3920,7 +4066,7 @@ function toSingular(plural) {
3920
4066
  }
3921
4067
  __name(toSingular, "toSingular");
3922
4068
  function createResourceGuards(ownershipClass, resourceType, resource, options) {
3923
- var _a16, _b8;
4069
+ var _a22, _b12;
3924
4070
  const writeGuard = options?.adminGuard ?? isAdmin;
3925
4071
  let AccessGuard = class AccessGuard {
3926
4072
  static {
@@ -3932,19 +4078,19 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
3932
4078
  return allowed ? { owner: user } : false;
3933
4079
  }
3934
4080
  };
3935
- __decorate23([
4081
+ __decorate24([
3936
4082
  Inject11(ownershipClass),
3937
- __metadata23("design:type", Object)
4083
+ __metadata24("design:type", Object)
3938
4084
  ], AccessGuard.prototype, "ownership", void 0);
3939
- __decorate23([
4085
+ __decorate24([
3940
4086
  __param10(0, User5()),
3941
4087
  __param10(1, Params4("id")),
3942
- __metadata23("design:type", Function),
3943
- __metadata23("design:paramtypes", [Object, String]),
3944
- __metadata23("design:returntype", typeof (_a16 = typeof Promise !== "undefined" && Promise) === "function" ? _a16 : Object)
4088
+ __metadata24("design:type", Function),
4089
+ __metadata24("design:paramtypes", [Object, String]),
4090
+ __metadata24("design:returntype", typeof (_a22 = typeof Promise !== "undefined" && Promise) === "function" ? _a22 : Object)
3945
4091
  ], AccessGuard.prototype, "canActivate", null);
3946
- AccessGuard = __decorate23([
3947
- Injectable11()
4092
+ AccessGuard = __decorate24([
4093
+ Injectable12()
3948
4094
  ], AccessGuard);
3949
4095
  let ListGuard = class ListGuard {
3950
4096
  static {
@@ -3956,18 +4102,18 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
3956
4102
  return { filter: ids };
3957
4103
  }
3958
4104
  };
3959
- __decorate23([
4105
+ __decorate24([
3960
4106
  Inject11(ownershipClass),
3961
- __metadata23("design:type", Object)
4107
+ __metadata24("design:type", Object)
3962
4108
  ], ListGuard.prototype, "ownership", void 0);
3963
- __decorate23([
4109
+ __decorate24([
3964
4110
  __param10(0, User5()),
3965
- __metadata23("design:type", Function),
3966
- __metadata23("design:paramtypes", [Object]),
3967
- __metadata23("design:returntype", typeof (_b8 = typeof Promise !== "undefined" && Promise) === "function" ? _b8 : Object)
4111
+ __metadata24("design:type", Function),
4112
+ __metadata24("design:paramtypes", [Object]),
4113
+ __metadata24("design:returntype", typeof (_b12 = typeof Promise !== "undefined" && Promise) === "function" ? _b12 : Object)
3968
4114
  ], ListGuard.prototype, "canActivate", null);
3969
- ListGuard = __decorate23([
3970
- Injectable11()
4115
+ ListGuard = __decorate24([
4116
+ Injectable12()
3971
4117
  ], ListGuard);
3972
4118
  const access = createGuard5(AccessGuard);
3973
4119
  const list = createGuard5(ListGuard);
@@ -4098,11 +4244,11 @@ function configureOwnership(config) {
4098
4244
  }
4099
4245
  }
4100
4246
  };
4101
- GeneratedOwnershipService = __decorate23([
4102
- Injectable11()
4247
+ GeneratedOwnershipService = __decorate24([
4248
+ Injectable12()
4103
4249
  ], GeneratedOwnershipService);
4104
4250
  function bodyGuard(resourceType, bodyField, optional = false) {
4105
- var _a16;
4251
+ var _a22;
4106
4252
  let BodyAccessGuard = class BodyAccessGuard {
4107
4253
  static {
4108
4254
  __name(this, "BodyAccessGuard");
@@ -4115,19 +4261,19 @@ function configureOwnership(config) {
4115
4261
  return this.ownership.canAccess(user, resourceType, id);
4116
4262
  }
4117
4263
  };
4118
- __decorate23([
4264
+ __decorate24([
4119
4265
  Inject11(GeneratedOwnershipService),
4120
- __metadata23("design:type", GeneratedOwnershipService)
4266
+ __metadata24("design:type", GeneratedOwnershipService)
4121
4267
  ], BodyAccessGuard.prototype, "ownership", void 0);
4122
- __decorate23([
4268
+ __decorate24([
4123
4269
  __param10(0, User5()),
4124
4270
  __param10(1, Body5()),
4125
- __metadata23("design:type", Function),
4126
- __metadata23("design:paramtypes", [Object, Object]),
4127
- __metadata23("design:returntype", typeof (_a16 = typeof Promise !== "undefined" && Promise) === "function" ? _a16 : Object)
4271
+ __metadata24("design:type", Function),
4272
+ __metadata24("design:paramtypes", [Object, Object]),
4273
+ __metadata24("design:returntype", typeof (_a22 = typeof Promise !== "undefined" && Promise) === "function" ? _a22 : Object)
4128
4274
  ], BodyAccessGuard.prototype, "canActivate", null);
4129
- BodyAccessGuard = __decorate23([
4130
- Injectable11()
4275
+ BodyAccessGuard = __decorate24([
4276
+ Injectable12()
4131
4277
  ], BodyAccessGuard);
4132
4278
  return createGuard5(BodyAccessGuard);
4133
4279
  }
@@ -4242,18 +4388,18 @@ __name(Policy, "Policy");
4242
4388
  // src/ownership/OwnedDecorator.ts
4243
4389
  import "reflect-metadata";
4244
4390
  import { sql as sql5, and as and3 } from "drizzle-orm";
4245
- import { Injectable as Injectable12, Inject as Inject12, DI as DI2, Container as Container2, REQUEST_ID } from "najm-core";
4391
+ import { Injectable as Injectable13, Inject as Inject12, DI as DI2, Container as Container2, REQUEST_ID } from "najm-core";
4246
4392
  import { USER as USER2 } from "najm-guard";
4247
- var __decorate24 = function(decorators, target, key, desc) {
4393
+ var __decorate25 = function(decorators, target, key, desc) {
4248
4394
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4249
4395
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4250
4396
  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;
4251
4397
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4252
4398
  };
4253
- var __metadata24 = function(k, v) {
4399
+ var __metadata25 = function(k, v) {
4254
4400
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4255
4401
  };
4256
- var _a15;
4402
+ var _a16;
4257
4403
  var OWNED_META = /* @__PURE__ */ Symbol.for("najm:owned");
4258
4404
  var ScopeContext = class ScopeContext2 {
4259
4405
  static {
@@ -4285,12 +4431,12 @@ var ScopeContext = class ScopeContext2 {
4285
4431
  }
4286
4432
  }
4287
4433
  };
4288
- __decorate24([
4434
+ __decorate25([
4289
4435
  DI2(),
4290
- __metadata24("design:type", typeof (_a15 = typeof Container2 !== "undefined" && Container2) === "function" ? _a15 : Object)
4436
+ __metadata25("design:type", typeof (_a16 = typeof Container2 !== "undefined" && Container2) === "function" ? _a16 : Object)
4291
4437
  ], ScopeContext.prototype, "container", void 0);
4292
- ScopeContext = __decorate24([
4293
- Injectable12()
4438
+ ScopeContext = __decorate25([
4439
+ Injectable13()
4294
4440
  ], ScopeContext);
4295
4441
  function Owned(token) {
4296
4442
  return function(target) {
@@ -4393,7 +4539,18 @@ var en_default = {
4393
4539
  unauthorized: "Unauthorized access",
4394
4540
  sessionExpired: "Session has expired",
4395
4541
  accountLocked: "Account is temporarily locked. Please try again later.",
4396
- accountInactive: "Account is inactive. Please contact support."
4542
+ accountInactive: "Account is inactive. Please contact support.",
4543
+ emailNotVerified: "Please verify your email address before signing in.",
4544
+ oauthProviderDisabled: "Google sign-in is not configured.",
4545
+ oauthStateInvalid: "The Google sign-in attempt is invalid or expired.",
4546
+ oauthAccessDenied: "Google sign-in was cancelled.",
4547
+ oauthProviderError: "Google sign-in could not be completed.",
4548
+ oauthVerifiedEmailRequired: "Google must provide a verified email address.",
4549
+ oauthAccountLinkRequired: "Sign in with your password and link Google from your account.",
4550
+ oauthProviderAccountLinked: "This Google account is already linked.",
4551
+ oauthSignupDisabled: "Registration with Google is disabled.",
4552
+ oauthHostedDomainDenied: "This Google Workspace domain is not allowed.",
4553
+ oauthLinkSessionExpired: "Your session changed before Google could be linked. Please try again."
4397
4554
  },
4398
4555
  success: {
4399
4556
  login: "Login successful",
@@ -4403,7 +4560,9 @@ var en_default = {
4403
4560
  passwordResetSent: "If that email exists, a reset link has been sent",
4404
4561
  passwordReset: "Password has been reset successfully",
4405
4562
  accountInviteSent: "Invitation sent successfully",
4406
- tokenRefreshed: "Token refreshed successfully"
4563
+ tokenRefreshed: "Token refreshed successfully",
4564
+ oauthLogin: "Google sign-in successful",
4565
+ oauthLinked: "Google account linked successfully"
4407
4566
  },
4408
4567
  emails: {
4409
4568
  passwordReset: {
@@ -4436,7 +4595,9 @@ var en_default = {
4436
4595
  notFound: "Role not found",
4437
4596
  exists: "Role already exists",
4438
4597
  nameRequired: "Role name is required",
4439
- cannotDeleteSystem: "Cannot delete system role"
4598
+ cannotDeleteSystem: "Cannot delete system role",
4599
+ cannotRenameSystem: "Cannot rename the system admin role",
4600
+ roleInUse: "Cannot delete a role that is assigned to users"
4440
4601
  },
4441
4602
  success: {
4442
4603
  created: "Role created successfully",
@@ -4477,6 +4638,674 @@ function getAuthLocale(lang) {
4477
4638
  __name(getAuthLocale, "getAuthLocale");
4478
4639
  var AUTH_SUPPORTED_LANGUAGES = Object.keys(AUTH_LOCALES);
4479
4640
 
4641
+ // src/oauth/google/GoogleOAuthProvider.ts
4642
+ import { Inject as Inject14, Injectable as Injectable15 } from "najm-core";
4643
+
4644
+ // src/oauth/types.ts
4645
+ var OAuthFlowError = class extends Error {
4646
+ static {
4647
+ __name(this, "OAuthFlowError");
4648
+ }
4649
+ oauthCode;
4650
+ status;
4651
+ constructor(oauthCode, status = 400) {
4652
+ super(oauthCode);
4653
+ this.oauthCode = oauthCode;
4654
+ this.status = status;
4655
+ this.name = "OAuthFlowError";
4656
+ }
4657
+ };
4658
+
4659
+ // src/oauth/google/GoogleTokenVerifier.ts
4660
+ import { Inject as Inject13, Injectable as Injectable14 } from "najm-core";
4661
+ import { createRemoteJWKSet, jwtVerify } from "jose";
4662
+ var __decorate26 = function(decorators, target, key, desc) {
4663
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4664
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4665
+ 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;
4666
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4667
+ };
4668
+ var __metadata26 = function(k, v) {
4669
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4670
+ };
4671
+ var GOOGLE_JWKS = createRemoteJWKSet(new URL("https://www.googleapis.com/oauth2/v3/certs"));
4672
+ var GoogleTokenVerifier = class GoogleTokenVerifier2 {
4673
+ static {
4674
+ __name(this, "GoogleTokenVerifier");
4675
+ }
4676
+ config;
4677
+ jwks = GOOGLE_JWKS;
4678
+ async verify(idToken, nonce) {
4679
+ const google = this.googleConfig();
4680
+ try {
4681
+ const { payload } = await jwtVerify(idToken, this.jwks, {
4682
+ issuer: ["https://accounts.google.com", "accounts.google.com"],
4683
+ audience: google.clientId,
4684
+ algorithms: ["RS256"]
4685
+ });
4686
+ if (payload.nonce !== nonce)
4687
+ throw new OAuthFlowError("oauth_token_invalid");
4688
+ if (typeof payload.sub !== "string" || !payload.sub) {
4689
+ throw new OAuthFlowError("oauth_token_invalid");
4690
+ }
4691
+ if (typeof payload.email !== "string" || !payload.email || payload.email_verified !== true) {
4692
+ throw new OAuthFlowError("oauth_verified_email_required");
4693
+ }
4694
+ const hostedDomain = typeof payload.hd === "string" ? payload.hd.toLowerCase() : void 0;
4695
+ if (google.allowedHostedDomains.length > 0 && (!hostedDomain || !google.allowedHostedDomains.includes(hostedDomain))) {
4696
+ throw new OAuthFlowError("oauth_hosted_domain_denied", 403);
4697
+ }
4698
+ return {
4699
+ provider: "google",
4700
+ providerAccountId: payload.sub,
4701
+ email: payload.email.trim().toLowerCase(),
4702
+ emailVerified: true,
4703
+ name: typeof payload.name === "string" ? payload.name : void 0,
4704
+ picture: typeof payload.picture === "string" ? payload.picture : void 0,
4705
+ hostedDomain
4706
+ };
4707
+ } catch (error) {
4708
+ if (error instanceof OAuthFlowError)
4709
+ throw error;
4710
+ throw new OAuthFlowError("oauth_token_invalid");
4711
+ }
4712
+ }
4713
+ googleConfig() {
4714
+ const google = this.config.oauth?.google;
4715
+ if (!google)
4716
+ throw new OAuthFlowError("oauth_provider_disabled", 404);
4717
+ return google;
4718
+ }
4719
+ };
4720
+ __decorate26([
4721
+ Inject13(AUTH_CONFIG),
4722
+ __metadata26("design:type", Object)
4723
+ ], GoogleTokenVerifier.prototype, "config", void 0);
4724
+ GoogleTokenVerifier = __decorate26([
4725
+ Injectable14()
4726
+ ], GoogleTokenVerifier);
4727
+
4728
+ // src/oauth/google/GoogleOAuthProvider.ts
4729
+ var __decorate27 = function(decorators, target, key, desc) {
4730
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4731
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4732
+ 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;
4733
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4734
+ };
4735
+ var __metadata27 = function(k, v) {
4736
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4737
+ };
4738
+ var _a17;
4739
+ var AUTHORIZATION_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth";
4740
+ var TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token";
4741
+ var GoogleOAuthProvider = class GoogleOAuthProvider2 {
4742
+ static {
4743
+ __name(this, "GoogleOAuthProvider");
4744
+ }
4745
+ verifier;
4746
+ config;
4747
+ constructor(verifier) {
4748
+ this.verifier = verifier;
4749
+ }
4750
+ authorizationUrl(attempt, codeChallenge) {
4751
+ const google = this.googleConfig();
4752
+ const url = new URL(AUTHORIZATION_ENDPOINT);
4753
+ url.search = new URLSearchParams({
4754
+ client_id: google.clientId,
4755
+ redirect_uri: google.callbackUrl,
4756
+ response_type: "code",
4757
+ scope: "openid email profile",
4758
+ state: attempt.state,
4759
+ nonce: attempt.nonce,
4760
+ code_challenge: codeChallenge,
4761
+ code_challenge_method: "S256"
4762
+ }).toString();
4763
+ return url.toString();
4764
+ }
4765
+ async exchange(code, attempt) {
4766
+ const google = this.googleConfig();
4767
+ let response;
4768
+ try {
4769
+ response = await fetch(TOKEN_ENDPOINT, {
4770
+ method: "POST",
4771
+ headers: { "content-type": "application/x-www-form-urlencoded" },
4772
+ body: new URLSearchParams({
4773
+ code,
4774
+ client_id: google.clientId,
4775
+ client_secret: google.clientSecret,
4776
+ redirect_uri: google.callbackUrl,
4777
+ grant_type: "authorization_code",
4778
+ code_verifier: attempt.codeVerifier
4779
+ }),
4780
+ signal: AbortSignal.timeout(15e3)
4781
+ });
4782
+ } catch {
4783
+ throw new OAuthFlowError("oauth_provider_error", 502);
4784
+ }
4785
+ if (!response.ok)
4786
+ throw new OAuthFlowError("oauth_provider_error", 502);
4787
+ let body;
4788
+ try {
4789
+ body = await response.json();
4790
+ } catch {
4791
+ throw new OAuthFlowError("oauth_provider_error", 502);
4792
+ }
4793
+ const idToken = body.id_token;
4794
+ if (typeof idToken !== "string" || !idToken) {
4795
+ throw new OAuthFlowError("oauth_provider_error", 502);
4796
+ }
4797
+ return this.verifier.verify(idToken, attempt.nonce);
4798
+ }
4799
+ googleConfig() {
4800
+ const google = this.config.oauth?.google;
4801
+ if (!google)
4802
+ throw new OAuthFlowError("oauth_provider_disabled", 404);
4803
+ return google;
4804
+ }
4805
+ };
4806
+ __decorate27([
4807
+ Inject14(AUTH_CONFIG),
4808
+ __metadata27("design:type", Object)
4809
+ ], GoogleOAuthProvider.prototype, "config", void 0);
4810
+ GoogleOAuthProvider = __decorate27([
4811
+ Injectable15(),
4812
+ __metadata27("design:paramtypes", [typeof (_a17 = typeof GoogleTokenVerifier !== "undefined" && GoogleTokenVerifier) === "function" ? _a17 : Object])
4813
+ ], GoogleOAuthProvider);
4814
+
4815
+ // src/oauth/OAuthAccountRepository.ts
4816
+ import { and as and4, eq as eq7 } from "drizzle-orm";
4817
+ import { Inject as Inject15, Repository as Repository5 } from "najm-core";
4818
+ import { DB as DB5 } from "najm-database";
4819
+ var __decorate28 = function(decorators, target, key, desc) {
4820
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4821
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4822
+ 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;
4823
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4824
+ };
4825
+ var __metadata28 = function(k, v) {
4826
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4827
+ };
4828
+ var OAuthAccountRepository = class OAuthAccountRepository2 {
4829
+ static {
4830
+ __name(this, "OAuthAccountRepository");
4831
+ }
4832
+ db;
4833
+ schema;
4834
+ get accounts() {
4835
+ if (!this.schema.oauthAccounts) {
4836
+ throw new OAuthFlowError("oauth_schema_missing", 500);
4837
+ }
4838
+ return this.schema.oauthAccounts;
4839
+ }
4840
+ async getByProviderAccount(provider, providerAccountId) {
4841
+ const [account] = await this.db.select().from(this.accounts).where(and4(eq7(this.accounts.provider, provider), eq7(this.accounts.providerAccountId, providerAccountId))).limit(1);
4842
+ return account;
4843
+ }
4844
+ async getByUserProvider(userId, provider) {
4845
+ const [account] = await this.db.select().from(this.accounts).where(and4(eq7(this.accounts.userId, userId), eq7(this.accounts.provider, provider))).limit(1);
4846
+ return account;
4847
+ }
4848
+ async create(data) {
4849
+ const [account] = await this.db.insert(this.accounts).values(data).onConflictDoNothing().returning();
4850
+ return account;
4851
+ }
4852
+ };
4853
+ __decorate28([
4854
+ DB5(),
4855
+ __metadata28("design:type", Object)
4856
+ ], OAuthAccountRepository.prototype, "db", void 0);
4857
+ __decorate28([
4858
+ Inject15(AUTH_SCHEMA),
4859
+ __metadata28("design:type", Object)
4860
+ ], OAuthAccountRepository.prototype, "schema", void 0);
4861
+ OAuthAccountRepository = __decorate28([
4862
+ Repository5()
4863
+ ], OAuthAccountRepository);
4864
+
4865
+ // src/oauth/OAuthAccountService.ts
4866
+ import { randomBytes as randomBytes2 } from "crypto";
4867
+ import { Inject as Inject16, Injectable as Injectable16 } from "najm-core";
4868
+ import { Transaction as Transaction2 } from "najm-database";
4869
+ var __decorate29 = function(decorators, target, key, desc) {
4870
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4871
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4872
+ 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;
4873
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4874
+ };
4875
+ var __metadata29 = function(k, v) {
4876
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4877
+ };
4878
+ var _a18;
4879
+ var _b9;
4880
+ var _c6;
4881
+ var _d3;
4882
+ var OAuthAccountService = class OAuthAccountService2 {
4883
+ static {
4884
+ __name(this, "OAuthAccountService");
4885
+ }
4886
+ accounts;
4887
+ users;
4888
+ config;
4889
+ constructor(accounts, users) {
4890
+ this.accounts = accounts;
4891
+ this.users = users;
4892
+ }
4893
+ async resolveForLogin(identity) {
4894
+ const linked = await this.accounts.getByProviderAccount("google", identity.providerAccountId);
4895
+ if (linked)
4896
+ return this.users.getById(linked.userId);
4897
+ const existingUser = await this.users.findByEmailInsensitive(identity.email);
4898
+ if (existingUser) {
4899
+ if (!this.googleConfig().autoLinkVerifiedEmail) {
4900
+ throw new OAuthFlowError("oauth_account_link_required", 409);
4901
+ }
4902
+ await this.createLink(existingUser.id, identity);
4903
+ return this.users.getById(existingUser.id);
4904
+ }
4905
+ if (!this.googleConfig().allowSignup) {
4906
+ throw new OAuthFlowError("oauth_signup_disabled", 403);
4907
+ }
4908
+ const password = `${randomBytes2(32).toString("base64url")}Aa1`;
4909
+ const user = await this.users.create({
4910
+ name: identity.name,
4911
+ email: identity.email,
4912
+ password,
4913
+ image: identity.picture,
4914
+ emailVerified: true
4915
+ });
4916
+ await this.createLink(user.id, identity);
4917
+ return this.users.getById(user.id);
4918
+ }
4919
+ async linkUser(userId, identity) {
4920
+ const user = await this.users.getById(userId);
4921
+ if (user.status !== "active")
4922
+ throw new OAuthFlowError("oauth_account_inactive", 403);
4923
+ const providerAccount = await this.accounts.getByProviderAccount("google", identity.providerAccountId);
4924
+ if (providerAccount && providerAccount.userId !== userId) {
4925
+ throw new OAuthFlowError("oauth_provider_account_linked", 409);
4926
+ }
4927
+ if (providerAccount)
4928
+ return user;
4929
+ const userProvider = await this.accounts.getByUserProvider(userId, "google");
4930
+ if (userProvider && userProvider.providerAccountId !== identity.providerAccountId) {
4931
+ throw new OAuthFlowError("oauth_user_provider_linked", 409);
4932
+ }
4933
+ if (!userProvider)
4934
+ await this.createLink(userId, identity);
4935
+ return user;
4936
+ }
4937
+ async createLink(userId, identity) {
4938
+ const created = await this.accounts.create({
4939
+ userId,
4940
+ provider: "google",
4941
+ providerAccountId: identity.providerAccountId
4942
+ });
4943
+ if (created)
4944
+ return;
4945
+ const linked = await this.accounts.getByProviderAccount("google", identity.providerAccountId);
4946
+ if (!linked || linked.userId !== userId) {
4947
+ throw new OAuthFlowError("oauth_provider_account_linked", 409);
4948
+ }
4949
+ }
4950
+ googleConfig() {
4951
+ const google = this.config.oauth?.google;
4952
+ if (!google)
4953
+ throw new OAuthFlowError("oauth_provider_disabled", 404);
4954
+ return google;
4955
+ }
4956
+ };
4957
+ __decorate29([
4958
+ Inject16(AUTH_CONFIG),
4959
+ __metadata29("design:type", Object)
4960
+ ], OAuthAccountService.prototype, "config", void 0);
4961
+ __decorate29([
4962
+ Transaction2(),
4963
+ __metadata29("design:type", Function),
4964
+ __metadata29("design:paramtypes", [Object]),
4965
+ __metadata29("design:returntype", typeof (_c6 = typeof Promise !== "undefined" && Promise) === "function" ? _c6 : Object)
4966
+ ], OAuthAccountService.prototype, "resolveForLogin", null);
4967
+ __decorate29([
4968
+ Transaction2(),
4969
+ __metadata29("design:type", Function),
4970
+ __metadata29("design:paramtypes", [String, Object]),
4971
+ __metadata29("design:returntype", typeof (_d3 = typeof Promise !== "undefined" && Promise) === "function" ? _d3 : Object)
4972
+ ], OAuthAccountService.prototype, "linkUser", null);
4973
+ OAuthAccountService = __decorate29([
4974
+ Injectable16(),
4975
+ __metadata29("design:paramtypes", [typeof (_a18 = typeof OAuthAccountRepository !== "undefined" && OAuthAccountRepository) === "function" ? _a18 : Object, typeof (_b9 = typeof UserService !== "undefined" && UserService) === "function" ? _b9 : Object])
4976
+ ], OAuthAccountService);
4977
+
4978
+ // src/oauth/OAuthController.ts
4979
+ import { createHash as createHash4 } from "crypto";
4980
+ import { Controller as Controller5, Ctx, Get as Get5, Post as Post5, Query as Query2, User as User6 } from "najm-core";
4981
+ import { RateLimit as RateLimit2 } from "najm-rate";
4982
+
4983
+ // src/oauth/OAuthService.ts
4984
+ import { Inject as Inject17, Injectable as Injectable18, Log as Log2 } from "najm-core";
4985
+
4986
+ // src/oauth/OAuthStateService.ts
4987
+ import { createHash as createHash3, randomBytes as randomBytes3, timingSafeEqual } from "crypto";
4988
+ import { Injectable as Injectable17 } from "najm-core";
4989
+ import { CookieService as CookieService2 } from "najm-cookies";
4990
+ var __decorate30 = function(decorators, target, key, desc) {
4991
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4992
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4993
+ 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;
4994
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
4995
+ };
4996
+ var __metadata30 = function(k, v) {
4997
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4998
+ };
4999
+ var _a19;
5000
+ var _b10;
5001
+ var ATTEMPT_TTL_MS = 10 * 60 * 1e3;
5002
+ var COOKIE_PREFIX = "najm.oauth.google.";
5003
+ var OAuthStateService = class OAuthStateService2 {
5004
+ static {
5005
+ __name(this, "OAuthStateService");
5006
+ }
5007
+ cookies;
5008
+ encryption;
5009
+ constructor(cookies2, encryption) {
5010
+ this.cookies = cookies2;
5011
+ this.encryption = encryption;
5012
+ }
5013
+ create(input) {
5014
+ const state = randomBytes3(32).toString("base64url");
5015
+ const codeVerifier = randomBytes3(48).toString("base64url");
5016
+ const attempt = {
5017
+ provider: "google",
5018
+ intent: input.intent,
5019
+ state,
5020
+ nonce: randomBytes3(32).toString("base64url"),
5021
+ codeVerifier,
5022
+ returnTo: this.validateReturnTo(input.returnTo),
5023
+ userId: input.userId,
5024
+ sessionVersion: input.sessionVersion,
5025
+ createdAt: Date.now()
5026
+ };
5027
+ this.cookies.set(this.cookieName(state), this.encryption.encrypt(JSON.stringify(attempt)), {
5028
+ httpOnly: true,
5029
+ sameSite: "Lax",
5030
+ path: "/",
5031
+ maxAge: Math.floor(ATTEMPT_TTL_MS / 1e3)
5032
+ });
5033
+ return {
5034
+ attempt,
5035
+ codeChallenge: createHash3("sha256").update(codeVerifier).digest("base64url")
5036
+ };
5037
+ }
5038
+ consume(state) {
5039
+ if (!this.isSafeState(state))
5040
+ throw new OAuthFlowError("oauth_state_invalid");
5041
+ const name = this.cookieName(state);
5042
+ const encrypted = this.cookies.get(name);
5043
+ this.cookies.delete(name, { path: "/" });
5044
+ if (!encrypted)
5045
+ throw new OAuthFlowError("oauth_state_invalid");
5046
+ try {
5047
+ const attempt = JSON.parse(this.encryption.decrypt(encrypted));
5048
+ const expected = Buffer.from(attempt.state);
5049
+ const actual = Buffer.from(state);
5050
+ if (expected.length !== actual.length || !timingSafeEqual(expected, actual)) {
5051
+ throw new OAuthFlowError("oauth_state_invalid");
5052
+ }
5053
+ if (attempt.provider !== "google" || Date.now() - attempt.createdAt > ATTEMPT_TTL_MS) {
5054
+ throw new OAuthFlowError("oauth_state_invalid");
5055
+ }
5056
+ attempt.returnTo = this.validateReturnTo(attempt.returnTo);
5057
+ return attempt;
5058
+ } catch (error) {
5059
+ if (error instanceof OAuthFlowError)
5060
+ throw error;
5061
+ throw new OAuthFlowError("oauth_state_invalid");
5062
+ }
5063
+ }
5064
+ validateReturnTo(value) {
5065
+ const candidate = value?.trim() || "/";
5066
+ if (!candidate.startsWith("/") || candidate.startsWith("//") || candidate.includes("\\")) {
5067
+ throw new OAuthFlowError("oauth_redirect_invalid");
5068
+ }
5069
+ try {
5070
+ const base = new URL("https://najm.invalid");
5071
+ const parsed = new URL(candidate, base);
5072
+ if (parsed.origin !== base.origin || parsed.username || parsed.password) {
5073
+ throw new OAuthFlowError("oauth_redirect_invalid");
5074
+ }
5075
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
5076
+ } catch (error) {
5077
+ if (error instanceof OAuthFlowError)
5078
+ throw error;
5079
+ throw new OAuthFlowError("oauth_redirect_invalid");
5080
+ }
5081
+ }
5082
+ cookieName(state) {
5083
+ return `${COOKIE_PREFIX}${state}`;
5084
+ }
5085
+ isSafeState(state) {
5086
+ return /^[A-Za-z0-9_-]{40,128}$/.test(state);
5087
+ }
5088
+ };
5089
+ OAuthStateService = __decorate30([
5090
+ Injectable17(),
5091
+ __metadata30("design:paramtypes", [typeof (_a19 = typeof CookieService2 !== "undefined" && CookieService2) === "function" ? _a19 : Object, typeof (_b10 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b10 : Object])
5092
+ ], OAuthStateService);
5093
+
5094
+ // src/oauth/OAuthService.ts
5095
+ var __decorate31 = function(decorators, target, key, desc) {
5096
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5097
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5098
+ 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;
5099
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
5100
+ };
5101
+ var __metadata31 = function(k, v) {
5102
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5103
+ };
5104
+ var _a20;
5105
+ var _b11;
5106
+ var _c7;
5107
+ var _d4;
5108
+ var _e3;
5109
+ var _f3;
5110
+ var OAuthService = class OAuthService2 {
5111
+ static {
5112
+ __name(this, "OAuthService");
5113
+ }
5114
+ state;
5115
+ google;
5116
+ accounts;
5117
+ sessions;
5118
+ tokens;
5119
+ users;
5120
+ config;
5121
+ logger;
5122
+ constructor(state, google, accounts, sessions, tokens, users) {
5123
+ this.state = state;
5124
+ this.google = google;
5125
+ this.accounts = accounts;
5126
+ this.sessions = sessions;
5127
+ this.tokens = tokens;
5128
+ this.users = users;
5129
+ }
5130
+ startGoogleLogin(returnTo) {
5131
+ this.googleConfig();
5132
+ const { attempt, codeChallenge } = this.state.create({ intent: "login", returnTo });
5133
+ return this.google.authorizationUrl(attempt, codeChallenge);
5134
+ }
5135
+ async startGoogleLink(userId, returnTo) {
5136
+ this.googleConfig();
5137
+ const user = await this.users.getById(userId);
5138
+ if (user.status !== "active")
5139
+ throw new OAuthFlowError("oauth_account_inactive", 403);
5140
+ const sessionVersion = await this.tokens.getSessionVersion(userId);
5141
+ const { attempt, codeChallenge } = this.state.create({
5142
+ intent: "link",
5143
+ returnTo,
5144
+ userId,
5145
+ sessionVersion
5146
+ });
5147
+ return { authorizationUrl: this.google.authorizationUrl(attempt, codeChallenge) };
5148
+ }
5149
+ async finishGoogleCallback(params) {
5150
+ try {
5151
+ this.googleConfig();
5152
+ if (!params.state)
5153
+ throw new OAuthFlowError("oauth_state_invalid");
5154
+ const attempt = this.state.consume(params.state);
5155
+ if (params.error) {
5156
+ throw new OAuthFlowError(params.error === "access_denied" ? "oauth_access_denied" : "oauth_provider_error");
5157
+ }
5158
+ if (!params.code)
5159
+ throw new OAuthFlowError("oauth_provider_error");
5160
+ const identity = await this.google.exchange(params.code, attempt);
5161
+ if (attempt.intent === "link") {
5162
+ if (!attempt.userId || attempt.sessionVersion === void 0) {
5163
+ throw new OAuthFlowError("oauth_state_invalid");
5164
+ }
5165
+ const currentVersion = await this.tokens.getSessionVersion(attempt.userId);
5166
+ if (currentVersion !== attempt.sessionVersion) {
5167
+ throw new OAuthFlowError("oauth_link_session_expired", 401);
5168
+ }
5169
+ await this.accounts.linkUser(attempt.userId, identity);
5170
+ } else {
5171
+ const user = await this.accounts.resolveForLogin(identity);
5172
+ await this.sessions.establish(user);
5173
+ }
5174
+ return this.frontendSuccessUrl(attempt.returnTo, attempt.intent);
5175
+ } catch (error) {
5176
+ const code = this.publicErrorCode(error);
5177
+ this.logger.warn("Google OAuth callback failed", { provider: "google", code });
5178
+ return this.frontendErrorUrl(code);
5179
+ }
5180
+ }
5181
+ frontendSuccessUrl(returnTo, mode) {
5182
+ const google = this.googleConfig();
5183
+ const url = new URL(google.frontendCallbackPath, this.config.frontendUrl);
5184
+ url.searchParams.set("provider", "google");
5185
+ url.searchParams.set("mode", mode);
5186
+ url.searchParams.set("returnTo", this.state.validateReturnTo(returnTo));
5187
+ return url.toString();
5188
+ }
5189
+ frontendErrorUrl(code) {
5190
+ const path2 = this.config.oauth?.google?.errorRedirectPath ?? "/login";
5191
+ const url = new URL(path2, this.config.frontendUrl);
5192
+ url.searchParams.set("oauthError", code);
5193
+ return url.toString();
5194
+ }
5195
+ publicErrorCode(error) {
5196
+ if (error instanceof OAuthFlowError)
5197
+ return error.oauthCode;
5198
+ if (error instanceof Error && /^oauth_[a-z0-9_]+$/.test(error.message))
5199
+ return error.message;
5200
+ return "oauth_provider_error";
5201
+ }
5202
+ googleConfig() {
5203
+ const google = this.config.oauth?.google;
5204
+ if (!google)
5205
+ throw new OAuthFlowError("oauth_provider_disabled", 404);
5206
+ return google;
5207
+ }
5208
+ };
5209
+ __decorate31([
5210
+ Inject17(AUTH_CONFIG),
5211
+ __metadata31("design:type", Object)
5212
+ ], OAuthService.prototype, "config", void 0);
5213
+ __decorate31([
5214
+ Log2(),
5215
+ __metadata31("design:type", Object)
5216
+ ], OAuthService.prototype, "logger", void 0);
5217
+ OAuthService = __decorate31([
5218
+ Injectable18(),
5219
+ __metadata31("design:paramtypes", [typeof (_a20 = typeof OAuthStateService !== "undefined" && OAuthStateService) === "function" ? _a20 : Object, typeof (_b11 = typeof GoogleOAuthProvider !== "undefined" && GoogleOAuthProvider) === "function" ? _b11 : Object, typeof (_c7 = typeof OAuthAccountService !== "undefined" && OAuthAccountService) === "function" ? _c7 : Object, typeof (_d4 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _d4 : Object, typeof (_e3 = typeof TokenService !== "undefined" && TokenService) === "function" ? _e3 : Object, typeof (_f3 = typeof UserService !== "undefined" && UserService) === "function" ? _f3 : Object])
5220
+ ], OAuthService);
5221
+
5222
+ // src/oauth/OAuthController.ts
5223
+ var __decorate32 = function(decorators, target, key, desc) {
5224
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5225
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5226
+ 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;
5227
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
5228
+ };
5229
+ var __metadata32 = function(k, v) {
5230
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5231
+ };
5232
+ var __param11 = function(paramIndex, decorator) {
5233
+ return function(target, key) {
5234
+ decorator(target, key, paramIndex);
5235
+ };
5236
+ };
5237
+ var _a21;
5238
+ var callbackKey = /* @__PURE__ */ __name((ctx) => {
5239
+ const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
5240
+ const state = ctx.req.query("state") ?? "none";
5241
+ const fingerprint = createHash4("sha256").update(state).digest("base64url").slice(0, 24);
5242
+ return `${ip}:${fingerprint}`;
5243
+ }, "callbackKey");
5244
+ var OAuthController = class OAuthController2 {
5245
+ static {
5246
+ __name(this, "OAuthController");
5247
+ }
5248
+ oauth;
5249
+ constructor(oauth) {
5250
+ this.oauth = oauth;
5251
+ }
5252
+ start(ctx, returnTo) {
5253
+ return ctx.redirect(this.oauth.startGoogleLogin(returnTo), 302);
5254
+ }
5255
+ async callback(ctx, code, state, error) {
5256
+ const redirect = await this.oauth.finishGoogleCallback({ code, state, error });
5257
+ return ctx.redirect(redirect, 302);
5258
+ }
5259
+ link(userId, returnTo) {
5260
+ return this.oauth.startGoogleLink(userId, returnTo);
5261
+ }
5262
+ };
5263
+ __decorate32([
5264
+ Get5("/start"),
5265
+ RateLimit2({ limit: 20, window: "15m", key: "ip" }),
5266
+ __param11(0, Ctx()),
5267
+ __param11(1, Query2("returnTo")),
5268
+ __metadata32("design:type", Function),
5269
+ __metadata32("design:paramtypes", [Object, String]),
5270
+ __metadata32("design:returntype", void 0)
5271
+ ], OAuthController.prototype, "start", null);
5272
+ __decorate32([
5273
+ Get5("/callback"),
5274
+ RateLimit2({ limit: 20, window: "15m", key: callbackKey }),
5275
+ __param11(0, Ctx()),
5276
+ __param11(1, Query2("code")),
5277
+ __param11(2, Query2("state")),
5278
+ __param11(3, Query2("error")),
5279
+ __metadata32("design:type", Function),
5280
+ __metadata32("design:paramtypes", [Object, String, String, String]),
5281
+ __metadata32("design:returntype", Promise)
5282
+ ], OAuthController.prototype, "callback", null);
5283
+ __decorate32([
5284
+ Post5("/link"),
5285
+ isAuth(),
5286
+ RateLimit2({ limit: 10, window: "15m", key: "user" }),
5287
+ __param11(0, User6("id")),
5288
+ __param11(1, Query2("returnTo")),
5289
+ __metadata32("design:type", Function),
5290
+ __metadata32("design:paramtypes", [String, String]),
5291
+ __metadata32("design:returntype", void 0)
5292
+ ], OAuthController.prototype, "link", null);
5293
+ OAuthController = __decorate32([
5294
+ Controller5("/auth/oauth/google"),
5295
+ __metadata32("design:paramtypes", [typeof (_a21 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a21 : Object])
5296
+ ], OAuthController);
5297
+
5298
+ // src/oauth/index.ts
5299
+ var OAUTH_MODULE = [
5300
+ OAuthAccountRepository,
5301
+ OAuthAccountService,
5302
+ OAuthStateService,
5303
+ GoogleTokenVerifier,
5304
+ GoogleOAuthProvider,
5305
+ OAuthService,
5306
+ OAuthController
5307
+ ];
5308
+
4480
5309
  // src/AuthPlugin.ts
4481
5310
  var DEFAULT_JWT = {
4482
5311
  accessSecret: process.env.JWT_ACCESS_SECRET || "",
@@ -4484,7 +5313,47 @@ var DEFAULT_JWT = {
4484
5313
  refreshSecret: process.env.JWT_REFRESH_SECRET || "",
4485
5314
  refreshExpiresIn: process.env.REFRESH_EXPIRES_IN || "7d"
4486
5315
  };
4487
- var mergeConfig = /* @__PURE__ */ __name((config) => {
5316
+ var validateFrontendPath = /* @__PURE__ */ __name((value, name) => {
5317
+ if (!value.startsWith("/") || value.startsWith("//") || value.includes("\\")) {
5318
+ throw new Error(`${name} must be a same-origin path starting with a single '/'`);
5319
+ }
5320
+ return value;
5321
+ }, "validateFrontendPath");
5322
+ var resolveGoogleConfig = /* @__PURE__ */ __name((config) => {
5323
+ const configuredGoogle = config?.oauth?.google;
5324
+ if (!configuredGoogle)
5325
+ return void 0;
5326
+ const google = configuredGoogle === true ? {} : configuredGoogle;
5327
+ const clientId = google.clientId ?? process.env.GOOGLE_CLIENT_ID ?? "";
5328
+ const clientSecret = google.clientSecret ?? process.env.GOOGLE_CLIENT_SECRET ?? "";
5329
+ if (!clientId)
5330
+ throw Err10.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
5331
+ if (!clientSecret)
5332
+ throw Err10.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
5333
+ const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
5334
+ const callbackUrl = google.callbackUrl ?? process.env.GOOGLE_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/google/callback`;
5335
+ let callback;
5336
+ try {
5337
+ callback = new URL(callbackUrl);
5338
+ } catch {
5339
+ throw new Error("auth.oauth.google.callbackUrl must be an absolute URL");
5340
+ }
5341
+ const local = callback.hostname === "localhost" || callback.hostname === "127.0.0.1" || callback.hostname === "[::1]" || callback.hostname === "::1";
5342
+ if (callback.protocol !== "https:" && !(local && callback.protocol === "http:")) {
5343
+ throw new Error("auth.oauth.google.callbackUrl must use HTTPS (HTTP is allowed only for localhost)");
5344
+ }
5345
+ return {
5346
+ clientId,
5347
+ clientSecret,
5348
+ callbackUrl: callback.toString(),
5349
+ frontendCallbackPath: validateFrontendPath(google.frontendCallbackPath ?? "/auth/oauth/callback", "auth.oauth.google.frontendCallbackPath"),
5350
+ errorRedirectPath: validateFrontendPath(google.errorRedirectPath ?? "/login", "auth.oauth.google.errorRedirectPath"),
5351
+ allowSignup: google.allowSignup ?? true,
5352
+ autoLinkVerifiedEmail: google.autoLinkVerifiedEmail ?? false,
5353
+ allowedHostedDomains: [...new Set((google.allowedHostedDomains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean))]
5354
+ };
5355
+ }, "resolveGoogleConfig");
5356
+ var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
4488
5357
  const bcryptRounds = config?.bcryptRounds ?? 10;
4489
5358
  if (!Number.isInteger(bcryptRounds) || bcryptRounds < 4 || bcryptRounds > 31) {
4490
5359
  throw new Error("auth.bcryptRounds must be an integer between 4 and 31");
@@ -4500,6 +5369,8 @@ var mergeConfig = /* @__PURE__ */ __name((config) => {
4500
5369
  defaultRole: config?.defaultRole ?? null,
4501
5370
  frontendUrl: config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000",
4502
5371
  registrationMode: config?.registrationMode ?? "active",
5372
+ requireVerifiedEmail: config?.requireVerifiedEmail ?? false,
5373
+ refreshCookiePath: config?.refreshCookiePath ?? "/",
4503
5374
  lockout: {
4504
5375
  maxAttempts: config?.lockout?.maxAttempts ?? 5,
4505
5376
  duration: config?.lockout?.duration ?? "15m"
@@ -4510,19 +5381,26 @@ var mergeConfig = /* @__PURE__ */ __name((config) => {
4510
5381
  maxAge: config?.session?.maxAge ?? 300,
4511
5382
  secret: config?.session?.secret
4512
5383
  // fallback to jwt.accessSecret at use site
5384
+ },
5385
+ oauth: {
5386
+ google: resolveGoogleConfig(config)
4513
5387
  }
4514
5388
  };
4515
5389
  if (!finalConfig.jwt.accessSecret) {
4516
- throw Err8.configRequired("auth", "JWT_ACCESS_SECRET");
5390
+ throw Err10.configRequired("auth", "JWT_ACCESS_SECRET");
4517
5391
  }
4518
5392
  if (!finalConfig.jwt.refreshSecret) {
4519
- throw Err8.configRequired("auth", "JWT_REFRESH_SECRET");
5393
+ throw Err10.configRequired("auth", "JWT_REFRESH_SECRET");
4520
5394
  }
4521
5395
  return finalConfig;
4522
- }, "mergeConfig");
4523
- var selectSchema = /* @__PURE__ */ __name((config) => {
4524
- if (config?.schema)
5396
+ }, "resolveAuthConfig");
5397
+ var selectAuthSchema = /* @__PURE__ */ __name((config) => {
5398
+ if (config?.schema) {
5399
+ if (config.oauth?.google && !config.schema.oauthAccounts) {
5400
+ throw new Error("auth.schema.oauthAccounts is required when Google OAuth is enabled");
5401
+ }
4525
5402
  return config.schema;
5403
+ }
4526
5404
  const dialect = config?.dialect ?? "pg";
4527
5405
  switch (dialect) {
4528
5406
  case "sqlite":
@@ -4531,8 +5409,8 @@ var selectSchema = /* @__PURE__ */ __name((config) => {
4531
5409
  default:
4532
5410
  return authSchema;
4533
5411
  }
4534
- }, "selectSchema");
4535
- 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_MODULE, users_exports, roles_exports, permissions_exports, tokens_exports, ScopeContext).config(AUTH_CONFIG, mergeConfig(config)).set(AUTH_SCHEMA, selectSchema(config)).set(AUTH_ENCRYPTION_KEY, config?.encryptionKey ?? null).build(), "auth");
5412
+ }, "selectAuthSchema");
5413
+ var auth = /* @__PURE__ */ __name((config) => plugin("auth").version("1.0.0").depends(cache(), cookies(), i18n(), guards(), validation(config?.validation), rateLimit(config?.rateLimit), email(config?.email)).requires("database").contributes(I18N_CONTRIBUTIONS, AUTH_LOCALES).services(AUTH_MODULE, OAUTH_MODULE, users_exports, roles_exports, permissions_exports, tokens_exports, ScopeContext).config(AUTH_CONFIG, resolveAuthConfig(config)).set(AUTH_SCHEMA, selectAuthSchema(config)).set(AUTH_ENCRYPTION_KEY, config?.encryptionKey ?? null).build(), "auth");
4536
5414
 
4537
5415
  // src/seed.ts
4538
5416
  var toSeedId = /* @__PURE__ */ __name((prefix, value) => {
@@ -4678,6 +5556,7 @@ export {
4678
5556
  AuthQueries,
4679
5557
  AuthResolver,
4680
5558
  AuthService,
5559
+ AuthSessionService,
4681
5560
  Can,
4682
5561
  CanCreate,
4683
5562
  CanDelete,
@@ -4746,12 +5625,14 @@ export {
4746
5625
  join2 as join,
4747
5626
  languageParam,
4748
5627
  loginDto,
5628
+ oauthAccountsTable,
4749
5629
  own,
4750
5630
  parseSchema,
4751
5631
  permissionIdParam,
4752
5632
  permissionsTable,
4753
5633
  pickProps,
4754
5634
  refreshTokenDto,
5635
+ registerDto,
4755
5636
  resetPasswordDto,
4756
5637
  revokeTokenDto,
4757
5638
  roleIdParam,