najm-auth 3.4.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/AuthPlugin.ts
9
- import { Err as Err15, plugin } from "najm-core";
9
+ import { Err as Err16, plugin } from "najm-core";
10
10
  import { cache } from "najm-cache";
11
11
 
12
12
  // src/auth.tokens.ts
@@ -354,6 +354,7 @@ function parseSessionCookiePayload(payload, maxAgeSeconds = DEFAULT_SESSION_MAX_
354
354
  if (!isRecord(data) || !isValidUser(data.user)) return null;
355
355
  if (!isStringArray(data.roles) || !isStringArray(data.permissions)) return null;
356
356
  if (!Number.isInteger(data.sessionVersion) || data.sessionVersion < 0) return null;
357
+ if (typeof data.tokenFamily !== "string" || !data.tokenFamily) return null;
357
358
  if (!Number.isFinite(data.iat) || !Number.isInteger(data.iat) || data.iat <= 0) return null;
358
359
  const issuedAt = data.iat;
359
360
  if (issuedAt > now + MAX_CLOCK_SKEW_MS) return null;
@@ -363,6 +364,7 @@ function parseSessionCookiePayload(payload, maxAgeSeconds = DEFAULT_SESSION_MAX_
363
364
  roles: [...data.roles],
364
365
  permissions: [...data.permissions],
365
366
  sessionVersion: data.sessionVersion,
367
+ tokenFamily: data.tokenFamily,
366
368
  iat: issuedAt
367
369
  };
368
370
  } catch {
@@ -439,8 +441,10 @@ var CookieManager = class CookieManager2 {
439
441
  // =========================================================================
440
442
  /**
441
443
  * Write a signed session cookie containing user data, roles, and permissions.
442
- * The cookie is HMAC-signed with the configured session secret so it is tamper-proof
443
- * but readable without a database query. Short TTL (5 min) ensures freshness.
444
+ * The cookie is HMAC-signed with the configured session secret, so its claims
445
+ * can be parsed without a database query. Authorization still verifies the
446
+ * session version and positive family liveness; a valid signature alone is
447
+ * never a revocation check. Short TTL (5 min) bounds claim staleness.
444
448
  */
445
449
  setSessionCookie(data) {
446
450
  const payload = { ...data, iat: Date.now() };
@@ -486,7 +490,7 @@ import { Get, Post, ResMsg } from "najm-core";
486
490
  import { Body, User as User2, Headers, Ctx } from "najm-core";
487
491
 
488
492
  // src/auth/AuthService.ts
489
- import { Injectable as Injectable11, Inject as Inject11 } from "najm-core";
493
+ import { Injectable as Injectable12, Inject as Inject12 } from "najm-core";
490
494
  import { Err as Err12, Log } from "najm-core";
491
495
  import { Transaction as Transaction4 } from "najm-database";
492
496
  import { I18n as I18n8, I18nService as I18nService2 } from "najm-i18n";
@@ -494,7 +498,7 @@ import { EmailService, passwordResetTemplate, accountInviteTemplate } from "najm
494
498
  import { nanoid as nanoid5 } from "nanoid";
495
499
 
496
500
  // src/users/UserService.ts
497
- import { Injectable as Injectable5, Inject as Inject5 } from "najm-core";
501
+ import { Injectable as Injectable6, Inject as Inject7 } from "najm-core";
498
502
  import { Transaction } from "najm-database";
499
503
  import { I18nService } from "najm-i18n";
500
504
  import { I18n as I18n4 } from "najm-i18n";
@@ -674,6 +678,15 @@ var UserRepository = class UserRepository2 {
674
678
  const [newUser] = await this.db.insert(this.users).values(data).returning();
675
679
  return newUser;
676
680
  }
681
+ /**
682
+ * Ids of everyone holding a role. Used to end sessions when the role's
683
+ * permission set changes: tokens carry permissions as claims, so the holders
684
+ * keep exercising the old set until their sessions do.
685
+ */
686
+ async getIdsByRole(roleId) {
687
+ const rows = await this.db.select({ id: this.users.id }).from(this.users).where(eq2(this.users.roleId, roleId));
688
+ return rows.map((row) => row.id);
689
+ }
677
690
  async update(id, data) {
678
691
  const [updatedUser] = await this.db.update(this.users).set(data).where(eq2(this.users.id, id)).returning();
679
692
  return updatedUser;
@@ -1334,6 +1347,16 @@ __name(isEmailIdentifier, "isEmailIdentifier");
1334
1347
 
1335
1348
  // src/users/UserService.ts
1336
1349
  import { Err as Err5 } from "najm-core";
1350
+
1351
+ // src/tokens/SessionInvalidationService.ts
1352
+ import { Inject as Inject6, Injectable as Injectable5 } from "najm-core";
1353
+ import { CacheService } from "najm-cache";
1354
+ import timestring2 from "timestring";
1355
+
1356
+ // src/tokens/TokenRepository.ts
1357
+ import { and, eq as eq4, isNull, lt } from "drizzle-orm";
1358
+ import { Repository as Repository3, Inject as Inject5 } from "najm-core";
1359
+ import { DB as DB3 } from "najm-database";
1337
1360
  var __decorate8 = function(decorators, target, key, desc) {
1338
1361
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1339
1362
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1343,19 +1366,383 @@ var __decorate8 = function(decorators, target, key, desc) {
1343
1366
  var __metadata8 = function(k, v) {
1344
1367
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1345
1368
  };
1369
+ var TokenRepository = class TokenRepository2 {
1370
+ static {
1371
+ __name(this, "TokenRepository");
1372
+ }
1373
+ db;
1374
+ schema;
1375
+ get tokens() {
1376
+ return this.schema.tokens;
1377
+ }
1378
+ get users() {
1379
+ return this.schema.users;
1380
+ }
1381
+ /** Shared query helper, scoped to the current database/transaction identity. */
1382
+ queryHelper;
1383
+ get q() {
1384
+ const db = this.db;
1385
+ if (this.queryHelper?.db !== db) {
1386
+ this.queryHelper = { db, queries: new AuthQueries(db, this.schema) };
1387
+ }
1388
+ return this.queryHelper.queries;
1389
+ }
1390
+ /**
1391
+ * Upsert the refresh-token row for a session, keyed on `tokenFamily` (the
1392
+ * per-login session identifier, unique). A brand-new login inserts a fresh
1393
+ * family row; a refresh rotation updates only that family's row, leaving the
1394
+ * user's other sessions untouched.
1395
+ */
1396
+ async storeRefreshToken(tokenData) {
1397
+ return await this.db.insert(this.tokens).values(tokenData).onConflictDoUpdate({
1398
+ target: this.tokens.tokenFamily,
1399
+ set: {
1400
+ token: tokenData.token,
1401
+ expiresAt: tokenData.expiresAt,
1402
+ previousHash: tokenData.previousHash ?? null,
1403
+ previousValidUntil: tokenData.previousValidUntil ?? null,
1404
+ previousUsedAt: tokenData.previousUsedAt ?? null
1405
+ },
1406
+ // A revoked family is a durable tombstone. It must never be revived by
1407
+ // an issuance racing with logout, or after the cache markers are lost.
1408
+ setWhere: and(eq4(this.tokens.status, "active"), eq4(this.tokens.userId, tokenData.userId))
1409
+ }).returning();
1410
+ }
1411
+ /**
1412
+ * Rotate an existing refresh-token family with compare-and-swap semantics.
1413
+ * This can never update a family durably revoked by a concurrent logout.
1414
+ */
1415
+ async rotateRefreshToken(tokenData, expectedCurrentHash) {
1416
+ return await this.db.update(this.tokens).set({
1417
+ token: tokenData.token,
1418
+ expiresAt: tokenData.expiresAt,
1419
+ previousHash: tokenData.previousHash,
1420
+ previousValidUntil: tokenData.previousValidUntil,
1421
+ previousUsedAt: tokenData.previousUsedAt ?? null
1422
+ }).where(and(eq4(this.tokens.tokenFamily, tokenData.tokenFamily), eq4(this.tokens.userId, tokenData.userId), eq4(this.tokens.token, expectedCurrentHash), eq4(this.tokens.status, "active"))).returning();
1423
+ }
1424
+ /**
1425
+ * Claim the previous-token grace slot for a single family. Conditional on
1426
+ * BOTH the stored previousHash still matching the presented token AND
1427
+ * previousUsedAt being NULL. Gating on the hash (not just the flag) closes
1428
+ * the rotation race: the winner's rotation rewrites previousHash via
1429
+ * storeRefreshToken (and resets previousUsedAt to NULL), so a loser whose
1430
+ * UPDATE lands after that rotation no longer matches and gets zero rows —
1431
+ * exactly one caller ever claims the slot.
1432
+ */
1433
+ async markPreviousUsed(tokenFamily, previousHash) {
1434
+ return await this.db.update(this.tokens).set({ previousUsedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.previousHash, previousHash), isNull(this.tokens.previousUsedAt), eq4(this.tokens.status, "active"))).returning();
1435
+ }
1436
+ /** Look up a single session's token row by its family identifier. */
1437
+ async getByFamily(tokenFamily) {
1438
+ const [token] = await this.db.select().from(this.tokens).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.status, "active")));
1439
+ return token ?? null;
1440
+ }
1441
+ /**
1442
+ * Durably revoke one family without depending on physical deletion.
1443
+ *
1444
+ * The row remains as a tombstone until its original refresh expiry. This is
1445
+ * what prevents a later cache loss from turning a failed/omitted cleanup
1446
+ * delete into a valid database-backed recovery session.
1447
+ */
1448
+ async revokeFamily(tokenFamily) {
1449
+ return this.db.update(this.tokens).set({
1450
+ status: "revoked",
1451
+ previousHash: null,
1452
+ previousValidUntil: null,
1453
+ previousUsedAt: null
1454
+ }).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.status, "active"))).returning();
1455
+ }
1456
+ /** Durably revoke every active family for a user. */
1457
+ async revokeAllForUser(userId) {
1458
+ return this.db.update(this.tokens).set({
1459
+ status: "revoked",
1460
+ previousHash: null,
1461
+ previousValidUntil: null,
1462
+ previousUsedAt: null
1463
+ }).where(and(eq4(this.tokens.userId, userId), eq4(this.tokens.status, "active"))).returning();
1464
+ }
1465
+ /**
1466
+ * Opportunistic cleanup: with one row per family (no unique userId), expired
1467
+ * and abandoned sessions accumulate. Delete every expired row.
1468
+ */
1469
+ async deleteExpired() {
1470
+ return this.db.delete(this.tokens).where(lt(this.tokens.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning();
1471
+ }
1472
+ async isUserExists(userId) {
1473
+ const [user] = await this.db.select({ id: this.users.id }).from(this.users).where(eq4(this.users.id, userId)).limit(1);
1474
+ return !!user;
1475
+ }
1476
+ async getRoleNameById(userId) {
1477
+ return this.q.getRoleName(userId);
1478
+ }
1479
+ async getUserPermissions(userId) {
1480
+ return this.q.getUserPermissions(userId);
1481
+ }
1482
+ async getRoleAndPermissions(userId) {
1483
+ return this.q.getRoleAndPermissions(userId);
1484
+ }
1485
+ async getUser(userId) {
1486
+ return await this.q.getUserWithPermissions(eq4(this.users.id, userId)) ?? null;
1487
+ }
1488
+ };
1489
+ __decorate8([
1490
+ DB3(),
1491
+ __metadata8("design:type", Object)
1492
+ ], TokenRepository.prototype, "db", void 0);
1493
+ __decorate8([
1494
+ Inject5(AUTH_SCHEMA),
1495
+ __metadata8("design:type", Object)
1496
+ ], TokenRepository.prototype, "schema", void 0);
1497
+ TokenRepository = __decorate8([
1498
+ Repository3()
1499
+ ], TokenRepository);
1500
+
1501
+ // src/tokens/SessionInvalidationService.ts
1502
+ var __decorate9 = function(decorators, target, key, desc) {
1503
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1504
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1505
+ 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;
1506
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1507
+ };
1508
+ var __metadata9 = function(k, v) {
1509
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1510
+ };
1511
+ var SessionInvalidationService_1;
1512
+ var _a5;
1513
+ var _b3;
1514
+ var SessionInvalidationService = class SessionInvalidationService2 {
1515
+ static {
1516
+ __name(this, "SessionInvalidationService");
1517
+ }
1518
+ static {
1519
+ SessionInvalidationService_1 = this;
1520
+ }
1521
+ cache;
1522
+ tokens;
1523
+ config;
1524
+ constructor(cache2, tokens) {
1525
+ this.cache = cache2;
1526
+ this.tokens = tokens;
1527
+ }
1528
+ /**
1529
+ * Fields whose change ends existing sessions. Everything absent from this set
1530
+ * — display name, avatar, language — is a profile edit and must leave the
1531
+ * user signed in, on every device.
1532
+ */
1533
+ static SECURITY_FIELDS = Object.freeze([
1534
+ "password",
1535
+ "status",
1536
+ "role",
1537
+ "roleId",
1538
+ "email",
1539
+ "emailVerified",
1540
+ "phone"
1541
+ ]);
1542
+ /** Whether an update payload touches anything that must end sessions. */
1543
+ static affectsSecurityState(data) {
1544
+ if (!data)
1545
+ return false;
1546
+ return SessionInvalidationService_1.SECURITY_FIELDS.some((field) => data[field] !== void 0);
1547
+ }
1548
+ get accessTokenTtlMs() {
1549
+ return timestring2(this.config.jwt.accessExpiresIn, "ms");
1550
+ }
1551
+ get refreshTokenTtlMs() {
1552
+ return timestring2(this.config.jwt.refreshExpiresIn, "ms");
1553
+ }
1554
+ sessionVersionKey(userId) {
1555
+ return `auth:session-version:${userId}`;
1556
+ }
1557
+ revokedFamilyKey(tokenFamily) {
1558
+ return `auth:revoked-family:${tokenFamily}`;
1559
+ }
1560
+ /**
1561
+ * Positive liveness marker for one session family.
1562
+ *
1563
+ * The signed session snapshot is authorized against this rather than against
1564
+ * the absence of a revocation marker, so losing the cache cannot make a
1565
+ * logged-out family look valid again: with no marker the fast path simply
1566
+ * declines and the request falls through to the database-backed resolver.
1567
+ */
1568
+ familyKey(tokenFamily) {
1569
+ return `auth:family:${tokenFamily}`;
1570
+ }
1571
+ userCacheKey(userId) {
1572
+ return `auth:user:${userId}`;
1573
+ }
1574
+ parseSessionVersion(raw) {
1575
+ if (!raw)
1576
+ return 0;
1577
+ const parsed = Number(raw);
1578
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
1579
+ }
1580
+ async getSessionVersion(userId) {
1581
+ return this.parseSessionVersion(await this.cache.get(this.sessionVersionKey(userId)));
1582
+ }
1583
+ /**
1584
+ * Extend the version key's lifetime without rewriting its value.
1585
+ *
1586
+ * Token issuance used to `set()` the version it had just read, which meant an
1587
+ * invalidation landing between that read and that write was silently undone —
1588
+ * the revoked version came back and the old tokens verified again. Only the
1589
+ * expiry is touched here, so a concurrent bump always survives.
1590
+ */
1591
+ async touchSessionVersion(userId) {
1592
+ await this.cache.expire(this.sessionVersionKey(userId), this.accessTokenTtlMs);
1593
+ }
1594
+ /**
1595
+ * Invalidate every access token already issued for a user, and drop the
1596
+ * cached user record so the next read sees the new state rather than a stale
1597
+ * snapshot that is merely truthy.
1598
+ *
1599
+ * The bump is an atomic increment, so concurrent invalidations cannot read
1600
+ * the same version and write the same successor back.
1601
+ */
1602
+ async invalidateAccessTokens(userId) {
1603
+ const key = this.sessionVersionKey(userId);
1604
+ const { count } = await this.cache.incr(key, this.accessTokenTtlMs);
1605
+ await this.cache.expire(key, this.accessTokenTtlMs);
1606
+ await this.dropUserCache(userId);
1607
+ return count;
1608
+ }
1609
+ async dropUserCache(userId) {
1610
+ await this.cache.del(this.userCacheKey(userId));
1611
+ }
1612
+ /**
1613
+ * End every session a user holds: access tokens by version, refresh sessions
1614
+ * by row, and each family's liveness marker.
1615
+ *
1616
+ * Callers run this AFTER their database mutation has committed. Running it
1617
+ * before would leave a window in which a concurrent login re-established a
1618
+ * session against the state the mutation was about to remove; running it
1619
+ * after a rollback merely signs the user out again, which is safe.
1620
+ */
1621
+ async invalidateUser(userId) {
1622
+ await this.invalidateAccessTokens(userId);
1623
+ const revoked = await this.tokens.revokeAllForUser(userId);
1624
+ await Promise.all(familiesOf(revoked).map((family) => this.markFamilyRevoked(family)));
1625
+ }
1626
+ /**
1627
+ * Record that a family is live, and whose it is. Called wherever the family's
1628
+ * refresh row is written.
1629
+ *
1630
+ * The marker stores the owning user rather than a bare flag so a reader can
1631
+ * confirm, in the same single lookup, that the family it was handed actually
1632
+ * belongs to the identity claiming it.
1633
+ *
1634
+ * Revocation always wins. A refresh that rotated its row, was descheduled,
1635
+ * and resumed after a logout would otherwise re-mark its family live and
1636
+ * hand the browser back the session it had just ended — the database row is
1637
+ * gone by then, but nothing on the fast path reads the database. So this
1638
+ * writes, then re-reads the revocation marker and withdraws the write if one
1639
+ * appeared. Combined with `markFamilyRevoked` setting the revocation marker
1640
+ * *before* clearing liveness, every interleaving of the two converges on
1641
+ * revoked: whichever of the pair observes the other, the liveness key ends
1642
+ * up deleted.
1643
+ *
1644
+ * @returns whether the family is live after this call.
1645
+ */
1646
+ async markFamilyIssued(tokenFamily, userId) {
1647
+ await this.cache.set(this.familyKey(tokenFamily), userId, this.refreshTokenTtlMs);
1648
+ if (await this.isFamilyRevoked(tokenFamily)) {
1649
+ await this.cache.del(this.familyKey(tokenFamily));
1650
+ return false;
1651
+ }
1652
+ return true;
1653
+ }
1654
+ /**
1655
+ * What one lookup can say about a family, in a single batched cache read.
1656
+ *
1657
+ * The three answers are deliberately distinct. `revoked` is authoritative and
1658
+ * must deny. `unknown` means the cache cannot vouch for the family — it was
1659
+ * evicted, or the cache was lost — and must send the caller to an
1660
+ * authoritative, database-backed check rather than being read either way.
1661
+ * Only `live` is a positive assertion, and only for the named user.
1662
+ */
1663
+ async familyStatus(tokenFamily, userId) {
1664
+ if (!tokenFamily)
1665
+ return "unknown";
1666
+ const [owner, revoked] = await this.readMany([
1667
+ this.familyKey(tokenFamily),
1668
+ this.revokedFamilyKey(tokenFamily)
1669
+ ]);
1670
+ if (revoked != null)
1671
+ return "revoked";
1672
+ if (owner == null)
1673
+ return "unknown";
1674
+ if (userId !== void 0 && owner !== userId)
1675
+ return "revoked";
1676
+ return "live";
1677
+ }
1678
+ /**
1679
+ * Whether a family is positively known to be live, and — when a user is
1680
+ * given — to belong to that user.
1681
+ *
1682
+ * `false` means "not proven live" — revoked, mismatched, or simply not in
1683
+ * cache. Callers must treat it as a reason to fall back to an authoritative
1684
+ * check, never as proof of validity in the other direction.
1685
+ */
1686
+ async isFamilyLive(tokenFamily, userId) {
1687
+ return await this.familyStatus(tokenFamily, userId) === "live";
1688
+ }
1689
+ async readMany(keys) {
1690
+ const cache2 = this.cache;
1691
+ if (cache2.getMany)
1692
+ return cache2.getMany(keys);
1693
+ return Promise.all(keys.map((key) => cache2.get(key)));
1694
+ }
1695
+ /**
1696
+ * Keep revocation through both credential lifetimes. If deleting the refresh
1697
+ * row fails, its still-valid cookie must remain denied after access expires.
1698
+ */
1699
+ async markFamilyRevoked(tokenFamily) {
1700
+ await this.cache.set(this.revokedFamilyKey(tokenFamily), "1", Math.max(this.accessTokenTtlMs, this.refreshTokenTtlMs));
1701
+ await this.cache.del(this.familyKey(tokenFamily));
1702
+ }
1703
+ async isFamilyRevoked(tokenFamily) {
1704
+ return await this.cache.get(this.revokedFamilyKey(tokenFamily)) !== null;
1705
+ }
1706
+ };
1707
+ __decorate9([
1708
+ Inject6(AUTH_CONFIG),
1709
+ __metadata9("design:type", Object)
1710
+ ], SessionInvalidationService.prototype, "config", void 0);
1711
+ SessionInvalidationService = SessionInvalidationService_1 = __decorate9([
1712
+ Injectable5(),
1713
+ __metadata9("design:paramtypes", [typeof (_a5 = typeof CacheService !== "undefined" && CacheService) === "function" ? _a5 : Object, typeof (_b3 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _b3 : Object])
1714
+ ], SessionInvalidationService);
1715
+ function familiesOf(rows) {
1716
+ if (!Array.isArray(rows))
1717
+ return [];
1718
+ return rows.map((row) => row?.tokenFamily).filter((family) => typeof family === "string" && family.length > 0);
1719
+ }
1720
+ __name(familiesOf, "familiesOf");
1721
+
1722
+ // src/users/UserService.ts
1723
+ var __decorate10 = function(decorators, target, key, desc) {
1724
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1725
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1726
+ 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;
1727
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1728
+ };
1729
+ var __metadata10 = function(k, v) {
1730
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1731
+ };
1346
1732
  var __param2 = function(paramIndex, decorator) {
1347
1733
  return function(target, key) {
1348
1734
  decorator(target, key, paramIndex);
1349
1735
  };
1350
1736
  };
1351
- var _a5;
1352
- var _b3;
1737
+ var _a6;
1738
+ var _b4;
1353
1739
  var _c;
1354
1740
  var _d;
1355
1741
  var _e;
1356
1742
  var _f;
1357
1743
  var _g;
1358
1744
  var _h;
1745
+ var _j;
1359
1746
  var E164_PHONE = /^\+[1-9]\d{7,14}$/;
1360
1747
  var UserService = class UserService2 {
1361
1748
  static {
@@ -1368,8 +1755,9 @@ var UserService = class UserService2 {
1368
1755
  encryptionService;
1369
1756
  i18nService;
1370
1757
  authConfig;
1758
+ sessionInvalidation;
1371
1759
  t;
1372
- constructor(roleValidator, roleService, userRepository, userValidator, encryptionService, i18nService, authConfig) {
1760
+ constructor(roleValidator, roleService, userRepository, userValidator, encryptionService, i18nService, authConfig, sessionInvalidation) {
1373
1761
  this.roleValidator = roleValidator;
1374
1762
  this.roleService = roleService;
1375
1763
  this.userRepository = userRepository;
@@ -1377,6 +1765,19 @@ var UserService = class UserService2 {
1377
1765
  this.encryptionService = encryptionService;
1378
1766
  this.i18nService = i18nService;
1379
1767
  this.authConfig = authConfig;
1768
+ this.sessionInvalidation = sessionInvalidation;
1769
+ }
1770
+ /**
1771
+ * End the user's sessions after a security-relevant mutation has committed.
1772
+ *
1773
+ * Deactivating, deleting, or re-roling an account through the generic
1774
+ * endpoints used to leave every already-issued token working until it
1775
+ * expired. Invalidation belongs here, next to the write, so no caller can
1776
+ * forget it — the application-level commands that already revoke keep doing
1777
+ * so, and a second call is harmless.
1778
+ */
1779
+ async invalidateSessions(userId) {
1780
+ await this.sessionInvalidation?.invalidateUser(userId);
1380
1781
  }
1381
1782
  sanitizeUser(user) {
1382
1783
  if (!user)
@@ -1494,15 +1895,23 @@ var UserService = class UserService2 {
1494
1895
  };
1495
1896
  const cleanedUpdateData = clean(updateData);
1496
1897
  const updatedUser = await this.userRepository.update(id, cleanedUpdateData);
1497
- return this.sanitizeUser(this.requireUser(updatedUser));
1898
+ const result = this.sanitizeUser(this.requireUser(updatedUser));
1899
+ if (SessionInvalidationService.affectsSecurityState(cleanedUpdateData)) {
1900
+ await this.invalidateSessions(id);
1901
+ }
1902
+ return result;
1498
1903
  }
1499
1904
  async delete(id) {
1500
1905
  const user = await this.userRepository.delete(id);
1501
- return this.sanitizeUser(this.requireUser(user));
1906
+ const result = this.sanitizeUser(this.requireUser(user));
1907
+ await this.invalidateSessions(id);
1908
+ return result;
1502
1909
  }
1503
1910
  async deleteAll() {
1504
1911
  const deletedUsers = await this.userRepository.deleteAll();
1505
- return this.sanitizeUsers(deletedUsers);
1912
+ const result = this.sanitizeUsers(deletedUsers);
1913
+ await Promise.all(result.map((user) => this.invalidateSessions(user.id)));
1914
+ return result;
1506
1915
  }
1507
1916
  async getRoleName(id) {
1508
1917
  await this.userValidator.checkUserExists(id);
@@ -1524,11 +1933,15 @@ var UserService = class UserService2 {
1524
1933
  async assignRole(id, roleId, roleName) {
1525
1934
  const resolvedRoleId = await this.resolveUserRole(roleId, roleName);
1526
1935
  const updatedUser = await this.userRepository.update(id, { roleId: resolvedRoleId });
1527
- return this.sanitizeUser(this.requireUser(updatedUser));
1936
+ const result = this.sanitizeUser(this.requireUser(updatedUser));
1937
+ await this.invalidateSessions(id);
1938
+ return result;
1528
1939
  }
1529
1940
  async removeRole(id) {
1530
1941
  const updatedUser = await this.userRepository.update(id, { roleId: null });
1531
- return this.sanitizeUser(this.requireUser(updatedUser));
1942
+ const result = this.sanitizeUser(this.requireUser(updatedUser));
1943
+ await this.invalidateSessions(id);
1944
+ return result;
1532
1945
  }
1533
1946
  async seedAdminUser(config) {
1534
1947
  if (!config?.email || !config?.password) {
@@ -1563,170 +1976,42 @@ var UserService = class UserService2 {
1563
1976
  return this.i18nService.getCurrentLanguage();
1564
1977
  }
1565
1978
  };
1566
- __decorate8([
1979
+ __decorate10([
1567
1980
  I18n4("users"),
1568
- __metadata8("design:type", Object)
1981
+ __metadata10("design:type", Object)
1569
1982
  ], UserService.prototype, "t", void 0);
1570
- __decorate8([
1983
+ __decorate10([
1571
1984
  Transaction(),
1572
- __metadata8("design:type", Function),
1573
- __metadata8("design:paramtypes", [typeof (_g = typeof Record !== "undefined" && Record) === "function" ? _g : Object, Object]),
1574
- __metadata8("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object)
1985
+ __metadata10("design:type", Function),
1986
+ __metadata10("design:paramtypes", [typeof (_h = typeof Record !== "undefined" && Record) === "function" ? _h : Object, Object]),
1987
+ __metadata10("design:returntype", typeof (_j = typeof Promise !== "undefined" && Promise) === "function" ? _j : Object)
1575
1988
  ], UserService.prototype, "create", null);
1576
- UserService = __decorate8([
1577
- Injectable5(),
1578
- __param2(6, Inject5(AUTH_CONFIG)),
1579
- __metadata8("design:paramtypes", [typeof (_a5 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _a5 : Object, typeof (_b3 = typeof RoleService !== "undefined" && RoleService) === "function" ? _b3 : Object, typeof (_c = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _c : Object, typeof (_d = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _d : Object, typeof (_e = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _e : Object, typeof (_f = typeof I18nService !== "undefined" && I18nService) === "function" ? _f : Object, Object])
1989
+ UserService = __decorate10([
1990
+ Injectable6(),
1991
+ __param2(6, Inject7(AUTH_CONFIG)),
1992
+ __metadata10("design:paramtypes", [typeof (_a6 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _a6 : Object, typeof (_b4 = typeof RoleService !== "undefined" && RoleService) === "function" ? _b4 : Object, typeof (_c = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _c : Object, typeof (_d = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _d : Object, typeof (_e = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _e : Object, typeof (_f = typeof I18nService !== "undefined" && I18nService) === "function" ? _f : Object, Object, typeof (_g = typeof SessionInvalidationService !== "undefined" && SessionInvalidationService) === "function" ? _g : Object])
1580
1993
  ], UserService);
1581
1994
 
1582
1995
  // src/tokens/TokenService.ts
1583
- import { Injectable as Injectable6, Inject as Inject8 } from "najm-core";
1996
+ import { Injectable as Injectable7, Inject as Inject9 } from "najm-core";
1584
1997
  import { I18n as I18n5 } from "najm-i18n";
1585
- import { CacheService } from "najm-cache";
1998
+ import { CacheService as CacheService2 } from "najm-cache";
1586
1999
  import { createHash } from "crypto";
1587
2000
  import jwt from "jsonwebtoken";
1588
2001
  import { nanoid as nanoid4 } from "nanoid";
1589
-
1590
- // src/tokens/TokenRepository.ts
1591
- import { and, eq as eq4, isNull, lt } from "drizzle-orm";
1592
- import { Repository as Repository3, Inject as Inject6 } from "najm-core";
1593
- import { DB as DB3 } from "najm-database";
1594
- var __decorate9 = function(decorators, target, key, desc) {
1595
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1596
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1597
- 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;
1598
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1599
- };
1600
- var __metadata9 = function(k, v) {
1601
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1602
- };
1603
- var TokenRepository = class TokenRepository2 {
1604
- static {
1605
- __name(this, "TokenRepository");
1606
- }
1607
- db;
1608
- schema;
1609
- get tokens() {
1610
- return this.schema.tokens;
1611
- }
1612
- get users() {
1613
- return this.schema.users;
1614
- }
1615
- /** Shared query helper, scoped to the current database/transaction identity. */
1616
- queryHelper;
1617
- get q() {
1618
- const db = this.db;
1619
- if (this.queryHelper?.db !== db) {
1620
- this.queryHelper = { db, queries: new AuthQueries(db, this.schema) };
1621
- }
1622
- return this.queryHelper.queries;
1623
- }
1624
- /**
1625
- * Upsert the refresh-token row for a session, keyed on `tokenFamily` (the
1626
- * per-login session identifier, unique). A brand-new login inserts a fresh
1627
- * family row; a refresh rotation updates only that family's row, leaving the
1628
- * user's other sessions untouched.
1629
- */
1630
- async storeRefreshToken(tokenData) {
1631
- return await this.db.insert(this.tokens).values(tokenData).onConflictDoUpdate({
1632
- target: this.tokens.tokenFamily,
1633
- set: {
1634
- token: tokenData.token,
1635
- expiresAt: tokenData.expiresAt,
1636
- previousHash: tokenData.previousHash ?? null,
1637
- previousValidUntil: tokenData.previousValidUntil ?? null,
1638
- previousUsedAt: tokenData.previousUsedAt ?? null
1639
- }
1640
- }).returning();
1641
- }
1642
- /**
1643
- * Rotate an existing refresh-token family with compare-and-swap semantics.
1644
- * This can never insert a family deleted by a concurrent logout.
1645
- */
1646
- async rotateRefreshToken(tokenData, expectedCurrentHash) {
1647
- return await this.db.update(this.tokens).set({
1648
- token: tokenData.token,
1649
- expiresAt: tokenData.expiresAt,
1650
- previousHash: tokenData.previousHash,
1651
- previousValidUntil: tokenData.previousValidUntil,
1652
- previousUsedAt: tokenData.previousUsedAt ?? null
1653
- }).where(and(eq4(this.tokens.tokenFamily, tokenData.tokenFamily), eq4(this.tokens.userId, tokenData.userId), eq4(this.tokens.token, expectedCurrentHash))).returning();
1654
- }
1655
- /**
1656
- * Claim the previous-token grace slot for a single family. Conditional on
1657
- * BOTH the stored previousHash still matching the presented token AND
1658
- * previousUsedAt being NULL. Gating on the hash (not just the flag) closes
1659
- * the rotation race: the winner's rotation rewrites previousHash via
1660
- * storeRefreshToken (and resets previousUsedAt to NULL), so a loser whose
1661
- * UPDATE lands after that rotation no longer matches and gets zero rows —
1662
- * exactly one caller ever claims the slot.
1663
- */
1664
- async markPreviousUsed(tokenFamily, previousHash) {
1665
- return await this.db.update(this.tokens).set({ previousUsedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(eq4(this.tokens.tokenFamily, tokenFamily), eq4(this.tokens.previousHash, previousHash), isNull(this.tokens.previousUsedAt))).returning();
1666
- }
1667
- /** Look up a single session's token row by its family identifier. */
1668
- async getByFamily(tokenFamily) {
1669
- const [token] = await this.db.select().from(this.tokens).where(eq4(this.tokens.tokenFamily, tokenFamily));
1670
- return token ?? null;
1671
- }
1672
- /** Revoke a single session (one family). */
1673
- async revokeFamily(tokenFamily) {
1674
- return this.db.delete(this.tokens).where(eq4(this.tokens.tokenFamily, tokenFamily)).returning();
1675
- }
1676
- /** Revoke every session for a user (password change/reset, logout-all). */
1677
- async revokeAllForUser(userId) {
1678
- return this.db.delete(this.tokens).where(eq4(this.tokens.userId, userId)).returning();
1679
- }
1680
- /**
1681
- * Opportunistic cleanup: with one row per family (no unique userId), expired
1682
- * and abandoned sessions accumulate. Delete every expired row.
1683
- */
1684
- async deleteExpired() {
1685
- return this.db.delete(this.tokens).where(lt(this.tokens.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning();
1686
- }
1687
- async isUserExists(userId) {
1688
- const [user] = await this.db.select({ id: this.users.id }).from(this.users).where(eq4(this.users.id, userId)).limit(1);
1689
- return !!user;
1690
- }
1691
- async getRoleNameById(userId) {
1692
- return this.q.getRoleName(userId);
1693
- }
1694
- async getUserPermissions(userId) {
1695
- return this.q.getUserPermissions(userId);
1696
- }
1697
- async getRoleAndPermissions(userId) {
1698
- return this.q.getRoleAndPermissions(userId);
1699
- }
1700
- async getUser(userId) {
1701
- return await this.q.getUserWithPermissions(eq4(this.users.id, userId)) ?? null;
1702
- }
1703
- };
1704
- __decorate9([
1705
- DB3(),
1706
- __metadata9("design:type", Object)
1707
- ], TokenRepository.prototype, "db", void 0);
1708
- __decorate9([
1709
- Inject6(AUTH_SCHEMA),
1710
- __metadata9("design:type", Object)
1711
- ], TokenRepository.prototype, "schema", void 0);
1712
- TokenRepository = __decorate9([
1713
- Repository3()
1714
- ], TokenRepository);
1715
-
1716
- // src/tokens/TokenService.ts
1717
- import timestring2 from "timestring";
2002
+ import timestring3 from "timestring";
1718
2003
 
1719
2004
  // src/credentialSetup/CredentialSetupRequirementRepository.ts
1720
2005
  import { and as and2, eq as eq5 } from "drizzle-orm";
1721
- import { Err as Err6, Inject as Inject7, Repository as Repository4 } from "najm-core";
2006
+ import { Err as Err6, Inject as Inject8, Repository as Repository4 } from "najm-core";
1722
2007
  import { DB as DB4 } from "najm-database";
1723
- var __decorate10 = function(decorators, target, key, desc) {
2008
+ var __decorate11 = function(decorators, target, key, desc) {
1724
2009
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1725
2010
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1726
2011
  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;
1727
2012
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1728
2013
  };
1729
- var __metadata10 = function(k, v) {
2014
+ var __metadata11 = function(k, v) {
1730
2015
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1731
2016
  };
1732
2017
  var CredentialSetupRequirementRepository = class CredentialSetupRequirementRepository2 {
@@ -1774,15 +2059,15 @@ var CredentialSetupRequirementRepository = class CredentialSetupRequirementRepos
1774
2059
  return requirement;
1775
2060
  }
1776
2061
  };
1777
- __decorate10([
2062
+ __decorate11([
1778
2063
  DB4(),
1779
- __metadata10("design:type", Object)
2064
+ __metadata11("design:type", Object)
1780
2065
  ], CredentialSetupRequirementRepository.prototype, "db", void 0);
1781
- __decorate10([
1782
- Inject7(AUTH_SCHEMA),
1783
- __metadata10("design:type", Object)
2066
+ __decorate11([
2067
+ Inject8(AUTH_SCHEMA),
2068
+ __metadata11("design:type", Object)
1784
2069
  ], CredentialSetupRequirementRepository.prototype, "schema", void 0);
1785
- CredentialSetupRequirementRepository = __decorate10([
2070
+ CredentialSetupRequirementRepository = __decorate11([
1786
2071
  Repository4()
1787
2072
  ], CredentialSetupRequirementRepository);
1788
2073
 
@@ -1791,20 +2076,21 @@ var PASSWORD_SETUP_PURPOSE = "password";
1791
2076
 
1792
2077
  // src/tokens/TokenService.ts
1793
2078
  import { Err as Err7 } from "najm-core";
1794
- var __decorate11 = function(decorators, target, key, desc) {
2079
+ var __decorate12 = function(decorators, target, key, desc) {
1795
2080
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1796
2081
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1797
2082
  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;
1798
2083
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1799
2084
  };
1800
- var __metadata11 = function(k, v) {
2085
+ var __metadata12 = function(k, v) {
1801
2086
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1802
2087
  };
1803
2088
  var TokenService_1;
1804
- var _a6;
1805
- var _b4;
2089
+ var _a7;
2090
+ var _b5;
1806
2091
  var _c2;
1807
2092
  var _d2;
2093
+ var _e2;
1808
2094
  var TokenService = class TokenService2 {
1809
2095
  static {
1810
2096
  __name(this, "TokenService");
@@ -1816,13 +2102,23 @@ var TokenService = class TokenService2 {
1816
2102
  cookieManager;
1817
2103
  cache;
1818
2104
  credentialSetupRequirements;
2105
+ sessions;
1819
2106
  config;
1820
2107
  t;
1821
- constructor(tokenRepository, cookieManager, cache2, credentialSetupRequirements) {
2108
+ constructor(tokenRepository, cookieManager, cache2, credentialSetupRequirements, sessions) {
1822
2109
  this.tokenRepository = tokenRepository;
1823
2110
  this.cookieManager = cookieManager;
1824
2111
  this.cache = cache2;
1825
2112
  this.credentialSetupRequirements = credentialSetupRequirements;
2113
+ this.sessions = sessions;
2114
+ }
2115
+ /** The shared invalidation contract — see SessionInvalidationService. */
2116
+ get invalidation() {
2117
+ if (!this.sessions) {
2118
+ this.sessions = new SessionInvalidationService(this.cache, this.tokenRepository);
2119
+ this.sessions.config = this.config;
2120
+ }
2121
+ return this.sessions;
1826
2122
  }
1827
2123
  /**
1828
2124
  * Get blacklist key prefix
@@ -1833,17 +2129,11 @@ var TokenService = class TokenService2 {
1833
2129
  get resetTokenPrefix() {
1834
2130
  return "auth:reset:";
1835
2131
  }
1836
- get sessionVersionPrefix() {
1837
- return "auth:session-version:";
1838
- }
1839
2132
  sessionVersionKey(userId) {
1840
- return `${this.sessionVersionPrefix}${userId}`;
1841
- }
1842
- accessTokenTtlMs() {
1843
- return timestring2(this.config.jwt.accessExpiresIn, "ms");
2133
+ return this.invalidation.sessionVersionKey(userId);
1844
2134
  }
1845
2135
  expiresAt(expiresIn) {
1846
- return Math.floor((Date.now() + timestring2(expiresIn, "ms")) / 1e3);
2136
+ return Math.floor((Date.now() + timestring3(expiresIn, "ms")) / 1e3);
1847
2137
  }
1848
2138
  async getCacheValues(keys) {
1849
2139
  const cache2 = this.cache;
@@ -1852,10 +2142,7 @@ var TokenService = class TokenService2 {
1852
2142
  return Promise.all(keys.map((key) => cache2.get(key)));
1853
2143
  }
1854
2144
  parseSessionVersion(raw) {
1855
- if (!raw)
1856
- return 0;
1857
- const parsed = Number(raw);
1858
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
2145
+ return this.invalidation.parseSessionVersion(raw);
1859
2146
  }
1860
2147
  // ============ TOKEN VALIDATION ============
1861
2148
  extractAccessToken(authorization) {
@@ -1877,18 +2164,23 @@ var TokenService = class TokenService2 {
1877
2164
  }
1878
2165
  const sessionKey = this.sessionVersionKey(payload.userId);
1879
2166
  const blacklistKey = payload.jti ? `${this.blacklistPrefix}${payload.jti}` : null;
1880
- const familyKey = payload.tokenFamily ? this.revokedFamilyKey(payload.tokenFamily) : null;
2167
+ const revokedKey = payload.tokenFamily ? this.revokedFamilyKey(payload.tokenFamily) : null;
2168
+ const liveKey = payload.tokenFamily ? this.invalidation.familyKey(payload.tokenFamily) : null;
1881
2169
  const keys = [
1882
2170
  ...blacklistKey ? [blacklistKey] : [],
1883
2171
  sessionKey,
1884
- ...familyKey ? [familyKey] : []
2172
+ ...revokedKey ? [revokedKey] : [],
2173
+ ...liveKey ? [liveKey] : []
1885
2174
  ];
1886
2175
  const values = await this.getCacheValues(keys);
1887
2176
  const valueByKey = new Map(keys.map((key, i) => [key, values[i]]));
1888
2177
  if (blacklistKey && valueByKey.get(blacklistKey) != null) {
1889
2178
  Err7(this.t("errors.tokenRevoked"), 401);
1890
2179
  }
1891
- if (familyKey && valueByKey.get(familyKey) != null) {
2180
+ if (revokedKey && valueByKey.get(revokedKey) != null) {
2181
+ Err7(this.t("errors.tokenRevoked"), 401);
2182
+ }
2183
+ if (!liveKey || valueByKey.get(liveKey) !== payload.userId) {
1892
2184
  Err7(this.t("errors.tokenRevoked"), 401);
1893
2185
  }
1894
2186
  const activeSessionVersion = this.parseSessionVersion(valueByKey.get(sessionKey) ?? null);
@@ -1922,6 +2214,11 @@ var TokenService = class TokenService2 {
1922
2214
  this.clearRefreshSessionCookies();
1923
2215
  Err7(this.t(messageKey), 401);
1924
2216
  }
2217
+ async assertRefreshFamilyAllowed(tokenFamily, userId) {
2218
+ if (await this.invalidation.familyStatus(tokenFamily, userId) === "revoked") {
2219
+ this.rejectRefreshSession();
2220
+ }
2221
+ }
1925
2222
  readRefreshSessionCookie() {
1926
2223
  const refreshToken = this.cookieManager.getRefreshToken();
1927
2224
  if (!refreshToken) {
@@ -1948,6 +2245,7 @@ var TokenService = class TokenService2 {
1948
2245
  async resolveRefreshSessionFromCookie() {
1949
2246
  const { refreshToken, userId, tokenFamily } = this.readRefreshSessionCookie();
1950
2247
  const stored = await this.tokenRepository.getByFamily(tokenFamily);
2248
+ await this.assertRefreshFamilyAllowed(tokenFamily, userId);
1951
2249
  if (!stored || stored.userId !== userId) {
1952
2250
  this.rejectRefreshSession();
1953
2251
  }
@@ -1979,7 +2277,8 @@ var TokenService = class TokenService2 {
1979
2277
  user,
1980
2278
  roles: user.role ? [user.role] : [],
1981
2279
  permissions: Array.isArray(user.permissions) ? user.permissions : [],
1982
- sessionVersion
2280
+ sessionVersion,
2281
+ tokenFamily
1983
2282
  };
1984
2283
  }
1985
2284
  // ============ USER RETRIEVAL (MAIN METHOD) ============
@@ -1988,7 +2287,26 @@ var TokenService = class TokenService2 {
1988
2287
  return null;
1989
2288
  const token = this.extractAccessToken(auth2);
1990
2289
  const { userId } = await this.verifyAccessToken(token);
1991
- return this.getUserById(userId);
2290
+ return this.requireActiveUser(await this.getUserById(userId));
2291
+ }
2292
+ /**
2293
+ * A user record is only an authorization if the account is still usable.
2294
+ *
2295
+ * A valid signature and an unrevoked version say the *token* is intact; they
2296
+ * say nothing about whether the account behind it was since deactivated or
2297
+ * deleted. Session invalidation is what normally ends such a token, but this
2298
+ * check is what makes a truthy cached record insufficient on its own — so a
2299
+ * missed invalidation, or a record filled into cache moments before the
2300
+ * change, still cannot authorize a request.
2301
+ */
2302
+ requireActiveUser(user) {
2303
+ if (!user) {
2304
+ Err7(this.t("errors.tokenVerificationFailed"), 401);
2305
+ }
2306
+ if (user.status !== void 0 && user.status !== "active") {
2307
+ Err7(this.t("errors.accountInactive"), 403);
2308
+ }
2309
+ return user;
1992
2310
  }
1993
2311
  async getUserById(userId) {
1994
2312
  const cacheKey = `auth:user:${userId}`;
@@ -2018,7 +2336,7 @@ var TokenService = class TokenService2 {
2018
2336
  const sessionVersion = await this.getUserSessionVersion(data.userId);
2019
2337
  const expiresAt = this.expiresAt(this.config.jwt.accessExpiresIn);
2020
2338
  if (sessionVersion > 0) {
2021
- await this.cache.set(this.sessionVersionKey(data.userId), String(sessionVersion), this.accessTokenTtlMs());
2339
+ await this.invalidation.touchSessionVersion(data.userId);
2022
2340
  }
2023
2341
  const token = jwt.sign({ ...data, jti, sessionVersion, exp: expiresAt }, this.config.jwt.accessSecret);
2024
2342
  return { token, expiresAt, sessionVersion };
@@ -2031,9 +2349,24 @@ var TokenService = class TokenService2 {
2031
2349
  async getSessionVersion(userId) {
2032
2350
  return this.getUserSessionVersion(userId);
2033
2351
  }
2352
+ /**
2353
+ * Whether one session family is positively known to be live.
2354
+ *
2355
+ * `false` means "not proven live" — logged out, or simply not in cache — and
2356
+ * is a reason to fall back to an authoritative check, never on its own a
2357
+ * reason to treat a session as valid.
2358
+ */
2359
+ async isSessionFamilyLive(tokenFamily, userId) {
2360
+ return await this.invalidation.familyStatus(tokenFamily, userId) === "live";
2361
+ }
2034
2362
  /**
2035
2363
  * Generate access token with unique jti for blacklist support.
2036
2364
  * Includes roles/permissions for client-side RBAC/PBAC.
2365
+ *
2366
+ * The token only verifies while its `tokenFamily` is a live session — see
2367
+ * verifyAccessToken. A token minted without one, or for a family that has
2368
+ * been revoked, is refused by design rather than trusted on its signature.
2369
+ * Use generateTokens() to establish a family.
2037
2370
  */
2038
2371
  async generateAccessToken(data) {
2039
2372
  return (await this.signAccessToken(data)).token;
@@ -2118,12 +2451,13 @@ var TokenService = class TokenService2 {
2118
2451
  * This prevents token theft in case of database breach
2119
2452
  */
2120
2453
  async storeRefreshToken(userId, refreshToken, tokenFamily) {
2121
- const expireInSecond = timestring2(this.config.jwt.refreshExpiresIn, "s");
2454
+ await this.assertRefreshFamilyAllowed(tokenFamily, userId);
2455
+ const expireInSecond = timestring3(this.config.jwt.refreshExpiresIn, "s");
2122
2456
  const hashedToken = this.hashToken(refreshToken);
2123
2457
  const existing = await this.tokenRepository.getByFamily(tokenFamily);
2124
2458
  const previousHash = existing?.token ?? null;
2125
2459
  const previousValidUntil = previousHash ? new Date(Date.now() + TokenService_1.PREVIOUS_GRACE_SECONDS * 1e3).toISOString() : null;
2126
- await this.tokenRepository.storeRefreshToken({
2460
+ const stored = await this.tokenRepository.storeRefreshToken({
2127
2461
  userId,
2128
2462
  token: hashedToken,
2129
2463
  tokenFamily,
@@ -2132,6 +2466,12 @@ var TokenService = class TokenService2 {
2132
2466
  previousValidUntil,
2133
2467
  previousUsedAt: null
2134
2468
  });
2469
+ if (!stored?.length) {
2470
+ this.rejectRefreshSession();
2471
+ }
2472
+ if (!await this.invalidation.markFamilyIssued(tokenFamily, userId)) {
2473
+ this.rejectRefreshSession();
2474
+ }
2135
2475
  }
2136
2476
  /**
2137
2477
  * Rotate only the family row observed by refreshTokens(). This conditional
@@ -2139,7 +2479,7 @@ var TokenService = class TokenService2 {
2139
2479
  */
2140
2480
  async rotateTokens(userId, tokenFamily, expectedCurrentHash) {
2141
2481
  const generated = await this.createTokenPair(userId, tokenFamily);
2142
- const expireInSecond = timestring2(this.config.jwt.refreshExpiresIn, "s");
2482
+ const expireInSecond = timestring3(this.config.jwt.refreshExpiresIn, "s");
2143
2483
  const rotated = await this.tokenRepository.rotateRefreshToken({
2144
2484
  userId,
2145
2485
  token: this.hashToken(generated.refreshToken),
@@ -2152,6 +2492,9 @@ var TokenService = class TokenService2 {
2152
2492
  if (!rotated?.length) {
2153
2493
  Err7(this.t("errors.refreshTokenInvalid"), 401);
2154
2494
  }
2495
+ if (!await this.invalidation.markFamilyIssued(tokenFamily, userId)) {
2496
+ this.rejectRefreshSession();
2497
+ }
2155
2498
  return generated;
2156
2499
  }
2157
2500
  /**
@@ -2161,6 +2504,7 @@ var TokenService = class TokenService2 {
2161
2504
  async refreshTokens() {
2162
2505
  const { refreshToken, userId, tokenFamily } = this.readRefreshSessionCookie();
2163
2506
  const stored = await this.tokenRepository.getByFamily(tokenFamily);
2507
+ await this.assertRefreshFamilyAllowed(tokenFamily, userId);
2164
2508
  if (!stored || stored.userId !== userId) {
2165
2509
  this.rejectRefreshSession();
2166
2510
  }
@@ -2196,16 +2540,21 @@ var TokenService = class TokenService2 {
2196
2540
  }
2197
2541
  /** Revoke every refresh session for a user (password change/reset, logout-all). */
2198
2542
  async revokeAllForUser(userId) {
2199
- return this.tokenRepository.revokeAllForUser(userId);
2543
+ const revoked = await this.tokenRepository.revokeAllForUser(userId);
2544
+ if (Array.isArray(revoked)) {
2545
+ await Promise.all(revoked.map((row) => row?.tokenFamily).filter((family) => typeof family === "string" && !!family).map((family) => this.invalidation.markFamilyRevoked(family)));
2546
+ }
2547
+ return revoked;
2200
2548
  }
2201
2549
  /** Revoke a single refresh session (one family). */
2202
2550
  async revokeFamily(tokenFamily) {
2203
- await this.markFamilyRevoked(tokenFamily);
2551
+ await this.invalidation.markFamilyRevoked(tokenFamily);
2204
2552
  return this.tokenRepository.revokeFamily(tokenFamily);
2205
2553
  }
2206
2554
  /**
2207
2555
  * Opportunistic cleanup of expired/abandoned sessions. With one row per
2208
- * family (no unique userId), abandoned logins would otherwise accumulate.
2556
+ * family (no unique userId), expired live rows and revocation tombstones
2557
+ * would otherwise accumulate.
2209
2558
  * Best-effort — never let cleanup failure break the calling flow.
2210
2559
  */
2211
2560
  async deleteExpiredSessions() {
@@ -2215,10 +2564,7 @@ var TokenService = class TokenService2 {
2215
2564
  }
2216
2565
  }
2217
2566
  async invalidateUserAccessTokens(userId) {
2218
- const nextVersion = await this.getUserSessionVersion(userId) + 1;
2219
- await this.cache.set(this.sessionVersionKey(userId), String(nextVersion), this.accessTokenTtlMs());
2220
- await this.cache.del(`auth:user:${userId}`);
2221
- return nextVersion;
2567
+ return this.invalidation.invalidateAccessTokens(userId);
2222
2568
  }
2223
2569
  async getUserFromCookie() {
2224
2570
  const userId = await this.resolveUserFromCookie();
@@ -2226,27 +2572,16 @@ var TokenService = class TokenService2 {
2226
2572
  if (!user) {
2227
2573
  Err7(this.t("errors.refreshTokenInvalid"), 401);
2228
2574
  }
2229
- return user;
2230
- }
2231
- get revokedFamilyPrefix() {
2232
- return "auth:revoked-family:";
2575
+ return this.requireActiveUser(user);
2233
2576
  }
2234
2577
  revokedFamilyKey(tokenFamily) {
2235
- return `${this.revokedFamilyPrefix}${tokenFamily}`;
2236
- }
2237
- /**
2238
- * Mark a family as revoked in cache for the access-token TTL, so every
2239
- * access token minted for that family (not just the presented one) is
2240
- * rejected by verifyAccessToken until it would have expired anyway.
2241
- */
2242
- async markFamilyRevoked(tokenFamily) {
2243
- await this.cache.set(this.revokedFamilyKey(tokenFamily), "1", this.accessTokenTtlMs());
2578
+ return this.invalidation.revokedFamilyKey(tokenFamily);
2244
2579
  }
2245
2580
  /**
2246
2581
  * Revoke only the suspect family — NOT the whole user. Bumping the global
2247
2582
  * per-user session version here would kill every device's access tokens on a
2248
- * single family's reuse detection. Instead drop the family's refresh row and
2249
- * mark the family revoked so its access tokens stop verifying.
2583
+ * single family's reuse detection. Instead durably mark the family revoked
2584
+ * so database recovery and its access tokens both stop verifying.
2250
2585
  */
2251
2586
  async revokeSuspectRefreshFamily(userId, tokenFamily) {
2252
2587
  if (tokenFamily) {
@@ -2258,7 +2593,7 @@ var TokenService = class TokenService2 {
2258
2593
  }
2259
2594
  /**
2260
2595
  * Logout the CURRENT session only — blacklist the presented access token,
2261
- * mark its family revoked, and delete that family's refresh row. Other
2596
+ * mark its family revoked in cache and durably in the token row. Other
2262
2597
  * devices/sessions for the same user keep working. Use a password change or
2263
2598
  * reset (revoke-all) to terminate every session.
2264
2599
  *
@@ -2339,7 +2674,7 @@ var TokenService = class TokenService2 {
2339
2674
  const token = jwt.sign(data, this.config.jwt.refreshSecret, {
2340
2675
  expiresIn
2341
2676
  });
2342
- await this.cache.set(`${this.resetTokenPrefix}${userId}`, jti, timestring2(expiresIn, "ms"));
2677
+ await this.cache.set(`${this.resetTokenPrefix}${userId}`, jti, timestring3(expiresIn, "ms"));
2343
2678
  return { token, userId };
2344
2679
  }
2345
2680
  /**
@@ -2358,10 +2693,22 @@ var TokenService = class TokenService2 {
2358
2693
  return this.generateSetPasswordToken(userId, "invite", "3d");
2359
2694
  }
2360
2695
  /**
2361
- * Verify password reset token
2362
- * Returns userId if valid, throws error if expired/invalid
2696
+ * Verify and CONSUME a password reset or invite token.
2697
+ *
2698
+ * Consumption is a single atomic compare-and-delete, so exactly one of any
2699
+ * number of concurrent callers holding the same link is told to proceed. The
2700
+ * earlier `get()` then `del()` pair left a window in which two callers both
2701
+ * read the same jti, both passed, and both went on to set a password.
2702
+ *
2703
+ * The comparison also means a stale token cannot delete the jti of a newer
2704
+ * one that superseded it — the newer link keeps working.
2705
+ *
2706
+ * Callers must finish validating the replacement password BEFORE calling
2707
+ * this: consumption is deliberately irreversible, so a token burned by a
2708
+ * request that then failed validation would cost the user their link for
2709
+ * nothing.
2363
2710
  */
2364
- async verifyResetToken(token) {
2711
+ async consumeSetPasswordToken(token) {
2365
2712
  let decoded;
2366
2713
  try {
2367
2714
  decoded = jwt.verify(token, this.config.jwt.refreshSecret);
@@ -2371,40 +2718,53 @@ var TokenService = class TokenService2 {
2371
2718
  if (decoded.type !== "reset" && decoded.type !== "invite" || !decoded.jti) {
2372
2719
  Err7(this.t("errors.invalidResetToken"));
2373
2720
  }
2721
+ const consume = this.cache.compareAndDelete;
2722
+ if (typeof consume !== "function") {
2723
+ Err7.invalidOperation("Password reset requires a cache with atomic compare-and-delete");
2724
+ }
2374
2725
  const key = `${this.resetTokenPrefix}${decoded.userId}`;
2375
- const storedJti = await this.cache.get(key);
2376
- if (!storedJti || storedJti !== decoded.jti) {
2726
+ if (!await consume.call(this.cache, key, decoded.jti)) {
2377
2727
  Err7(this.t("errors.invalidResetToken"));
2378
2728
  }
2379
- await this.cache.del(key);
2380
- return decoded.userId;
2729
+ return {
2730
+ userId: decoded.userId,
2731
+ type: decoded.type
2732
+ };
2733
+ }
2734
+ /**
2735
+ * Backward-compatible user-id-only reset/invite token consumption.
2736
+ * Prefer `consumeSetPasswordToken()` when the caller must distinguish an
2737
+ * account invitation from an ordinary password reset.
2738
+ */
2739
+ async verifyResetToken(token) {
2740
+ return (await this.consumeSetPasswordToken(token)).userId;
2381
2741
  }
2382
2742
  async getUserSessionVersion(userId) {
2383
- return this.parseSessionVersion(await this.cache.get(this.sessionVersionKey(userId)));
2743
+ return this.invalidation.getSessionVersion(userId);
2384
2744
  }
2385
2745
  };
2386
- __decorate11([
2387
- Inject8(AUTH_CONFIG),
2388
- __metadata11("design:type", Object)
2746
+ __decorate12([
2747
+ Inject9(AUTH_CONFIG),
2748
+ __metadata12("design:type", Object)
2389
2749
  ], TokenService.prototype, "config", void 0);
2390
- __decorate11([
2750
+ __decorate12([
2391
2751
  I18n5("auth"),
2392
- __metadata11("design:type", Object)
2752
+ __metadata12("design:type", Object)
2393
2753
  ], TokenService.prototype, "t", void 0);
2394
- TokenService = TokenService_1 = __decorate11([
2395
- Injectable6(),
2396
- __metadata11("design:paramtypes", [typeof (_a6 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _a6 : Object, typeof (_b4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _b4 : Object, typeof (_c2 = typeof CacheService !== "undefined" && CacheService) === "function" ? _c2 : Object, typeof (_d2 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _d2 : Object])
2754
+ TokenService = TokenService_1 = __decorate12([
2755
+ Injectable7(),
2756
+ __metadata12("design:paramtypes", [typeof (_a7 = typeof TokenRepository !== "undefined" && TokenRepository) === "function" ? _a7 : Object, typeof (_b5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _b5 : Object, typeof (_c2 = typeof CacheService2 !== "undefined" && CacheService2) === "function" ? _c2 : Object, typeof (_d2 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _d2 : Object, typeof (_e2 = typeof SessionInvalidationService !== "undefined" && SessionInvalidationService) === "function" ? _e2 : Object])
2397
2757
  ], TokenService);
2398
2758
 
2399
2759
  // src/auth/AuthService.ts
2400
- import timestring3 from "timestring";
2760
+ import timestring4 from "timestring";
2401
2761
 
2402
2762
  // src/auth/AuthSessionService.ts
2403
- import { Injectable as Injectable8 } from "najm-core";
2763
+ import { Injectable as Injectable9 } from "najm-core";
2404
2764
  import { Err as Err9 } from "najm-core";
2405
2765
 
2406
2766
  // src/credentialSetup/CredentialSetupRequirementService.ts
2407
- import { Injectable as Injectable7 } from "najm-core";
2767
+ import { Injectable as Injectable8 } from "najm-core";
2408
2768
  import { Transaction as Transaction2 } from "najm-database";
2409
2769
 
2410
2770
  // src/identity/temporaryCredential.ts
@@ -2476,17 +2836,17 @@ function normalizeSetupPurpose(purpose) {
2476
2836
  __name(normalizeSetupPurpose, "normalizeSetupPurpose");
2477
2837
 
2478
2838
  // src/credentialSetup/CredentialSetupRequirementService.ts
2479
- var __decorate12 = function(decorators, target, key, desc) {
2839
+ var __decorate13 = function(decorators, target, key, desc) {
2480
2840
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2481
2841
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2482
2842
  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;
2483
2843
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2484
2844
  };
2485
- var __metadata12 = function(k, v) {
2845
+ var __metadata13 = function(k, v) {
2486
2846
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2487
2847
  };
2488
- var _a7;
2489
- var _b5;
2848
+ var _a8;
2849
+ var _b6;
2490
2850
  var _c3;
2491
2851
  var CredentialSetupRequirementService = class CredentialSetupRequirementService2 {
2492
2852
  static {
@@ -2526,15 +2886,15 @@ var CredentialSetupRequirementService = class CredentialSetupRequirementService2
2526
2886
  return this.repository.complete(userId, normalizeSetupPurpose(purpose));
2527
2887
  }
2528
2888
  };
2529
- __decorate12([
2889
+ __decorate13([
2530
2890
  Transaction2({ retries: 2 }),
2531
- __metadata12("design:type", Function),
2532
- __metadata12("design:paramtypes", [String, String, Object]),
2533
- __metadata12("design:returntype", typeof (_c3 = typeof Promise !== "undefined" && Promise) === "function" ? _c3 : Object)
2891
+ __metadata13("design:type", Function),
2892
+ __metadata13("design:paramtypes", [String, String, Object]),
2893
+ __metadata13("design:returntype", typeof (_c3 = typeof Promise !== "undefined" && Promise) === "function" ? _c3 : Object)
2534
2894
  ], CredentialSetupRequirementService.prototype, "markRequired", null);
2535
- CredentialSetupRequirementService = __decorate12([
2536
- Injectable7(),
2537
- __metadata12("design:paramtypes", [typeof (_a7 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _a7 : Object, typeof (_b5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b5 : Object])
2895
+ CredentialSetupRequirementService = __decorate13([
2896
+ Injectable8(),
2897
+ __metadata13("design:paramtypes", [typeof (_a8 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _a8 : Object, typeof (_b6 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b6 : Object])
2538
2898
  ], CredentialSetupRequirementService);
2539
2899
 
2540
2900
  // src/credentialSetup/errors.ts
@@ -2560,17 +2920,17 @@ var credentialSetupError = /* @__PURE__ */ __name((code, message, status = 400)
2560
2920
  }, "credentialSetupError");
2561
2921
 
2562
2922
  // src/auth/AuthSessionService.ts
2563
- var __decorate13 = function(decorators, target, key, desc) {
2923
+ var __decorate14 = function(decorators, target, key, desc) {
2564
2924
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2565
2925
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2566
2926
  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;
2567
2927
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2568
2928
  };
2569
- var __metadata13 = function(k, v) {
2929
+ var __metadata14 = function(k, v) {
2570
2930
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2571
2931
  };
2572
- var _a8;
2573
- var _b6;
2932
+ var _a9;
2933
+ var _b7;
2574
2934
  var _c4;
2575
2935
  var _d3;
2576
2936
  var AuthSessionService = class AuthSessionService2 {
@@ -2598,7 +2958,7 @@ var AuthSessionService = class AuthSessionService2 {
2598
2958
  const generated = await this.tokenService.generateTokens(user.id);
2599
2959
  this.cookieManager.setRefreshToken(generated.refreshToken);
2600
2960
  await this.userService.updateLastLogin(user.id);
2601
- const { roles, permissions, sessionVersion } = generated;
2961
+ const { roles, permissions, sessionVersion, tokenFamily } = generated;
2602
2962
  this.cookieManager.setSessionCookie({
2603
2963
  user: {
2604
2964
  id: user.id,
@@ -2609,39 +2969,40 @@ var AuthSessionService = class AuthSessionService2 {
2609
2969
  },
2610
2970
  roles,
2611
2971
  permissions,
2612
- sessionVersion
2972
+ sessionVersion,
2973
+ tokenFamily
2613
2974
  });
2614
2975
  const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sessionVersion, ...tokens } = generated;
2615
2976
  return { ...tokens, user };
2616
2977
  }
2617
2978
  };
2618
- AuthSessionService = __decorate13([
2619
- Injectable8(),
2620
- __metadata13("design:paramtypes", [typeof (_a8 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a8 : Object, typeof (_b6 = typeof UserService !== "undefined" && UserService) === "function" ? _b6 : Object, typeof (_c4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c4 : Object, typeof (_d3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _d3 : Object])
2979
+ AuthSessionService = __decorate14([
2980
+ Injectable9(),
2981
+ __metadata14("design:paramtypes", [typeof (_a9 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a9 : Object, typeof (_b7 = typeof UserService !== "undefined" && UserService) === "function" ? _b7 : Object, typeof (_c4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c4 : Object, typeof (_d3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _d3 : Object])
2621
2982
  ], AuthSessionService);
2622
2983
 
2623
2984
  // src/credentialSetup/PasswordSetupService.ts
2624
- import { Inject as Inject10, Injectable as Injectable10 } from "najm-core";
2985
+ import { Inject as Inject11, Injectable as Injectable11 } from "najm-core";
2625
2986
  import { I18n as I18n7 } from "najm-i18n";
2626
2987
 
2627
2988
  // src/credentialSetup/CredentialSetupService.ts
2628
2989
  import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
2629
2990
  import { CookieService as CookieService2 } from "najm-cookies";
2630
- import { Err as Err11, Injectable as Injectable9 } from "najm-core";
2991
+ import { Err as Err11, Injectable as Injectable10 } from "najm-core";
2631
2992
  import { Transaction as Transaction3 } from "najm-database";
2632
2993
  import { I18n as I18n6 } from "najm-i18n";
2633
2994
 
2634
2995
  // src/credentialSetup/CredentialSetupRepository.ts
2635
2996
  import { and as and3, eq as eq6, gt, isNull as isNull2, lt as lt2 } from "drizzle-orm";
2636
- import { Err as Err10, Inject as Inject9, Repository as Repository5 } from "najm-core";
2997
+ import { Err as Err10, Inject as Inject10, Repository as Repository5 } from "najm-core";
2637
2998
  import { DB as DB5 } from "najm-database";
2638
- var __decorate14 = function(decorators, target, key, desc) {
2999
+ var __decorate15 = function(decorators, target, key, desc) {
2639
3000
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2640
3001
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2641
3002
  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;
2642
3003
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2643
3004
  };
2644
- var __metadata14 = function(k, v) {
3005
+ var __metadata15 = function(k, v) {
2645
3006
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2646
3007
  };
2647
3008
  var CredentialSetupRepository = class CredentialSetupRepository2 {
@@ -2693,33 +3054,33 @@ var CredentialSetupRepository = class CredentialSetupRepository2 {
2693
3054
  return this.db.delete(this.sessions).where(lt2(this.sessions.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning({ userId: this.sessions.userId });
2694
3055
  }
2695
3056
  };
2696
- __decorate14([
3057
+ __decorate15([
2697
3058
  DB5(),
2698
- __metadata14("design:type", Object)
3059
+ __metadata15("design:type", Object)
2699
3060
  ], CredentialSetupRepository.prototype, "db", void 0);
2700
- __decorate14([
2701
- Inject9(AUTH_SCHEMA),
2702
- __metadata14("design:type", Object)
3061
+ __decorate15([
3062
+ Inject10(AUTH_SCHEMA),
3063
+ __metadata15("design:type", Object)
2703
3064
  ], CredentialSetupRepository.prototype, "schema", void 0);
2704
- CredentialSetupRepository = __decorate14([
3065
+ CredentialSetupRepository = __decorate15([
2705
3066
  Repository5()
2706
3067
  ], CredentialSetupRepository);
2707
3068
 
2708
3069
  // src/credentialSetup/CredentialSetupService.ts
2709
- var __decorate15 = function(decorators, target, key, desc) {
3070
+ var __decorate16 = function(decorators, target, key, desc) {
2710
3071
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2711
3072
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2712
3073
  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;
2713
3074
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2714
3075
  };
2715
- var __metadata15 = function(k, v) {
3076
+ var __metadata16 = function(k, v) {
2716
3077
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2717
3078
  };
2718
- var _a9;
2719
- var _b7;
3079
+ var _a10;
3080
+ var _b8;
2720
3081
  var _c5;
2721
3082
  var _d4;
2722
- var _e2;
3083
+ var _e3;
2723
3084
  var _f2;
2724
3085
  var _g2;
2725
3086
  var DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME = "najm.credential-setup";
@@ -2855,48 +3216,48 @@ var CredentialSetupService = class CredentialSetupService2 {
2855
3216
  });
2856
3217
  }
2857
3218
  };
2858
- __decorate15([
3219
+ __decorate16([
2859
3220
  I18n6("auth"),
2860
- __metadata15("design:type", Object)
3221
+ __metadata16("design:type", Object)
2861
3222
  ], CredentialSetupService.prototype, "t", void 0);
2862
- __decorate15([
3223
+ __decorate16([
2863
3224
  Transaction3({ retries: 2 }),
2864
- __metadata15("design:type", Function),
2865
- __metadata15("design:paramtypes", [String, Object]),
2866
- __metadata15("design:returntype", typeof (_e2 = typeof Promise !== "undefined" && Promise) === "function" ? _e2 : Object)
3225
+ __metadata16("design:type", Function),
3226
+ __metadata16("design:paramtypes", [String, Object]),
3227
+ __metadata16("design:returntype", typeof (_e3 = typeof Promise !== "undefined" && Promise) === "function" ? _e3 : Object)
2867
3228
  ], CredentialSetupService.prototype, "begin", null);
2868
- __decorate15([
3229
+ __decorate16([
2869
3230
  Transaction3({ retries: 2 }),
2870
- __metadata15("design:type", Function),
2871
- __metadata15("design:paramtypes", [Object, Function]),
2872
- __metadata15("design:returntype", typeof (_f2 = typeof Promise !== "undefined" && Promise) === "function" ? _f2 : Object)
3231
+ __metadata16("design:type", Function),
3232
+ __metadata16("design:paramtypes", [Object, Function]),
3233
+ __metadata16("design:returntype", typeof (_f2 = typeof Promise !== "undefined" && Promise) === "function" ? _f2 : Object)
2873
3234
  ], CredentialSetupService.prototype, "consume", null);
2874
- __decorate15([
3235
+ __decorate16([
2875
3236
  Transaction3({ retries: 2 }),
2876
- __metadata15("design:type", Function),
2877
- __metadata15("design:paramtypes", [Object]),
2878
- __metadata15("design:returntype", typeof (_g2 = typeof Promise !== "undefined" && Promise) === "function" ? _g2 : Object)
3237
+ __metadata16("design:type", Function),
3238
+ __metadata16("design:paramtypes", [Object]),
3239
+ __metadata16("design:returntype", typeof (_g2 = typeof Promise !== "undefined" && Promise) === "function" ? _g2 : Object)
2879
3240
  ], CredentialSetupService.prototype, "cancel", null);
2880
- CredentialSetupService = __decorate15([
2881
- Injectable9(),
2882
- __metadata15("design:paramtypes", [typeof (_a9 = typeof CredentialSetupRepository !== "undefined" && CredentialSetupRepository) === "function" ? _a9 : Object, typeof (_b7 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b7 : Object, typeof (_c5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c5 : Object, typeof (_d4 = typeof CookieService2 !== "undefined" && CookieService2) === "function" ? _d4 : Object])
3241
+ CredentialSetupService = __decorate16([
3242
+ Injectable10(),
3243
+ __metadata16("design:paramtypes", [typeof (_a10 = typeof CredentialSetupRepository !== "undefined" && CredentialSetupRepository) === "function" ? _a10 : Object, typeof (_b8 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b8 : Object, typeof (_c5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _c5 : Object, typeof (_d4 = typeof CookieService2 !== "undefined" && CookieService2) === "function" ? _d4 : Object])
2883
3244
  ], CredentialSetupService);
2884
3245
 
2885
3246
  // src/credentialSetup/PasswordSetupService.ts
2886
- var __decorate16 = function(decorators, target, key, desc) {
3247
+ var __decorate17 = function(decorators, target, key, desc) {
2887
3248
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2888
3249
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2889
3250
  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;
2890
3251
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2891
3252
  };
2892
- var __metadata16 = function(k, v) {
3253
+ var __metadata17 = function(k, v) {
2893
3254
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2894
3255
  };
2895
- var _a10;
2896
- var _b8;
3256
+ var _a11;
3257
+ var _b9;
2897
3258
  var _c6;
2898
3259
  var _d5;
2899
- var _e3;
3260
+ var _e4;
2900
3261
  var _f3;
2901
3262
  var PasswordSetupService = class PasswordSetupService2 {
2902
3263
  static {
@@ -3013,38 +3374,38 @@ var PasswordSetupService = class PasswordSetupService2 {
3013
3374
  return this.validator.comparePassword(normalized, storedHash);
3014
3375
  }
3015
3376
  };
3016
- __decorate16([
3017
- Inject10(AUTH_CONFIG),
3018
- __metadata16("design:type", Object)
3377
+ __decorate17([
3378
+ Inject11(AUTH_CONFIG),
3379
+ __metadata17("design:type", Object)
3019
3380
  ], PasswordSetupService.prototype, "config", void 0);
3020
- __decorate16([
3381
+ __decorate17([
3021
3382
  I18n7("auth"),
3022
- __metadata16("design:type", Object)
3383
+ __metadata17("design:type", Object)
3023
3384
  ], PasswordSetupService.prototype, "t", void 0);
3024
- PasswordSetupService = __decorate16([
3025
- Injectable10(),
3026
- __metadata16("design:paramtypes", [typeof (_a10 = typeof CredentialSetupService !== "undefined" && CredentialSetupService) === "function" ? _a10 : Object, typeof (_b8 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _b8 : Object, typeof (_c6 = typeof UserService !== "undefined" && UserService) === "function" ? _c6 : Object, typeof (_d5 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _d5 : Object, typeof (_e3 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _e3 : Object, typeof (_f3 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _f3 : Object])
3385
+ PasswordSetupService = __decorate17([
3386
+ Injectable11(),
3387
+ __metadata17("design:paramtypes", [typeof (_a11 = typeof CredentialSetupService !== "undefined" && CredentialSetupService) === "function" ? _a11 : Object, typeof (_b9 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _b9 : Object, typeof (_c6 = typeof UserService !== "undefined" && UserService) === "function" ? _c6 : Object, typeof (_d5 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _d5 : Object, typeof (_e4 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _e4 : Object, typeof (_f3 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _f3 : Object])
3027
3388
  ], PasswordSetupService);
3028
3389
 
3029
3390
  // src/auth/AuthService.ts
3030
- var __decorate17 = function(decorators, target, key, desc) {
3391
+ var __decorate18 = function(decorators, target, key, desc) {
3031
3392
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3032
3393
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3033
3394
  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;
3034
3395
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3035
3396
  };
3036
- var __metadata17 = function(k, v) {
3397
+ var __metadata18 = function(k, v) {
3037
3398
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3038
3399
  };
3039
- var _a11;
3040
- var _b9;
3400
+ var _a12;
3401
+ var _b10;
3041
3402
  var _c7;
3042
3403
  var _d6;
3043
- var _e4;
3404
+ var _e5;
3044
3405
  var _f4;
3045
3406
  var _g3;
3046
3407
  var _h2;
3047
- var _j;
3408
+ var _j2;
3048
3409
  var _k;
3049
3410
  var _l;
3050
3411
  var AuthService = class AuthService2 {
@@ -3083,7 +3444,7 @@ var AuthService = class AuthService2 {
3083
3444
  return new Date(lockoutUntil).getTime() > Date.now();
3084
3445
  }
3085
3446
  nextLockoutUntil() {
3086
- const durationMs = timestring3(this.config.lockout.duration, "ms");
3447
+ const durationMs = timestring4(this.config.lockout.duration, "ms");
3087
3448
  return new Date(Date.now() + durationMs).toISOString();
3088
3449
  }
3089
3450
  getDummyHash() {
@@ -3333,7 +3694,8 @@ var AuthService = class AuthService2 {
3333
3694
  user: { id: user.id, email: user.email, name: user.name, role: user.role, status: user.status ?? void 0 },
3334
3695
  roles: generated.roles,
3335
3696
  permissions: generated.permissions,
3336
- sessionVersion: generated.sessionVersion
3697
+ sessionVersion: generated.sessionVersion,
3698
+ tokenFamily: generated.tokenFamily
3337
3699
  });
3338
3700
  }
3339
3701
  const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sv, ...tokens } = generated;
@@ -3356,7 +3718,8 @@ var AuthService = class AuthService2 {
3356
3718
  },
3357
3719
  roles: recovered.roles,
3358
3720
  permissions: recovered.permissions,
3359
- sessionVersion: recovered.sessionVersion
3721
+ sessionVersion: recovered.sessionVersion,
3722
+ tokenFamily: recovered.tokenFamily
3360
3723
  });
3361
3724
  return { recovered: true };
3362
3725
  }
@@ -3408,7 +3771,12 @@ var AuthService = class AuthService2 {
3408
3771
  const lang = this.i18nService.getCurrentLanguage();
3409
3772
  result = { ...user, language: lang };
3410
3773
  const token = this.tokenService.decodeAccessToken(authorization.replace(/^Bearer\s+/i, ""));
3411
- cachePayload = { roles: token?.roles ?? [], permissions: token?.permissions ?? [], sessionVersion: token?.sessionVersion ?? 0 };
3774
+ cachePayload = token?.tokenFamily ? {
3775
+ roles: token.roles ?? [],
3776
+ permissions: token.permissions ?? [],
3777
+ sessionVersion: token.sessionVersion ?? 0,
3778
+ tokenFamily: token.tokenFamily
3779
+ } : null;
3412
3780
  } else {
3413
3781
  result = await this.getUserFromCookie();
3414
3782
  }
@@ -3420,7 +3788,8 @@ var AuthService = class AuthService2 {
3420
3788
  user: { id: result.id, email: result.email, name: result.name, role: result.role, status: result.status ?? void 0 },
3421
3789
  roles: cachePayload.roles,
3422
3790
  permissions: cachePayload.permissions,
3423
- sessionVersion: cachePayload.sessionVersion
3791
+ sessionVersion: cachePayload.sessionVersion,
3792
+ tokenFamily: cachePayload.tokenFamily
3424
3793
  });
3425
3794
  }
3426
3795
  return result;
@@ -3459,49 +3828,57 @@ var AuthService = class AuthService2 {
3459
3828
  return { message: this.t("success.passwordChanged") };
3460
3829
  }
3461
3830
  async resetPassword(token, newPassword) {
3462
- const userId = await this.tokenService.verifyResetToken(token);
3463
3831
  this.userValidator.validatePasswordStrength(newPassword);
3464
- await this.userService.update(userId, { password: newPassword });
3465
- await this.tokenService.invalidateUserAccessTokens(userId);
3466
- await this.tokenService.revokeAllForUser(userId);
3832
+ const consumed = await this.tokenService.consumeSetPasswordToken(token);
3833
+ const user = await this.userService.getById(consumed.userId);
3834
+ const acceptsInvitation = consumed.type === "invite";
3835
+ await this.userService.update(consumed.userId, {
3836
+ password: newPassword,
3837
+ ...acceptsInvitation ? {
3838
+ emailVerified: true,
3839
+ ...user.status === "pending" ? { status: "active" } : {}
3840
+ } : {}
3841
+ });
3842
+ await this.tokenService.invalidateUserAccessTokens(consumed.userId);
3843
+ await this.tokenService.revokeAllForUser(consumed.userId);
3467
3844
  this.cookieManager.clearRefreshToken();
3468
3845
  this.cookieManager.clearSessionCookie();
3469
3846
  return { message: this.t("success.passwordReset") };
3470
3847
  }
3471
3848
  };
3472
- __decorate17([
3473
- Inject11(AUTH_CONFIG),
3474
- __metadata17("design:type", Object)
3849
+ __decorate18([
3850
+ Inject12(AUTH_CONFIG),
3851
+ __metadata18("design:type", Object)
3475
3852
  ], AuthService.prototype, "config", void 0);
3476
- __decorate17([
3853
+ __decorate18([
3477
3854
  I18n8("auth"),
3478
- __metadata17("design:type", Object)
3855
+ __metadata18("design:type", Object)
3479
3856
  ], AuthService.prototype, "t", void 0);
3480
- __decorate17([
3857
+ __decorate18([
3481
3858
  Log(),
3482
- __metadata17("design:type", Object)
3859
+ __metadata18("design:type", Object)
3483
3860
  ], AuthService.prototype, "logger", void 0);
3484
- __decorate17([
3861
+ __decorate18([
3485
3862
  Transaction4(),
3486
- __metadata17("design:type", Function),
3487
- __metadata17("design:paramtypes", [Object]),
3488
- __metadata17("design:returntype", typeof (_l = typeof Promise !== "undefined" && Promise) === "function" ? _l : Object)
3863
+ __metadata18("design:type", Function),
3864
+ __metadata18("design:paramtypes", [Object]),
3865
+ __metadata18("design:returntype", typeof (_l = typeof Promise !== "undefined" && Promise) === "function" ? _l : Object)
3489
3866
  ], AuthService.prototype, "provisionWithCredentialSetup", null);
3490
- AuthService = __decorate17([
3491
- Injectable11(),
3492
- __metadata17("design:paramtypes", [typeof (_a11 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a11 : Object, typeof (_b9 = typeof UserService !== "undefined" && UserService) === "function" ? _b9 : Object, typeof (_c7 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _c7 : Object, typeof (_d6 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _d6 : Object, typeof (_e4 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _e4 : Object, typeof (_f4 = typeof I18nService2 !== "undefined" && I18nService2) === "function" ? _f4 : Object, typeof (_g3 = typeof EmailService !== "undefined" && EmailService) === "function" ? _g3 : Object, typeof (_h2 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _h2 : Object, typeof (_j = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _j : Object, typeof (_k = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _k : Object])
3867
+ AuthService = __decorate18([
3868
+ Injectable12(),
3869
+ __metadata18("design:paramtypes", [typeof (_a12 = typeof TokenService !== "undefined" && TokenService) === "function" ? _a12 : Object, typeof (_b10 = typeof UserService !== "undefined" && UserService) === "function" ? _b10 : Object, typeof (_c7 = typeof UserValidator !== "undefined" && UserValidator) === "function" ? _c7 : Object, typeof (_d6 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _d6 : Object, typeof (_e5 = typeof CookieManager !== "undefined" && CookieManager) === "function" ? _e5 : Object, typeof (_f4 = typeof I18nService2 !== "undefined" && I18nService2) === "function" ? _f4 : Object, typeof (_g3 = typeof EmailService !== "undefined" && EmailService) === "function" ? _g3 : Object, typeof (_h2 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _h2 : Object, typeof (_j2 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _j2 : Object, typeof (_k = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _k : Object])
3493
3870
  ], AuthService);
3494
3871
 
3495
3872
  // src/auth/AuthGuard.ts
3496
3873
  import { Service as Service2, User } from "najm-core";
3497
3874
  import { createGuard } from "najm-guard";
3498
- var __decorate18 = function(decorators, target, key, desc) {
3875
+ var __decorate19 = function(decorators, target, key, desc) {
3499
3876
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3500
3877
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3501
3878
  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;
3502
3879
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3503
3880
  };
3504
- var __metadata18 = function(k, v) {
3881
+ var __metadata19 = function(k, v) {
3505
3882
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3506
3883
  };
3507
3884
  var __param3 = function(paramIndex, decorator) {
@@ -3513,17 +3890,27 @@ var AuthGuard = class AuthGuard2 {
3513
3890
  static {
3514
3891
  __name(this, "AuthGuard");
3515
3892
  }
3893
+ /**
3894
+ * A resolved principal is not automatically an authorized one.
3895
+ *
3896
+ * The resolvers ahead of this guard already reject deactivated accounts, so
3897
+ * this is the backstop for anything that publishes a principal by another
3898
+ * route: a truthy user record must still be an active one to pass. Records
3899
+ * whose projection omits `status` are unchanged.
3900
+ */
3516
3901
  canActivate(user) {
3517
- return !!user;
3902
+ if (!user)
3903
+ return false;
3904
+ return user.status === void 0 || user.status === "active";
3518
3905
  }
3519
3906
  };
3520
- __decorate18([
3907
+ __decorate19([
3521
3908
  __param3(0, User()),
3522
- __metadata18("design:type", Function),
3523
- __metadata18("design:paramtypes", [Object]),
3524
- __metadata18("design:returntype", Boolean)
3909
+ __metadata19("design:type", Function),
3910
+ __metadata19("design:paramtypes", [Object]),
3911
+ __metadata19("design:returntype", Boolean)
3525
3912
  ], AuthGuard.prototype, "canActivate", null);
3526
- AuthGuard = __decorate18([
3913
+ AuthGuard = __decorate19([
3527
3914
  Service2()
3528
3915
  ], AuthGuard);
3529
3916
  var isAuth = createGuard(AuthGuard);
@@ -3532,13 +3919,13 @@ var isAuth = createGuard(AuthGuard);
3532
3919
  import { Service as Service3 } from "najm-core";
3533
3920
  import { GuardParams, Role as RequestRole } from "najm-core";
3534
3921
  import { composeGuards, createGuard as createGuard2 } from "najm-guard";
3535
- var __decorate19 = function(decorators, target, key, desc) {
3922
+ var __decorate20 = function(decorators, target, key, desc) {
3536
3923
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3537
3924
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3538
3925
  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;
3539
3926
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3540
3927
  };
3541
- var __metadata19 = function(k, v) {
3928
+ var __metadata20 = function(k, v) {
3542
3929
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3543
3930
  };
3544
3931
  var __param4 = function(paramIndex, decorator) {
@@ -3561,14 +3948,14 @@ var RoleGuard = class RoleGuard2 {
3561
3948
  return false;
3562
3949
  }
3563
3950
  };
3564
- __decorate19([
3951
+ __decorate20([
3565
3952
  __param4(0, GuardParams()),
3566
3953
  __param4(1, RequestRole()),
3567
- __metadata19("design:type", Function),
3568
- __metadata19("design:paramtypes", [Object, String]),
3569
- __metadata19("design:returntype", void 0)
3954
+ __metadata20("design:type", Function),
3955
+ __metadata20("design:paramtypes", [Object, String]),
3956
+ __metadata20("design:returntype", void 0)
3570
3957
  ], RoleGuard.prototype, "canActivate", null);
3571
- RoleGuard = __decorate19([
3958
+ RoleGuard = __decorate20([
3572
3959
  Service3()
3573
3960
  ], RoleGuard);
3574
3961
  var Role = createGuard2(RoleGuard);
@@ -3739,13 +4126,13 @@ var userListQuery = z.object({
3739
4126
  });
3740
4127
 
3741
4128
  // src/auth/AuthController.ts
3742
- var __decorate20 = function(decorators, target, key, desc) {
4129
+ var __decorate21 = function(decorators, target, key, desc) {
3743
4130
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3744
4131
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3745
4132
  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;
3746
4133
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3747
4134
  };
3748
- var __metadata20 = function(k, v) {
4135
+ var __metadata21 = function(k, v) {
3749
4136
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3750
4137
  };
3751
4138
  var __param5 = function(paramIndex, decorator) {
@@ -3753,18 +4140,28 @@ var __param5 = function(paramIndex, decorator) {
3753
4140
  decorator(target, key, paramIndex);
3754
4141
  };
3755
4142
  };
3756
- var _a12;
4143
+ var _a13;
3757
4144
  var hashKeyPart = /* @__PURE__ */ __name((value) => createHash3("sha256").update(value).digest("base64url").slice(0, 32), "hashKeyPart");
3758
4145
  var cookieFingerprint = /* @__PURE__ */ __name(() => (ctx, { clientIp }) => {
3759
4146
  const cookie = ctx.req.raw.headers.get("cookie") ?? "";
3760
4147
  const fingerprint = cookie ? hashKeyPart(cookie) : "none";
3761
4148
  return `${clientIp}:${fingerprint}`;
3762
4149
  }, "cookieFingerprint");
3763
- var authIdentityRateLimitKey = /* @__PURE__ */ __name(async (ctx, keyContext) => {
4150
+ var readDeclaredIdentity = /* @__PURE__ */ __name((body, fields) => {
4151
+ if (typeof body !== "object" || body === null || Array.isArray(body))
4152
+ return void 0;
4153
+ for (const field of fields) {
4154
+ const value = body[field];
4155
+ if (typeof value === "string" && value.trim())
4156
+ return value;
4157
+ }
4158
+ return void 0;
4159
+ }, "readDeclaredIdentity");
4160
+ var identityRateLimitKey = /* @__PURE__ */ __name((fields) => async (ctx, keyContext) => {
3764
4161
  const ip = keyContext?.clientIp ?? UNRESOLVED_CLIENT_ADDRESS;
3765
4162
  try {
3766
4163
  const body = await ctx.req.json();
3767
- const identity = body?.identifier ?? body?.email;
4164
+ const identity = readDeclaredIdentity(body, fields);
3768
4165
  const normalizedIdentity = getRequestIdentityResolver(ctx)(identity);
3769
4166
  if (normalizedIdentity) {
3770
4167
  return `${ip}:${hashKeyPart(normalizedIdentity)}`;
@@ -3772,7 +4169,9 @@ var authIdentityRateLimitKey = /* @__PURE__ */ __name(async (ctx, keyContext) =>
3772
4169
  } catch {
3773
4170
  }
3774
4171
  return ip;
3775
- }, "authIdentityRateLimitKey");
4172
+ }, "identityRateLimitKey");
4173
+ var authIdentityRateLimitKey = identityRateLimitKey(["identifier", "email"]);
4174
+ var authEmailRateLimitKey = identityRateLimitKey(["email"]);
3776
4175
  var loginRateLimit = resolveAuthLoginRateLimitConfig();
3777
4176
  var AuthController = class AuthController2 {
3778
4177
  static {
@@ -3815,7 +4214,7 @@ var AuthController = class AuthController2 {
3815
4214
  return this.authService.resetPassword(body.token, body.newPassword);
3816
4215
  }
3817
4216
  };
3818
- __decorate20([
4217
+ __decorate21([
3819
4218
  Post("/login"),
3820
4219
  RateLimit({
3821
4220
  limit: loginRateLimit.limit,
@@ -3827,105 +4226,105 @@ __decorate20([
3827
4226
  Validate(loginDto),
3828
4227
  ResMsg("auth.success.login"),
3829
4228
  __param5(0, Body()),
3830
- __metadata20("design:type", Function),
3831
- __metadata20("design:paramtypes", [Object]),
3832
- __metadata20("design:returntype", Promise)
4229
+ __metadata21("design:type", Function),
4230
+ __metadata21("design:paramtypes", [Object]),
4231
+ __metadata21("design:returntype", Promise)
3833
4232
  ], AuthController.prototype, "loginUser", null);
3834
- __decorate20([
4233
+ __decorate21([
3835
4234
  Post("/invite"),
3836
4235
  isAdmin(),
3837
4236
  RateLimit({ limit: 20, window: "15m", key: "user" }),
3838
4237
  Validate(inviteUserDto),
3839
4238
  ResMsg("auth.success.accountInviteSent"),
3840
4239
  __param5(0, Body()),
3841
- __metadata20("design:type", Function),
3842
- __metadata20("design:paramtypes", [Object]),
3843
- __metadata20("design:returntype", Promise)
4240
+ __metadata21("design:type", Function),
4241
+ __metadata21("design:paramtypes", [Object]),
4242
+ __metadata21("design:returntype", Promise)
3844
4243
  ], AuthController.prototype, "inviteUser", null);
3845
- __decorate20([
4244
+ __decorate21([
3846
4245
  Post("/refresh"),
3847
4246
  RateLimit({ limit: 15, window: "15m", key: cookieFingerprint() }),
3848
4247
  ResMsg("auth.success.tokenRefreshed"),
3849
- __metadata20("design:type", Function),
3850
- __metadata20("design:paramtypes", []),
3851
- __metadata20("design:returntype", Promise)
4248
+ __metadata21("design:type", Function),
4249
+ __metadata21("design:paramtypes", []),
4250
+ __metadata21("design:returntype", Promise)
3852
4251
  ], AuthController.prototype, "refreshTokens", null);
3853
- __decorate20([
4252
+ __decorate21([
3854
4253
  Post("/session/recover"),
3855
4254
  RateLimit({ limit: 120, window: "1m", key: cookieFingerprint() }),
3856
4255
  ResMsg("auth.success.sessionRecovered"),
3857
4256
  __param5(0, Headers("x-najm-session-recovery")),
3858
4257
  __param5(1, Ctx()),
3859
- __metadata20("design:type", Function),
3860
- __metadata20("design:paramtypes", [String, Object]),
3861
- __metadata20("design:returntype", Promise)
4258
+ __metadata21("design:type", Function),
4259
+ __metadata21("design:paramtypes", [String, Object]),
4260
+ __metadata21("design:returntype", Promise)
3862
4261
  ], AuthController.prototype, "recoverSession", null);
3863
- __decorate20([
4262
+ __decorate21([
3864
4263
  Post("/logout"),
3865
4264
  __param5(0, User2("id")),
3866
4265
  __param5(1, Headers("authorization")),
3867
- __metadata20("design:type", Function),
3868
- __metadata20("design:paramtypes", [String, String]),
3869
- __metadata20("design:returntype", Promise)
4266
+ __metadata21("design:type", Function),
4267
+ __metadata21("design:paramtypes", [String, String]),
4268
+ __metadata21("design:returntype", Promise)
3870
4269
  ], AuthController.prototype, "logoutUser", null);
3871
- __decorate20([
4270
+ __decorate21([
3872
4271
  Post("/change-password"),
3873
4272
  isAuth(),
3874
4273
  Validate(changePasswordDto),
3875
4274
  ResMsg("auth.success.passwordChanged"),
3876
4275
  __param5(0, User2("id")),
3877
4276
  __param5(1, Body()),
3878
- __metadata20("design:type", Function),
3879
- __metadata20("design:paramtypes", [String, Object]),
3880
- __metadata20("design:returntype", Promise)
4277
+ __metadata21("design:type", Function),
4278
+ __metadata21("design:paramtypes", [String, Object]),
4279
+ __metadata21("design:returntype", Promise)
3881
4280
  ], AuthController.prototype, "changePassword", null);
3882
- __decorate20([
4281
+ __decorate21([
3883
4282
  Get("/me"),
3884
4283
  RateLimit({ limit: 30, window: "1m", key: cookieFingerprint() }),
3885
4284
  ResMsg("auth.users.success.retrieved"),
3886
4285
  __param5(0, Headers("authorization")),
3887
- __metadata20("design:type", Function),
3888
- __metadata20("design:paramtypes", [String]),
3889
- __metadata20("design:returntype", Promise)
4286
+ __metadata21("design:type", Function),
4287
+ __metadata21("design:paramtypes", [String]),
4288
+ __metadata21("design:returntype", Promise)
3890
4289
  ], AuthController.prototype, "userProfile", null);
3891
- __decorate20([
4290
+ __decorate21([
3892
4291
  Post("/forgot-password"),
3893
- RateLimit({ limit: 3, window: "15m", key: authIdentityRateLimitKey, message: "Too many password reset requests. Please try again later." }),
4292
+ RateLimit({ limit: 3, window: "15m", key: authEmailRateLimitKey, message: "Too many password reset requests. Please try again later." }),
3894
4293
  Validate(resetPasswordDto),
3895
4294
  ResMsg("auth.success.passwordResetSent"),
3896
4295
  __param5(0, Body()),
3897
- __metadata20("design:type", Function),
3898
- __metadata20("design:paramtypes", [Object]),
3899
- __metadata20("design:returntype", Promise)
4296
+ __metadata21("design:type", Function),
4297
+ __metadata21("design:paramtypes", [Object]),
4298
+ __metadata21("design:returntype", Promise)
3900
4299
  ], AuthController.prototype, "forgotPassword", null);
3901
- __decorate20([
4300
+ __decorate21([
3902
4301
  Post("/reset-password"),
3903
4302
  RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many password reset attempts. Please try again later." }),
3904
4303
  Validate(confirmResetPasswordDto),
3905
4304
  ResMsg("auth.success.passwordReset"),
3906
4305
  __param5(0, Body()),
3907
- __metadata20("design:type", Function),
3908
- __metadata20("design:paramtypes", [Object]),
3909
- __metadata20("design:returntype", Promise)
4306
+ __metadata21("design:type", Function),
4307
+ __metadata21("design:paramtypes", [Object]),
4308
+ __metadata21("design:returntype", Promise)
3910
4309
  ], AuthController.prototype, "resetPassword", null);
3911
- AuthController = __decorate20([
4310
+ AuthController = __decorate21([
3912
4311
  Controller("/auth"),
3913
- __metadata20("design:paramtypes", [typeof (_a12 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a12 : Object])
4312
+ __metadata21("design:paramtypes", [typeof (_a13 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a13 : Object])
3914
4313
  ], AuthController);
3915
4314
 
3916
4315
  // src/auth/AuthResolver.ts
3917
- import { APP, Container, DI, Inject as Inject12, LOGGER, Meta, Service as Service4 } from "najm-core";
4316
+ import { APP, Container, DI, Inject as Inject13, LOGGER, Meta, Service as Service4 } from "najm-core";
3918
4317
  import { USER, ROLE, PERMISSIONS } from "najm-guard";
3919
- var __decorate21 = function(decorators, target, key, desc) {
4318
+ var __decorate22 = function(decorators, target, key, desc) {
3920
4319
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3921
4320
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
3922
4321
  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;
3923
4322
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3924
4323
  };
3925
- var __metadata21 = function(k, v) {
4324
+ var __metadata22 = function(k, v) {
3926
4325
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3927
4326
  };
3928
- var _a13;
4327
+ var _a14;
3929
4328
  var AuthResolver = class AuthResolver2 {
3930
4329
  static {
3931
4330
  __name(this, "AuthResolver");
@@ -3976,6 +4375,12 @@ var AuthResolver = class AuthResolver2 {
3976
4375
  const currentVersion = await tokenService.getSessionVersion(session.user.id);
3977
4376
  if ((session.sessionVersion ?? 0) !== currentVersion)
3978
4377
  return false;
4378
+ if (!await tokenService.isSessionFamilyLive(session.tokenFamily, session.user.id)) {
4379
+ return false;
4380
+ }
4381
+ const status = session.user.status;
4382
+ if (status !== void 0 && status !== "active")
4383
+ return false;
3979
4384
  return {
3980
4385
  user: { ...session.user, permissions: session.permissions },
3981
4386
  role: session.user.role ?? session.roles[0],
@@ -4041,32 +4446,32 @@ var AuthResolver = class AuthResolver2 {
4041
4446
  await authService.warmupPasswordHash();
4042
4447
  }
4043
4448
  };
4044
- __decorate21([
4449
+ __decorate22([
4045
4450
  DI(),
4046
- __metadata21("design:type", typeof (_a13 = typeof Container !== "undefined" && Container) === "function" ? _a13 : Object)
4451
+ __metadata22("design:type", typeof (_a14 = typeof Container !== "undefined" && Container) === "function" ? _a14 : Object)
4047
4452
  ], AuthResolver.prototype, "container", void 0);
4048
- __decorate21([
4049
- Inject12(APP),
4050
- __metadata21("design:type", Object)
4453
+ __decorate22([
4454
+ Inject13(APP),
4455
+ __metadata22("design:type", Object)
4051
4456
  ], AuthResolver.prototype, "app", void 0);
4052
- __decorate21([
4053
- Inject12(LOGGER),
4054
- __metadata21("design:type", Object)
4457
+ __decorate22([
4458
+ Inject13(LOGGER),
4459
+ __metadata22("design:type", Object)
4055
4460
  ], AuthResolver.prototype, "log", void 0);
4056
- AuthResolver = __decorate21([
4461
+ AuthResolver = __decorate22([
4057
4462
  Service4(),
4058
4463
  Meta({ layer: "plugin", order: 30 })
4059
4464
  ], AuthResolver);
4060
4465
 
4061
4466
  // src/auth/AuthIdentityContextService.ts
4062
- import { DI as DI2, Inject as Inject13, INJECTION_TYPES, Meta as Meta2, Service as Service5 } from "najm-core";
4063
- var __decorate22 = function(decorators, target, key, desc) {
4467
+ import { DI as DI2, Inject as Inject14, INJECTION_TYPES, Meta as Meta2, Service as Service5 } from "najm-core";
4468
+ var __decorate23 = function(decorators, target, key, desc) {
4064
4469
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4065
4470
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4066
4471
  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;
4067
4472
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4068
4473
  };
4069
- var __metadata22 = function(k, v) {
4474
+ var __metadata23 = function(k, v) {
4070
4475
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4071
4476
  };
4072
4477
  var __param6 = function(paramIndex, decorator) {
@@ -4096,28 +4501,28 @@ var AuthIdentityContextService = class AuthIdentityContextService2 {
4096
4501
  });
4097
4502
  }
4098
4503
  };
4099
- __decorate22([
4504
+ __decorate23([
4100
4505
  DI2(),
4101
- __metadata22("design:type", Object)
4506
+ __metadata23("design:type", Object)
4102
4507
  ], AuthIdentityContextService.prototype, "container", void 0);
4103
- AuthIdentityContextService = __decorate22([
4508
+ AuthIdentityContextService = __decorate23([
4104
4509
  Service5(),
4105
4510
  Meta2({ layer: "plugin", order: 14 }),
4106
- __param6(0, Inject13(AUTH_CONFIG)),
4107
- __metadata22("design:paramtypes", [Object])
4511
+ __param6(0, Inject14(AUTH_CONFIG)),
4512
+ __metadata23("design:paramtypes", [Object])
4108
4513
  ], AuthIdentityContextService);
4109
4514
 
4110
4515
  // src/auth/RegistrationController.ts
4111
4516
  import { Body as Body2, Controller as Controller2, Post as Post2, ResMsg as ResMsg2 } from "najm-core";
4112
4517
  import { RateLimit as RateLimit2 } from "najm-rate";
4113
4518
  import { Validate as Validate2 } from "najm-validation";
4114
- var __decorate23 = function(decorators, target, key, desc) {
4519
+ var __decorate24 = function(decorators, target, key, desc) {
4115
4520
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4116
4521
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4117
4522
  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;
4118
4523
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4119
4524
  };
4120
- var __metadata23 = function(k, v) {
4525
+ var __metadata24 = function(k, v) {
4121
4526
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4122
4527
  };
4123
4528
  var __param7 = function(paramIndex, decorator) {
@@ -4125,7 +4530,7 @@ var __param7 = function(paramIndex, decorator) {
4125
4530
  decorator(target, key, paramIndex);
4126
4531
  };
4127
4532
  };
4128
- var _a14;
4533
+ var _a15;
4129
4534
  var RegistrationController = class RegistrationController2 {
4130
4535
  static {
4131
4536
  __name(this, "RegistrationController");
@@ -4138,19 +4543,19 @@ var RegistrationController = class RegistrationController2 {
4138
4543
  return this.authService.registerUser(body);
4139
4544
  }
4140
4545
  };
4141
- __decorate23([
4546
+ __decorate24([
4142
4547
  Post2("/register"),
4143
- RateLimit2({ limit: 5, window: "15m", key: authIdentityRateLimitKey }),
4548
+ RateLimit2({ limit: 5, window: "15m", key: authEmailRateLimitKey }),
4144
4549
  Validate2(registerDto),
4145
4550
  ResMsg2("auth.success.register"),
4146
4551
  __param7(0, Body2()),
4147
- __metadata23("design:type", Function),
4148
- __metadata23("design:paramtypes", [Object]),
4149
- __metadata23("design:returntype", Promise)
4552
+ __metadata24("design:type", Function),
4553
+ __metadata24("design:paramtypes", [Object]),
4554
+ __metadata24("design:returntype", Promise)
4150
4555
  ], RegistrationController.prototype, "registerUser", null);
4151
- RegistrationController = __decorate23([
4556
+ RegistrationController = __decorate24([
4152
4557
  Controller2("/auth"),
4153
- __metadata23("design:paramtypes", [typeof (_a14 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a14 : Object])
4558
+ __metadata24("design:paramtypes", [typeof (_a15 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a15 : Object])
4154
4559
  ], RegistrationController);
4155
4560
 
4156
4561
  // src/auth/runAsUser.ts
@@ -4301,13 +4706,13 @@ var assignRoleDto = z2.object({
4301
4706
  });
4302
4707
 
4303
4708
  // src/roles/RoleController.ts
4304
- var __decorate24 = function(decorators, target, key, desc) {
4709
+ var __decorate25 = function(decorators, target, key, desc) {
4305
4710
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4306
4711
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4307
4712
  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;
4308
4713
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4309
4714
  };
4310
- var __metadata24 = function(k, v) {
4715
+ var __metadata25 = function(k, v) {
4311
4716
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4312
4717
  };
4313
4718
  var __param8 = function(paramIndex, decorator) {
@@ -4315,7 +4720,7 @@ var __param8 = function(paramIndex, decorator) {
4315
4720
  decorator(target, key, paramIndex);
4316
4721
  };
4317
4722
  };
4318
- var _a15;
4723
+ var _a16;
4319
4724
  var RoleController = class RoleController2 {
4320
4725
  static {
4321
4726
  __name(this, "RoleController");
@@ -4340,35 +4745,35 @@ var RoleController = class RoleController2 {
4340
4745
  return this.roleService.delete(params.id);
4341
4746
  }
4342
4747
  };
4343
- __decorate24([
4748
+ __decorate25([
4344
4749
  Get2(),
4345
4750
  isAdmin(),
4346
4751
  ResMsg3("roles.success.retrieved"),
4347
- __metadata24("design:type", Function),
4348
- __metadata24("design:paramtypes", []),
4349
- __metadata24("design:returntype", Promise)
4752
+ __metadata25("design:type", Function),
4753
+ __metadata25("design:paramtypes", []),
4754
+ __metadata25("design:returntype", Promise)
4350
4755
  ], RoleController.prototype, "getRoles", null);
4351
- __decorate24([
4756
+ __decorate25([
4352
4757
  Get2("/:id"),
4353
4758
  isAdmin(),
4354
4759
  Validate3({ params: roleIdParam }),
4355
4760
  ResMsg3("roles.success.retrieved"),
4356
4761
  __param8(0, Params()),
4357
- __metadata24("design:type", Function),
4358
- __metadata24("design:paramtypes", [Object]),
4359
- __metadata24("design:returntype", Promise)
4762
+ __metadata25("design:type", Function),
4763
+ __metadata25("design:paramtypes", [Object]),
4764
+ __metadata25("design:returntype", Promise)
4360
4765
  ], RoleController.prototype, "getRole", null);
4361
- __decorate24([
4766
+ __decorate25([
4362
4767
  Post3(),
4363
4768
  isAdmin(),
4364
4769
  Validate3(createRoleDto),
4365
4770
  ResMsg3("roles.success.created"),
4366
4771
  __param8(0, Body3()),
4367
- __metadata24("design:type", Function),
4368
- __metadata24("design:paramtypes", [Object]),
4369
- __metadata24("design:returntype", Promise)
4772
+ __metadata25("design:type", Function),
4773
+ __metadata25("design:paramtypes", [Object]),
4774
+ __metadata25("design:returntype", Promise)
4370
4775
  ], RoleController.prototype, "createRole", null);
4371
- __decorate24([
4776
+ __decorate25([
4372
4777
  Put("/:id"),
4373
4778
  isAdmin(),
4374
4779
  Validate3({
@@ -4378,34 +4783,34 @@ __decorate24([
4378
4783
  ResMsg3("roles.success.updated"),
4379
4784
  __param8(0, Params()),
4380
4785
  __param8(1, Body3()),
4381
- __metadata24("design:type", Function),
4382
- __metadata24("design:paramtypes", [Object, Object]),
4383
- __metadata24("design:returntype", Promise)
4786
+ __metadata25("design:type", Function),
4787
+ __metadata25("design:paramtypes", [Object, Object]),
4788
+ __metadata25("design:returntype", Promise)
4384
4789
  ], RoleController.prototype, "updateRole", null);
4385
- __decorate24([
4790
+ __decorate25([
4386
4791
  Delete("/:id"),
4387
4792
  isAdmin(),
4388
4793
  Validate3({ params: roleIdParam }),
4389
4794
  ResMsg3("roles.success.deleted"),
4390
4795
  __param8(0, Params()),
4391
- __metadata24("design:type", Function),
4392
- __metadata24("design:paramtypes", [Object]),
4393
- __metadata24("design:returntype", Promise)
4796
+ __metadata25("design:type", Function),
4797
+ __metadata25("design:paramtypes", [Object]),
4798
+ __metadata25("design:returntype", Promise)
4394
4799
  ], RoleController.prototype, "deleteRole", null);
4395
- RoleController = __decorate24([
4800
+ RoleController = __decorate25([
4396
4801
  Controller3("/roles"),
4397
- __metadata24("design:paramtypes", [typeof (_a15 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a15 : Object])
4802
+ __metadata25("design:paramtypes", [typeof (_a16 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a16 : Object])
4398
4803
  ], RoleController);
4399
4804
 
4400
4805
  // src/users/UserController.ts
4401
4806
  import { Validate as Validate4 } from "najm-validation";
4402
- var __decorate25 = function(decorators, target, key, desc) {
4807
+ var __decorate26 = function(decorators, target, key, desc) {
4403
4808
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4404
4809
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4405
4810
  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;
4406
4811
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4407
4812
  };
4408
- var __metadata25 = function(k, v) {
4813
+ var __metadata26 = function(k, v) {
4409
4814
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4410
4815
  };
4411
4816
  var __param9 = function(paramIndex, decorator) {
@@ -4413,7 +4818,7 @@ var __param9 = function(paramIndex, decorator) {
4413
4818
  decorator(target, key, paramIndex);
4414
4819
  };
4415
4820
  };
4416
- var _a16;
4821
+ var _a17;
4417
4822
  var UserController = class UserController2 {
4418
4823
  static {
4419
4824
  __name(this, "UserController");
@@ -4460,75 +4865,75 @@ var UserController = class UserController2 {
4460
4865
  return this.userService.removeRole(params.userId);
4461
4866
  }
4462
4867
  };
4463
- __decorate25([
4868
+ __decorate26([
4464
4869
  Get3(),
4465
4870
  isAdmin(),
4466
4871
  Validate4({ query: userListQuery }),
4467
4872
  ResMsg4("users.success.retrieved"),
4468
4873
  __param9(0, Query()),
4469
- __metadata25("design:type", Function),
4470
- __metadata25("design:paramtypes", [Object]),
4471
- __metadata25("design:returntype", Promise)
4874
+ __metadata26("design:type", Function),
4875
+ __metadata26("design:paramtypes", [Object]),
4876
+ __metadata26("design:returntype", Promise)
4472
4877
  ], UserController.prototype, "getUsers", null);
4473
- __decorate25([
4878
+ __decorate26([
4474
4879
  Get3("/lang"),
4475
4880
  isAuth(),
4476
4881
  ResMsg4("users.success.retrieved"),
4477
- __metadata25("design:type", Function),
4478
- __metadata25("design:paramtypes", []),
4479
- __metadata25("design:returntype", Promise)
4882
+ __metadata26("design:type", Function),
4883
+ __metadata26("design:paramtypes", []),
4884
+ __metadata26("design:returntype", Promise)
4480
4885
  ], UserController.prototype, "getLang", null);
4481
- __decorate25([
4886
+ __decorate26([
4482
4887
  Post4("/lang/:language"),
4483
4888
  isAuth(),
4484
4889
  Validate4({ params: languageParam }),
4485
4890
  ResMsg4("users.success.updated"),
4486
4891
  __param9(0, Params2()),
4487
- __metadata25("design:type", Function),
4488
- __metadata25("design:paramtypes", [Object]),
4489
- __metadata25("design:returntype", Promise)
4892
+ __metadata26("design:type", Function),
4893
+ __metadata26("design:paramtypes", [Object]),
4894
+ __metadata26("design:returntype", Promise)
4490
4895
  ], UserController.prototype, "updateLang", null);
4491
- __decorate25([
4896
+ __decorate26([
4492
4897
  Get3("/:id"),
4493
4898
  isAdmin(),
4494
4899
  Validate4({ params: userIdParam }),
4495
4900
  ResMsg4("users.success.retrieved"),
4496
4901
  __param9(0, Params2()),
4497
- __metadata25("design:type", Function),
4498
- __metadata25("design:paramtypes", [Object]),
4499
- __metadata25("design:returntype", Promise)
4902
+ __metadata26("design:type", Function),
4903
+ __metadata26("design:paramtypes", [Object]),
4904
+ __metadata26("design:returntype", Promise)
4500
4905
  ], UserController.prototype, "getUser", null);
4501
- __decorate25([
4906
+ __decorate26([
4502
4907
  Get3("/email/:email"),
4503
4908
  isAdmin(),
4504
4909
  Validate4({ params: emailParam }),
4505
4910
  ResMsg4("users.success.retrieved"),
4506
4911
  __param9(0, Params2()),
4507
- __metadata25("design:type", Function),
4508
- __metadata25("design:paramtypes", [Object]),
4509
- __metadata25("design:returntype", Promise)
4912
+ __metadata26("design:type", Function),
4913
+ __metadata26("design:paramtypes", [Object]),
4914
+ __metadata26("design:returntype", Promise)
4510
4915
  ], UserController.prototype, "getByEmail", null);
4511
- __decorate25([
4916
+ __decorate26([
4512
4917
  Get3("/role/:userId"),
4513
4918
  isAdmin(),
4514
4919
  Validate4({ params: userIdInParam }),
4515
4920
  ResMsg4("users.success.retrieved"),
4516
4921
  __param9(0, Params2()),
4517
- __metadata25("design:type", Function),
4518
- __metadata25("design:paramtypes", [Object]),
4519
- __metadata25("design:returntype", Promise)
4922
+ __metadata26("design:type", Function),
4923
+ __metadata26("design:paramtypes", [Object]),
4924
+ __metadata26("design:returntype", Promise)
4520
4925
  ], UserController.prototype, "getRole", null);
4521
- __decorate25([
4926
+ __decorate26([
4522
4927
  Post4(),
4523
4928
  isAdmin(),
4524
4929
  Validate4(createUserDto),
4525
- ResMsg4("users.success.created"),
4526
- __param9(0, Body4()),
4527
- __metadata25("design:type", Function),
4528
- __metadata25("design:paramtypes", [Object]),
4529
- __metadata25("design:returntype", Promise)
4930
+ ResMsg4("users.success.created"),
4931
+ __param9(0, Body4()),
4932
+ __metadata26("design:type", Function),
4933
+ __metadata26("design:paramtypes", [Object]),
4934
+ __metadata26("design:returntype", Promise)
4530
4935
  ], UserController.prototype, "create", null);
4531
- __decorate25([
4936
+ __decorate26([
4532
4937
  Put2("/:id"),
4533
4938
  isAdmin(),
4534
4939
  Validate4({
@@ -4538,51 +4943,51 @@ __decorate25([
4538
4943
  ResMsg4("users.success.updated"),
4539
4944
  __param9(0, Params2()),
4540
4945
  __param9(1, Body4()),
4541
- __metadata25("design:type", Function),
4542
- __metadata25("design:paramtypes", [Object, Object]),
4543
- __metadata25("design:returntype", Promise)
4946
+ __metadata26("design:type", Function),
4947
+ __metadata26("design:paramtypes", [Object, Object]),
4948
+ __metadata26("design:returntype", Promise)
4544
4949
  ], UserController.prototype, "update", null);
4545
- __decorate25([
4950
+ __decorate26([
4546
4951
  Delete2("/:id"),
4547
4952
  isAdmin(),
4548
4953
  Validate4({ params: userIdParam }),
4549
4954
  ResMsg4("users.success.deleted"),
4550
4955
  __param9(0, Params2()),
4551
- __metadata25("design:type", Function),
4552
- __metadata25("design:paramtypes", [Object]),
4553
- __metadata25("design:returntype", Promise)
4956
+ __metadata26("design:type", Function),
4957
+ __metadata26("design:paramtypes", [Object]),
4958
+ __metadata26("design:returntype", Promise)
4554
4959
  ], UserController.prototype, "delete", null);
4555
- __decorate25([
4960
+ __decorate26([
4556
4961
  Delete2(),
4557
4962
  isAdmin(),
4558
4963
  ResMsg4("users.success.allDeleted"),
4559
- __metadata25("design:type", Function),
4560
- __metadata25("design:paramtypes", []),
4561
- __metadata25("design:returntype", Promise)
4964
+ __metadata26("design:type", Function),
4965
+ __metadata26("design:paramtypes", []),
4966
+ __metadata26("design:returntype", Promise)
4562
4967
  ], UserController.prototype, "deleteAll", null);
4563
- __decorate25([
4968
+ __decorate26([
4564
4969
  Post4("/assign/:userId/:roleId"),
4565
4970
  isAdmin(),
4566
4971
  Validate4({ params: assignRoleParams }),
4567
4972
  ResMsg4("users.success.updated"),
4568
4973
  __param9(0, Params2()),
4569
- __metadata25("design:type", Function),
4570
- __metadata25("design:paramtypes", [Object]),
4571
- __metadata25("design:returntype", Promise)
4974
+ __metadata26("design:type", Function),
4975
+ __metadata26("design:paramtypes", [Object]),
4976
+ __metadata26("design:returntype", Promise)
4572
4977
  ], UserController.prototype, "assignRole", null);
4573
- __decorate25([
4978
+ __decorate26([
4574
4979
  Delete2("/remove/:userId"),
4575
4980
  isAdmin(),
4576
4981
  Validate4({ params: userIdInParam }),
4577
4982
  ResMsg4("users.success.updated"),
4578
4983
  __param9(0, Params2()),
4579
- __metadata25("design:type", Function),
4580
- __metadata25("design:paramtypes", [Object]),
4581
- __metadata25("design:returntype", Promise)
4984
+ __metadata26("design:type", Function),
4985
+ __metadata26("design:paramtypes", [Object]),
4986
+ __metadata26("design:returntype", Promise)
4582
4987
  ], UserController.prototype, "removeRole", null);
4583
- UserController = __decorate25([
4988
+ UserController = __decorate26([
4584
4989
  Controller4("/users"),
4585
- __metadata25("design:paramtypes", [typeof (_a16 = typeof UserService !== "undefined" && UserService) === "function" ? _a16 : Object])
4990
+ __metadata26("design:paramtypes", [typeof (_a17 = typeof UserService !== "undefined" && UserService) === "function" ? _a17 : Object])
4586
4991
  ], UserController);
4587
4992
 
4588
4993
  // src/permissions/index.ts
@@ -4603,15 +5008,15 @@ __export(permissions_exports, {
4603
5008
 
4604
5009
  // src/permissions/PermissionRepository.ts
4605
5010
  import { eq as eq7, and as and4 } from "drizzle-orm";
4606
- import { Repository as Repository6, Inject as Inject14 } from "najm-core";
5011
+ import { Repository as Repository6, Inject as Inject15 } from "najm-core";
4607
5012
  import { DB as DB6 } from "najm-database";
4608
- var __decorate26 = function(decorators, target, key, desc) {
5013
+ var __decorate27 = function(decorators, target, key, desc) {
4609
5014
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4610
5015
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4611
5016
  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;
4612
5017
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4613
5018
  };
4614
- var __metadata26 = function(k, v) {
5019
+ var __metadata27 = function(k, v) {
4615
5020
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4616
5021
  };
4617
5022
  var PermissionRepository = class PermissionRepository2 {
@@ -4689,29 +5094,29 @@ var PermissionRepository = class PermissionRepository2 {
4689
5094
  return deletedPermissions;
4690
5095
  }
4691
5096
  };
4692
- __decorate26([
5097
+ __decorate27([
4693
5098
  DB6(),
4694
- __metadata26("design:type", Object)
5099
+ __metadata27("design:type", Object)
4695
5100
  ], PermissionRepository.prototype, "db", void 0);
4696
- __decorate26([
4697
- Inject14(AUTH_SCHEMA),
4698
- __metadata26("design:type", Object)
5101
+ __decorate27([
5102
+ Inject15(AUTH_SCHEMA),
5103
+ __metadata27("design:type", Object)
4699
5104
  ], PermissionRepository.prototype, "schema", void 0);
4700
- PermissionRepository = __decorate26([
5105
+ PermissionRepository = __decorate27([
4701
5106
  Repository6()
4702
5107
  ], PermissionRepository);
4703
5108
 
4704
5109
  // src/permissions/PermissionGuards.ts
4705
- import { Injectable as Injectable12 } from "najm-core";
5110
+ import { Injectable as Injectable13 } from "najm-core";
4706
5111
  import { GuardParams as GuardParams2, User as User3 } from "najm-core";
4707
5112
  import { createGuard as createGuard4, composeGuards as composeGuards3 } from "najm-guard";
4708
- var __decorate27 = function(decorators, target, key, desc) {
5113
+ var __decorate28 = function(decorators, target, key, desc) {
4709
5114
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4710
5115
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4711
5116
  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;
4712
5117
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4713
5118
  };
4714
- var __metadata27 = function(k, v) {
5119
+ var __metadata28 = function(k, v) {
4715
5120
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4716
5121
  };
4717
5122
  var __param10 = function(paramIndex, decorator) {
@@ -4747,15 +5152,15 @@ var PermissionGuard = class PermissionGuard2 {
4747
5152
  return false;
4748
5153
  }
4749
5154
  };
4750
- __decorate27([
5155
+ __decorate28([
4751
5156
  __param10(0, GuardParams2()),
4752
5157
  __param10(1, User3("permissions")),
4753
- __metadata27("design:type", Function),
4754
- __metadata27("design:paramtypes", [String, Array]),
4755
- __metadata27("design:returntype", Object)
5158
+ __metadata28("design:type", Function),
5159
+ __metadata28("design:paramtypes", [String, Array]),
5160
+ __metadata28("design:returntype", Object)
4756
5161
  ], PermissionGuard.prototype, "canActivate", null);
4757
- PermissionGuard = __decorate27([
4758
- Injectable12()
5162
+ PermissionGuard = __decorate28([
5163
+ Injectable13()
4759
5164
  ], PermissionGuard);
4760
5165
  var Permission = createGuard4(PermissionGuard);
4761
5166
  var Can = /* @__PURE__ */ __name((permission) => composeGuards3(isAuth(), Permission(permission))(), "Can");
@@ -4766,23 +5171,23 @@ import { Get as Get4, Post as Post5, Put as Put3, Delete as Delete3, ResMsg as R
4766
5171
  import { Params as Params3, Body as Body5 } from "najm-core";
4767
5172
 
4768
5173
  // src/permissions/PermissionService.ts
4769
- import { Injectable as Injectable14 } from "najm-core";
5174
+ import { Injectable as Injectable15 } from "najm-core";
4770
5175
 
4771
5176
  // src/permissions/PermissionValidator.ts
4772
- import { Injectable as Injectable13 } from "najm-core";
5177
+ import { Injectable as Injectable14 } from "najm-core";
4773
5178
  import { I18n as I18n9 } from "najm-i18n";
4774
5179
  import { Err as Err14 } from "najm-core";
4775
- var __decorate28 = function(decorators, target, key, desc) {
5180
+ var __decorate29 = function(decorators, target, key, desc) {
4776
5181
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4777
5182
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4778
5183
  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;
4779
5184
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4780
5185
  };
4781
- var __metadata28 = function(k, v) {
5186
+ var __metadata29 = function(k, v) {
4782
5187
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4783
5188
  };
4784
- var _a17;
4785
- var _b10;
5189
+ var _a18;
5190
+ var _b11;
4786
5191
  var PermissionValidator = class PermissionValidator2 {
4787
5192
  static {
4788
5193
  __name(this, "PermissionValidator");
@@ -4849,28 +5254,30 @@ var PermissionValidator = class PermissionValidator2 {
4849
5254
  }
4850
5255
  }
4851
5256
  };
4852
- __decorate28([
5257
+ __decorate29([
4853
5258
  I18n9("permissions"),
4854
- __metadata28("design:type", Object)
5259
+ __metadata29("design:type", Object)
4855
5260
  ], PermissionValidator.prototype, "t", void 0);
4856
- PermissionValidator = __decorate28([
4857
- Injectable13(),
4858
- __metadata28("design:paramtypes", [typeof (_a17 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a17 : Object, typeof (_b10 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b10 : Object])
5261
+ PermissionValidator = __decorate29([
5262
+ Injectable14(),
5263
+ __metadata29("design:paramtypes", [typeof (_a18 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a18 : Object, typeof (_b11 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b11 : Object])
4859
5264
  ], PermissionValidator);
4860
5265
 
4861
5266
  // src/permissions/PermissionService.ts
4862
- var __decorate29 = function(decorators, target, key, desc) {
5267
+ var __decorate30 = function(decorators, target, key, desc) {
4863
5268
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4864
5269
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4865
5270
  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;
4866
5271
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4867
5272
  };
4868
- var __metadata29 = function(k, v) {
5273
+ var __metadata30 = function(k, v) {
4869
5274
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4870
5275
  };
4871
- var _a18;
4872
- var _b11;
5276
+ var _a19;
5277
+ var _b12;
4873
5278
  var _c8;
5279
+ var _d7;
5280
+ var _e6;
4874
5281
  var PermissionService = class PermissionService2 {
4875
5282
  static {
4876
5283
  __name(this, "PermissionService");
@@ -4878,10 +5285,30 @@ var PermissionService = class PermissionService2 {
4878
5285
  permissionRepository;
4879
5286
  permissionValidator;
4880
5287
  roleService;
4881
- constructor(permissionRepository, permissionValidator, roleService) {
5288
+ userRepository;
5289
+ sessionInvalidation;
5290
+ constructor(permissionRepository, permissionValidator, roleService, userRepository, sessionInvalidation) {
4882
5291
  this.permissionRepository = permissionRepository;
4883
5292
  this.permissionValidator = permissionValidator;
4884
5293
  this.roleService = roleService;
5294
+ this.userRepository = userRepository;
5295
+ this.sessionInvalidation = sessionInvalidation;
5296
+ }
5297
+ /**
5298
+ * End the sessions of everyone holding a role whose permission set changed.
5299
+ *
5300
+ * Access tokens and signed session snapshots both carry permissions as
5301
+ * claims, so a permission removed from a role stays exercisable until the
5302
+ * sessions that captured it end. This is an infrequent administrative
5303
+ * action, and the work is proportional to the role's membership.
5304
+ */
5305
+ async invalidateRoleHolders(roleId) {
5306
+ if (!this.userRepository || !this.sessionInvalidation)
5307
+ return;
5308
+ const userIds = await this.userRepository.getIdsByRole(roleId);
5309
+ for (const userId of userIds) {
5310
+ await this.sessionInvalidation.invalidateAccessTokens(userId);
5311
+ }
4885
5312
  }
4886
5313
  async getAll() {
4887
5314
  return await this.permissionRepository.getAll();
@@ -4918,10 +5345,14 @@ var PermissionService = class PermissionService2 {
4918
5345
  }
4919
5346
  async assignPermissionToRole(roleId, permissionId) {
4920
5347
  await this.permissionValidator.checkRoleHasPermission(roleId, permissionId);
4921
- return await this.permissionRepository.assignPermissionToRole(roleId, permissionId);
5348
+ const assigned = await this.permissionRepository.assignPermissionToRole(roleId, permissionId);
5349
+ await this.invalidateRoleHolders(roleId);
5350
+ return assigned;
4922
5351
  }
4923
5352
  async removePermissionFromRole(roleId, permissionId) {
4924
- return await this.permissionRepository.removePermissionFromRole(roleId, permissionId);
5353
+ const removed = await this.permissionRepository.removePermissionFromRole(roleId, permissionId);
5354
+ await this.invalidateRoleHolders(roleId);
5355
+ return removed;
4925
5356
  }
4926
5357
  async seedDefaultPermissions(defaultPermissions) {
4927
5358
  const created = [];
@@ -4975,9 +5406,9 @@ var PermissionService = class PermissionService2 {
4975
5406
  return await this.permissionRepository.deleteAll();
4976
5407
  }
4977
5408
  };
4978
- PermissionService = __decorate29([
4979
- Injectable14(),
4980
- __metadata29("design:paramtypes", [typeof (_a18 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a18 : Object, typeof (_b11 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b11 : Object, typeof (_c8 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c8 : Object])
5409
+ PermissionService = __decorate30([
5410
+ Injectable15(),
5411
+ __metadata30("design:paramtypes", [typeof (_a19 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a19 : Object, typeof (_b12 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b12 : Object, typeof (_c8 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c8 : Object, typeof (_d7 = typeof UserRepository !== "undefined" && UserRepository) === "function" ? _d7 : Object, typeof (_e6 = typeof SessionInvalidationService !== "undefined" && SessionInvalidationService) === "function" ? _e6 : Object])
4981
5412
  ], PermissionService);
4982
5413
 
4983
5414
  // src/permissions/PermissionController.ts
@@ -5010,13 +5441,13 @@ var checkPermissionDto = z3.object({
5010
5441
  });
5011
5442
 
5012
5443
  // src/permissions/PermissionController.ts
5013
- var __decorate30 = function(decorators, target, key, desc) {
5444
+ var __decorate31 = function(decorators, target, key, desc) {
5014
5445
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5015
5446
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5016
5447
  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;
5017
5448
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5018
5449
  };
5019
- var __metadata30 = function(k, v) {
5450
+ var __metadata31 = function(k, v) {
5020
5451
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5021
5452
  };
5022
5453
  var __param11 = function(paramIndex, decorator) {
@@ -5024,7 +5455,7 @@ var __param11 = function(paramIndex, decorator) {
5024
5455
  decorator(target, key, paramIndex);
5025
5456
  };
5026
5457
  };
5027
- var _a19;
5458
+ var _a20;
5028
5459
  var PermissionController = class PermissionController2 {
5029
5460
  static {
5030
5461
  __name(this, "PermissionController");
@@ -5070,32 +5501,32 @@ var PermissionController = class PermissionController2 {
5070
5501
  return this.permissionService.deleteAll();
5071
5502
  }
5072
5503
  };
5073
- __decorate30([
5504
+ __decorate31([
5074
5505
  Get4(),
5075
5506
  ResMsg5("permissions.success.retrieved"),
5076
- __metadata30("design:type", Function),
5077
- __metadata30("design:paramtypes", []),
5078
- __metadata30("design:returntype", Promise)
5507
+ __metadata31("design:type", Function),
5508
+ __metadata31("design:paramtypes", []),
5509
+ __metadata31("design:returntype", Promise)
5079
5510
  ], PermissionController.prototype, "getPermissions", null);
5080
- __decorate30([
5511
+ __decorate31([
5081
5512
  Get4("/:id"),
5082
5513
  Validate5({ params: permissionIdParam }),
5083
5514
  ResMsg5("permissions.success.retrieved"),
5084
5515
  __param11(0, Params3()),
5085
- __metadata30("design:type", Function),
5086
- __metadata30("design:paramtypes", [Object]),
5087
- __metadata30("design:returntype", Promise)
5516
+ __metadata31("design:type", Function),
5517
+ __metadata31("design:paramtypes", [Object]),
5518
+ __metadata31("design:returntype", Promise)
5088
5519
  ], PermissionController.prototype, "getPermission", null);
5089
- __decorate30([
5520
+ __decorate31([
5090
5521
  Post5(),
5091
5522
  Validate5(createPermissionDto),
5092
5523
  ResMsg5({ message: "Permission created successfully", status: 201 }),
5093
5524
  __param11(0, Body5()),
5094
- __metadata30("design:type", Function),
5095
- __metadata30("design:paramtypes", [Object]),
5096
- __metadata30("design:returntype", Promise)
5525
+ __metadata31("design:type", Function),
5526
+ __metadata31("design:paramtypes", [Object]),
5527
+ __metadata31("design:returntype", Promise)
5097
5528
  ], PermissionController.prototype, "create", null);
5098
- __decorate30([
5529
+ __decorate31([
5099
5530
  Put3("/:id"),
5100
5531
  Validate5({
5101
5532
  params: permissionIdParam,
@@ -5104,72 +5535,73 @@ __decorate30([
5104
5535
  ResMsg5("permissions.success.updated"),
5105
5536
  __param11(0, Params3()),
5106
5537
  __param11(1, Body5()),
5107
- __metadata30("design:type", Function),
5108
- __metadata30("design:paramtypes", [Object, Object]),
5109
- __metadata30("design:returntype", Promise)
5538
+ __metadata31("design:type", Function),
5539
+ __metadata31("design:paramtypes", [Object, Object]),
5540
+ __metadata31("design:returntype", Promise)
5110
5541
  ], PermissionController.prototype, "update", null);
5111
- __decorate30([
5542
+ __decorate31([
5112
5543
  Delete3("/:id"),
5113
5544
  Validate5({ params: permissionIdParam }),
5114
5545
  ResMsg5("permissions.success.deleted"),
5115
5546
  __param11(0, Params3()),
5116
- __metadata30("design:type", Function),
5117
- __metadata30("design:paramtypes", [Object]),
5118
- __metadata30("design:returntype", Promise)
5547
+ __metadata31("design:type", Function),
5548
+ __metadata31("design:paramtypes", [Object]),
5549
+ __metadata31("design:returntype", Promise)
5119
5550
  ], PermissionController.prototype, "delete", null);
5120
- __decorate30([
5551
+ __decorate31([
5121
5552
  Get4("/role/:id"),
5122
5553
  Validate5({ params: roleIdParam }),
5123
5554
  ResMsg5("permissions.success.retrieved"),
5124
5555
  __param11(0, Params3()),
5125
- __metadata30("design:type", Function),
5126
- __metadata30("design:paramtypes", [Object]),
5127
- __metadata30("design:returntype", Promise)
5556
+ __metadata31("design:type", Function),
5557
+ __metadata31("design:paramtypes", [Object]),
5558
+ __metadata31("design:returntype", Promise)
5128
5559
  ], PermissionController.prototype, "getByRole", null);
5129
- __decorate30([
5560
+ __decorate31([
5130
5561
  Get4("/roles/:id"),
5131
5562
  Validate5({ params: permissionIdParam }),
5132
5563
  ResMsg5("permissions.success.retrieved"),
5133
5564
  __param11(0, Params3()),
5134
- __metadata30("design:type", Function),
5135
- __metadata30("design:paramtypes", [Object]),
5136
- __metadata30("design:returntype", Promise)
5565
+ __metadata31("design:type", Function),
5566
+ __metadata31("design:paramtypes", [Object]),
5567
+ __metadata31("design:returntype", Promise)
5137
5568
  ], PermissionController.prototype, "getRolesByPermission", null);
5138
- __decorate30([
5569
+ __decorate31([
5139
5570
  Post5("/assign/:roleId/:permissionId"),
5140
5571
  Validate5({ params: assignPermissionDto }),
5141
5572
  ResMsg5("permissions.success.assigned"),
5142
5573
  __param11(0, Params3()),
5143
- __metadata30("design:type", Function),
5144
- __metadata30("design:paramtypes", [Object]),
5145
- __metadata30("design:returntype", Promise)
5574
+ __metadata31("design:type", Function),
5575
+ __metadata31("design:paramtypes", [Object]),
5576
+ __metadata31("design:returntype", Promise)
5146
5577
  ], PermissionController.prototype, "assignToRole", null);
5147
- __decorate30([
5578
+ __decorate31([
5148
5579
  Delete3("/remove/:roleId/:permissionId"),
5149
5580
  Validate5({ params: assignPermissionDto }),
5150
5581
  ResMsg5("permissions.success.removed"),
5151
5582
  __param11(0, Params3()),
5152
- __metadata30("design:type", Function),
5153
- __metadata30("design:paramtypes", [Object]),
5154
- __metadata30("design:returntype", Promise)
5583
+ __metadata31("design:type", Function),
5584
+ __metadata31("design:paramtypes", [Object]),
5585
+ __metadata31("design:returntype", Promise)
5155
5586
  ], PermissionController.prototype, "removeFromRole", null);
5156
- __decorate30([
5587
+ __decorate31([
5157
5588
  Delete3(),
5158
5589
  isAdmin(),
5159
5590
  ResMsg5("permissions.success.allDeleted"),
5160
- __metadata30("design:type", Function),
5161
- __metadata30("design:paramtypes", []),
5162
- __metadata30("design:returntype", Promise)
5591
+ __metadata31("design:type", Function),
5592
+ __metadata31("design:paramtypes", []),
5593
+ __metadata31("design:returntype", Promise)
5163
5594
  ], PermissionController.prototype, "deleteAll", null);
5164
- PermissionController = __decorate30([
5595
+ PermissionController = __decorate31([
5165
5596
  Controller5("/permissions"),
5166
5597
  isAdmin(),
5167
- __metadata30("design:paramtypes", [typeof (_a19 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a19 : Object])
5598
+ __metadata31("design:paramtypes", [typeof (_a20 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a20 : Object])
5168
5599
  ], PermissionController);
5169
5600
 
5170
5601
  // src/tokens/index.ts
5171
5602
  var tokens_exports = {};
5172
5603
  __export(tokens_exports, {
5604
+ SessionInvalidationService: () => SessionInvalidationService,
5173
5605
  TokenRepository: () => TokenRepository,
5174
5606
  TokenService: () => TokenService,
5175
5607
  createTokenDto: () => createTokenDto,
@@ -5371,15 +5803,15 @@ function own(table, opts) {
5371
5803
  __name(own, "own");
5372
5804
 
5373
5805
  // src/ownership/configureOwnership.ts
5374
- import { Injectable as Injectable15, Inject as Inject15, User as User4, Body as Body6, Params as Params4 } from "najm-core";
5806
+ import { Injectable as Injectable16, Inject as Inject16, User as User4, Body as Body6, Params as Params4 } from "najm-core";
5375
5807
  import { createGuard as createGuard5, composeGuards as composeGuards4 } from "najm-guard";
5376
- var __decorate31 = function(decorators, target, key, desc) {
5808
+ var __decorate32 = function(decorators, target, key, desc) {
5377
5809
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5378
5810
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5379
5811
  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;
5380
5812
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5381
5813
  };
5382
- var __metadata31 = function(k, v) {
5814
+ var __metadata32 = function(k, v) {
5383
5815
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5384
5816
  };
5385
5817
  var __param12 = function(paramIndex, decorator) {
@@ -5399,7 +5831,7 @@ function toSingular(plural) {
5399
5831
  }
5400
5832
  __name(toSingular, "toSingular");
5401
5833
  function createResourceGuards(ownershipClass, resourceType, resource, options) {
5402
- var _a28, _b15;
5834
+ var _a29, _b16;
5403
5835
  const writeGuard = options?.adminGuard ?? isAdmin;
5404
5836
  let AccessGuard = class AccessGuard {
5405
5837
  static {
@@ -5411,19 +5843,19 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
5411
5843
  return allowed ? { owner: user } : false;
5412
5844
  }
5413
5845
  };
5414
- __decorate31([
5415
- Inject15(ownershipClass),
5416
- __metadata31("design:type", Object)
5846
+ __decorate32([
5847
+ Inject16(ownershipClass),
5848
+ __metadata32("design:type", Object)
5417
5849
  ], AccessGuard.prototype, "ownership", void 0);
5418
- __decorate31([
5850
+ __decorate32([
5419
5851
  __param12(0, User4()),
5420
5852
  __param12(1, Params4("id")),
5421
- __metadata31("design:type", Function),
5422
- __metadata31("design:paramtypes", [Object, String]),
5423
- __metadata31("design:returntype", typeof (_a28 = typeof Promise !== "undefined" && Promise) === "function" ? _a28 : Object)
5853
+ __metadata32("design:type", Function),
5854
+ __metadata32("design:paramtypes", [Object, String]),
5855
+ __metadata32("design:returntype", typeof (_a29 = typeof Promise !== "undefined" && Promise) === "function" ? _a29 : Object)
5424
5856
  ], AccessGuard.prototype, "canActivate", null);
5425
- AccessGuard = __decorate31([
5426
- Injectable15()
5857
+ AccessGuard = __decorate32([
5858
+ Injectable16()
5427
5859
  ], AccessGuard);
5428
5860
  let ListGuard = class ListGuard {
5429
5861
  static {
@@ -5435,18 +5867,18 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
5435
5867
  return { filter: ids };
5436
5868
  }
5437
5869
  };
5438
- __decorate31([
5439
- Inject15(ownershipClass),
5440
- __metadata31("design:type", Object)
5870
+ __decorate32([
5871
+ Inject16(ownershipClass),
5872
+ __metadata32("design:type", Object)
5441
5873
  ], ListGuard.prototype, "ownership", void 0);
5442
- __decorate31([
5874
+ __decorate32([
5443
5875
  __param12(0, User4()),
5444
- __metadata31("design:type", Function),
5445
- __metadata31("design:paramtypes", [Object]),
5446
- __metadata31("design:returntype", typeof (_b15 = typeof Promise !== "undefined" && Promise) === "function" ? _b15 : Object)
5876
+ __metadata32("design:type", Function),
5877
+ __metadata32("design:paramtypes", [Object]),
5878
+ __metadata32("design:returntype", typeof (_b16 = typeof Promise !== "undefined" && Promise) === "function" ? _b16 : Object)
5447
5879
  ], ListGuard.prototype, "canActivate", null);
5448
- ListGuard = __decorate31([
5449
- Injectable15()
5880
+ ListGuard = __decorate32([
5881
+ Injectable16()
5450
5882
  ], ListGuard);
5451
5883
  const access = createGuard5(AccessGuard);
5452
5884
  const list = createGuard5(ListGuard);
@@ -5577,11 +6009,11 @@ function configureOwnership(config) {
5577
6009
  }
5578
6010
  }
5579
6011
  };
5580
- GeneratedOwnershipService = __decorate31([
5581
- Injectable15()
6012
+ GeneratedOwnershipService = __decorate32([
6013
+ Injectable16()
5582
6014
  ], GeneratedOwnershipService);
5583
6015
  function bodyGuard(resourceType, bodyField, optional = false) {
5584
- var _a28;
6016
+ var _a29;
5585
6017
  let BodyAccessGuard = class BodyAccessGuard {
5586
6018
  static {
5587
6019
  __name(this, "BodyAccessGuard");
@@ -5594,19 +6026,19 @@ function configureOwnership(config) {
5594
6026
  return this.ownership.canAccess(user, resourceType, id);
5595
6027
  }
5596
6028
  };
5597
- __decorate31([
5598
- Inject15(GeneratedOwnershipService),
5599
- __metadata31("design:type", GeneratedOwnershipService)
6029
+ __decorate32([
6030
+ Inject16(GeneratedOwnershipService),
6031
+ __metadata32("design:type", GeneratedOwnershipService)
5600
6032
  ], BodyAccessGuard.prototype, "ownership", void 0);
5601
- __decorate31([
6033
+ __decorate32([
5602
6034
  __param12(0, User4()),
5603
6035
  __param12(1, Body6()),
5604
- __metadata31("design:type", Function),
5605
- __metadata31("design:paramtypes", [Object, Object]),
5606
- __metadata31("design:returntype", typeof (_a28 = typeof Promise !== "undefined" && Promise) === "function" ? _a28 : Object)
6036
+ __metadata32("design:type", Function),
6037
+ __metadata32("design:paramtypes", [Object, Object]),
6038
+ __metadata32("design:returntype", typeof (_a29 = typeof Promise !== "undefined" && Promise) === "function" ? _a29 : Object)
5607
6039
  ], BodyAccessGuard.prototype, "canActivate", null);
5608
- BodyAccessGuard = __decorate31([
5609
- Injectable15()
6040
+ BodyAccessGuard = __decorate32([
6041
+ Injectable16()
5610
6042
  ], BodyAccessGuard);
5611
6043
  return createGuard5(BodyAccessGuard);
5612
6044
  }
@@ -5721,18 +6153,18 @@ __name(Policy, "Policy");
5721
6153
  // src/ownership/OwnedDecorator.ts
5722
6154
  import "reflect-metadata";
5723
6155
  import { sql as sql5, and as and5 } from "drizzle-orm";
5724
- import { Injectable as Injectable16, Inject as Inject16, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
6156
+ import { Injectable as Injectable17, Inject as Inject17, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
5725
6157
  import { USER as USER2 } from "najm-guard";
5726
- var __decorate32 = function(decorators, target, key, desc) {
6158
+ var __decorate33 = function(decorators, target, key, desc) {
5727
6159
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5728
6160
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5729
6161
  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;
5730
6162
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5731
6163
  };
5732
- var __metadata32 = function(k, v) {
6164
+ var __metadata33 = function(k, v) {
5733
6165
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
5734
6166
  };
5735
- var _a20;
6167
+ var _a21;
5736
6168
  var OWNED_META = Symbol.for("najm:owned");
5737
6169
  var ScopeContext = class ScopeContext2 {
5738
6170
  static {
@@ -5764,18 +6196,18 @@ var ScopeContext = class ScopeContext2 {
5764
6196
  }
5765
6197
  }
5766
6198
  };
5767
- __decorate32([
6199
+ __decorate33([
5768
6200
  DI3(),
5769
- __metadata32("design:type", typeof (_a20 = typeof Container2 !== "undefined" && Container2) === "function" ? _a20 : Object)
6201
+ __metadata33("design:type", typeof (_a21 = typeof Container2 !== "undefined" && Container2) === "function" ? _a21 : Object)
5770
6202
  ], ScopeContext.prototype, "container", void 0);
5771
- ScopeContext = __decorate32([
5772
- Injectable16()
6203
+ ScopeContext = __decorate33([
6204
+ Injectable17()
5773
6205
  ], ScopeContext);
5774
6206
  function Owned(token) {
5775
6207
  return function(target) {
5776
6208
  Reflect.defineMetadata(OWNED_META, token, target);
5777
6209
  const proto = target.prototype;
5778
- Inject16(ScopeContext)(proto, "_scopeCtx");
6210
+ Inject17(ScopeContext)(proto, "_scopeCtx");
5779
6211
  function getUser(self) {
5780
6212
  return self._scopeCtx?.getUser() ?? null;
5781
6213
  }
@@ -5985,7 +6417,7 @@ __name(getAuthLocale, "getAuthLocale");
5985
6417
  var AUTH_SUPPORTED_LANGUAGES = Object.keys(AUTH_LOCALES);
5986
6418
 
5987
6419
  // src/oauth/google/GoogleOAuthProvider.ts
5988
- import { Inject as Inject18, Injectable as Injectable18 } from "najm-core";
6420
+ import { Inject as Inject19, Injectable as Injectable19 } from "najm-core";
5989
6421
 
5990
6422
  // src/oauth/types.ts
5991
6423
  var OAuthFlowError = class extends Error {
@@ -6003,15 +6435,15 @@ var OAuthFlowError = class extends Error {
6003
6435
  };
6004
6436
 
6005
6437
  // src/oauth/google/GoogleTokenVerifier.ts
6006
- import { Inject as Inject17, Injectable as Injectable17 } from "najm-core";
6438
+ import { Inject as Inject18, Injectable as Injectable18 } from "najm-core";
6007
6439
  import { createRemoteJWKSet, jwtVerify } from "jose";
6008
- var __decorate33 = function(decorators, target, key, desc) {
6440
+ var __decorate34 = function(decorators, target, key, desc) {
6009
6441
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6010
6442
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6011
6443
  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;
6012
6444
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6013
6445
  };
6014
- var __metadata33 = function(k, v) {
6446
+ var __metadata34 = function(k, v) {
6015
6447
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6016
6448
  };
6017
6449
  var GOOGLE_JWKS = createRemoteJWKSet(new URL("https://www.googleapis.com/oauth2/v3/certs"));
@@ -6063,25 +6495,25 @@ var GoogleTokenVerifier = class GoogleTokenVerifier2 {
6063
6495
  return google;
6064
6496
  }
6065
6497
  };
6066
- __decorate33([
6067
- Inject17(AUTH_CONFIG),
6068
- __metadata33("design:type", Object)
6498
+ __decorate34([
6499
+ Inject18(AUTH_CONFIG),
6500
+ __metadata34("design:type", Object)
6069
6501
  ], GoogleTokenVerifier.prototype, "config", void 0);
6070
- GoogleTokenVerifier = __decorate33([
6071
- Injectable17()
6502
+ GoogleTokenVerifier = __decorate34([
6503
+ Injectable18()
6072
6504
  ], GoogleTokenVerifier);
6073
6505
 
6074
6506
  // src/oauth/google/GoogleOAuthProvider.ts
6075
- var __decorate34 = function(decorators, target, key, desc) {
6507
+ var __decorate35 = function(decorators, target, key, desc) {
6076
6508
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6077
6509
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6078
6510
  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;
6079
6511
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6080
6512
  };
6081
- var __metadata34 = function(k, v) {
6513
+ var __metadata35 = function(k, v) {
6082
6514
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6083
6515
  };
6084
- var _a21;
6516
+ var _a22;
6085
6517
  var AUTHORIZATION_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth";
6086
6518
  var TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token";
6087
6519
  var GoogleOAuthProvider = class GoogleOAuthProvider2 {
@@ -6149,24 +6581,24 @@ var GoogleOAuthProvider = class GoogleOAuthProvider2 {
6149
6581
  return google;
6150
6582
  }
6151
6583
  };
6152
- __decorate34([
6153
- Inject18(AUTH_CONFIG),
6154
- __metadata34("design:type", Object)
6584
+ __decorate35([
6585
+ Inject19(AUTH_CONFIG),
6586
+ __metadata35("design:type", Object)
6155
6587
  ], GoogleOAuthProvider.prototype, "config", void 0);
6156
- GoogleOAuthProvider = __decorate34([
6157
- Injectable18(),
6158
- __metadata34("design:paramtypes", [typeof (_a21 = typeof GoogleTokenVerifier !== "undefined" && GoogleTokenVerifier) === "function" ? _a21 : Object])
6588
+ GoogleOAuthProvider = __decorate35([
6589
+ Injectable19(),
6590
+ __metadata35("design:paramtypes", [typeof (_a22 = typeof GoogleTokenVerifier !== "undefined" && GoogleTokenVerifier) === "function" ? _a22 : Object])
6159
6591
  ], GoogleOAuthProvider);
6160
6592
 
6161
6593
  // src/oauth/github/GitHubOAuthProvider.ts
6162
- import { Inject as Inject19, Injectable as Injectable19 } from "najm-core";
6163
- var __decorate35 = function(decorators, target, key, desc) {
6594
+ import { Inject as Inject20, Injectable as Injectable20 } from "najm-core";
6595
+ var __decorate36 = function(decorators, target, key, desc) {
6164
6596
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6165
6597
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6166
6598
  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;
6167
6599
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6168
6600
  };
6169
- var __metadata35 = function(k, v) {
6601
+ var __metadata36 = function(k, v) {
6170
6602
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6171
6603
  };
6172
6604
  var AUTHORIZATION_ENDPOINT2 = "https://github.com/login/oauth/authorize";
@@ -6282,12 +6714,12 @@ var GitHubOAuthProvider = class GitHubOAuthProvider2 {
6282
6714
  return github;
6283
6715
  }
6284
6716
  };
6285
- __decorate35([
6286
- Inject19(AUTH_CONFIG),
6287
- __metadata35("design:type", Object)
6717
+ __decorate36([
6718
+ Inject20(AUTH_CONFIG),
6719
+ __metadata36("design:type", Object)
6288
6720
  ], GitHubOAuthProvider.prototype, "config", void 0);
6289
- GitHubOAuthProvider = __decorate35([
6290
- Injectable19()
6721
+ GitHubOAuthProvider = __decorate36([
6722
+ Injectable20()
6291
6723
  ], GitHubOAuthProvider);
6292
6724
 
6293
6725
  // src/oauth/GitHubOAuthController.ts
@@ -6296,24 +6728,24 @@ import { Controller as Controller6, Ctx as Ctx2, Get as Get5, Post as Post6, Que
6296
6728
  import { RateLimit as RateLimit3 } from "najm-rate";
6297
6729
 
6298
6730
  // src/oauth/OAuthService.ts
6299
- import { Inject as Inject22, Injectable as Injectable22, Log as Log2 } from "najm-core";
6731
+ import { Err as Err15, Inject as Inject23, Injectable as Injectable23, Log as Log2 } from "najm-core";
6300
6732
 
6301
6733
  // src/oauth/OAuthAccountService.ts
6302
6734
  import { randomBytes as randomBytes3 } from "crypto";
6303
- import { Inject as Inject21, Injectable as Injectable20 } from "najm-core";
6735
+ import { Inject as Inject22, Injectable as Injectable21 } from "najm-core";
6304
6736
  import { Transaction as Transaction5 } from "najm-database";
6305
6737
 
6306
6738
  // src/oauth/OAuthAccountRepository.ts
6307
6739
  import { and as and6, eq as eq9 } from "drizzle-orm";
6308
- import { Inject as Inject20, Repository as Repository7 } from "najm-core";
6740
+ import { Inject as Inject21, Repository as Repository7 } from "najm-core";
6309
6741
  import { DB as DB7 } from "najm-database";
6310
- var __decorate36 = function(decorators, target, key, desc) {
6742
+ var __decorate37 = function(decorators, target, key, desc) {
6311
6743
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6312
6744
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6313
6745
  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;
6314
6746
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6315
6747
  };
6316
- var __metadata36 = function(k, v) {
6748
+ var __metadata37 = function(k, v) {
6317
6749
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6318
6750
  };
6319
6751
  var OAuthAccountRepository = class OAuthAccountRepository2 {
@@ -6341,32 +6773,32 @@ var OAuthAccountRepository = class OAuthAccountRepository2 {
6341
6773
  return account;
6342
6774
  }
6343
6775
  };
6344
- __decorate36([
6776
+ __decorate37([
6345
6777
  DB7(),
6346
- __metadata36("design:type", Object)
6778
+ __metadata37("design:type", Object)
6347
6779
  ], OAuthAccountRepository.prototype, "db", void 0);
6348
- __decorate36([
6349
- Inject20(AUTH_SCHEMA),
6350
- __metadata36("design:type", Object)
6780
+ __decorate37([
6781
+ Inject21(AUTH_SCHEMA),
6782
+ __metadata37("design:type", Object)
6351
6783
  ], OAuthAccountRepository.prototype, "schema", void 0);
6352
- OAuthAccountRepository = __decorate36([
6784
+ OAuthAccountRepository = __decorate37([
6353
6785
  Repository7()
6354
6786
  ], OAuthAccountRepository);
6355
6787
 
6356
6788
  // src/oauth/OAuthAccountService.ts
6357
- var __decorate37 = function(decorators, target, key, desc) {
6789
+ var __decorate38 = function(decorators, target, key, desc) {
6358
6790
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6359
6791
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6360
6792
  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;
6361
6793
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6362
6794
  };
6363
- var __metadata37 = function(k, v) {
6795
+ var __metadata38 = function(k, v) {
6364
6796
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6365
6797
  };
6366
- var _a22;
6367
- var _b12;
6798
+ var _a23;
6799
+ var _b13;
6368
6800
  var _c9;
6369
- var _d7;
6801
+ var _d8;
6370
6802
  var OAuthAccountService = class OAuthAccountService2 {
6371
6803
  static {
6372
6804
  __name(this, "OAuthAccountService");
@@ -6442,42 +6874,42 @@ var OAuthAccountService = class OAuthAccountService2 {
6442
6874
  return providerConfig;
6443
6875
  }
6444
6876
  };
6445
- __decorate37([
6446
- Inject21(AUTH_CONFIG),
6447
- __metadata37("design:type", Object)
6877
+ __decorate38([
6878
+ Inject22(AUTH_CONFIG),
6879
+ __metadata38("design:type", Object)
6448
6880
  ], OAuthAccountService.prototype, "config", void 0);
6449
- __decorate37([
6881
+ __decorate38([
6450
6882
  Transaction5(),
6451
- __metadata37("design:type", Function),
6452
- __metadata37("design:paramtypes", [Object]),
6453
- __metadata37("design:returntype", typeof (_c9 = typeof Promise !== "undefined" && Promise) === "function" ? _c9 : Object)
6883
+ __metadata38("design:type", Function),
6884
+ __metadata38("design:paramtypes", [Object]),
6885
+ __metadata38("design:returntype", typeof (_c9 = typeof Promise !== "undefined" && Promise) === "function" ? _c9 : Object)
6454
6886
  ], OAuthAccountService.prototype, "resolveForLogin", null);
6455
- __decorate37([
6887
+ __decorate38([
6456
6888
  Transaction5(),
6457
- __metadata37("design:type", Function),
6458
- __metadata37("design:paramtypes", [String, Object]),
6459
- __metadata37("design:returntype", typeof (_d7 = typeof Promise !== "undefined" && Promise) === "function" ? _d7 : Object)
6889
+ __metadata38("design:type", Function),
6890
+ __metadata38("design:paramtypes", [String, Object]),
6891
+ __metadata38("design:returntype", typeof (_d8 = typeof Promise !== "undefined" && Promise) === "function" ? _d8 : Object)
6460
6892
  ], OAuthAccountService.prototype, "linkUser", null);
6461
- OAuthAccountService = __decorate37([
6462
- Injectable20(),
6463
- __metadata37("design:paramtypes", [typeof (_a22 = typeof OAuthAccountRepository !== "undefined" && OAuthAccountRepository) === "function" ? _a22 : Object, typeof (_b12 = typeof UserService !== "undefined" && UserService) === "function" ? _b12 : Object])
6893
+ OAuthAccountService = __decorate38([
6894
+ Injectable21(),
6895
+ __metadata38("design:paramtypes", [typeof (_a23 = typeof OAuthAccountRepository !== "undefined" && OAuthAccountRepository) === "function" ? _a23 : Object, typeof (_b13 = typeof UserService !== "undefined" && UserService) === "function" ? _b13 : Object])
6464
6896
  ], OAuthAccountService);
6465
6897
 
6466
6898
  // src/oauth/OAuthStateService.ts
6467
6899
  import { createHash as createHash4, randomBytes as randomBytes4, timingSafeEqual } from "crypto";
6468
- import { Injectable as Injectable21 } from "najm-core";
6900
+ import { Injectable as Injectable22 } from "najm-core";
6469
6901
  import { CookieService as CookieService3 } from "najm-cookies";
6470
- var __decorate38 = function(decorators, target, key, desc) {
6902
+ var __decorate39 = function(decorators, target, key, desc) {
6471
6903
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6472
6904
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6473
6905
  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;
6474
6906
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6475
6907
  };
6476
- var __metadata38 = function(k, v) {
6908
+ var __metadata39 = function(k, v) {
6477
6909
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6478
6910
  };
6479
- var _a23;
6480
- var _b13;
6911
+ var _a24;
6912
+ var _b14;
6481
6913
  var ATTEMPT_TTL_MS = 10 * 60 * 1e3;
6482
6914
  var COOKIE_PREFIX = "najm.oauth.";
6483
6915
  var OAuthStateService = class OAuthStateService2 {
@@ -6566,26 +6998,26 @@ var OAuthStateService = class OAuthStateService2 {
6566
6998
  return /^[A-Za-z0-9_-]{40,128}$/.test(state);
6567
6999
  }
6568
7000
  };
6569
- OAuthStateService = __decorate38([
6570
- Injectable21(),
6571
- __metadata38("design:paramtypes", [typeof (_a23 = typeof CookieService3 !== "undefined" && CookieService3) === "function" ? _a23 : Object, typeof (_b13 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b13 : Object])
7001
+ OAuthStateService = __decorate39([
7002
+ Injectable22(),
7003
+ __metadata39("design:paramtypes", [typeof (_a24 = typeof CookieService3 !== "undefined" && CookieService3) === "function" ? _a24 : Object, typeof (_b14 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b14 : Object])
6572
7004
  ], OAuthStateService);
6573
7005
 
6574
7006
  // src/oauth/OAuthService.ts
6575
- var __decorate39 = function(decorators, target, key, desc) {
7007
+ var __decorate40 = function(decorators, target, key, desc) {
6576
7008
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6577
7009
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6578
7010
  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;
6579
7011
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6580
7012
  };
6581
- var __metadata39 = function(k, v) {
7013
+ var __metadata40 = function(k, v) {
6582
7014
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6583
7015
  };
6584
- var _a24;
6585
- var _b14;
7016
+ var _a25;
7017
+ var _b15;
6586
7018
  var _c10;
6587
- var _d8;
6588
- var _e5;
7019
+ var _d9;
7020
+ var _e7;
6589
7021
  var _f5;
6590
7022
  var _g4;
6591
7023
  var _h3;
@@ -6631,16 +7063,47 @@ var OAuthService = class OAuthService2 {
6631
7063
  finishGitHubCallback(params) {
6632
7064
  return this.finishCallback("github", params);
6633
7065
  }
7066
+ /**
7067
+ * Turn an expected OAuth start failure into the HTTP response it describes.
7068
+ *
7069
+ * `OAuthFlowError` carries the status it means — 404 for a provider that is
7070
+ * not configured, 400 for a return path the caller chose badly — but it is a
7071
+ * plain Error, so the framework's handler could only classify it as an
7072
+ * unhandled 500. A disabled provider and a bad query string are ordinary
7073
+ * client-visible outcomes, and reporting them as server faults hides real
7074
+ * ones. Only the stable `oauth_*` code crosses the boundary; provider
7075
+ * secrets, state, and codes never appear in it.
7076
+ *
7077
+ * The callback path deliberately does not go through here: it answers with a
7078
+ * redirect carrying the same code, and that contract is unchanged.
7079
+ */
7080
+ failStart(error) {
7081
+ if (error instanceof OAuthFlowError) {
7082
+ Err15(error.oauthCode, error.status);
7083
+ }
7084
+ throw error;
7085
+ }
6634
7086
  startLogin(provider, returnTo) {
6635
- this.providerConfig(provider);
6636
- const { attempt, codeChallenge } = this.state.create({
6637
- provider,
6638
- intent: "login",
6639
- returnTo
6640
- });
6641
- return this.provider(provider).authorizationUrl(attempt, codeChallenge);
7087
+ try {
7088
+ this.providerConfig(provider);
7089
+ const { attempt, codeChallenge } = this.state.create({
7090
+ provider,
7091
+ intent: "login",
7092
+ returnTo
7093
+ });
7094
+ return this.provider(provider).authorizationUrl(attempt, codeChallenge);
7095
+ } catch (error) {
7096
+ this.failStart(error);
7097
+ }
6642
7098
  }
6643
7099
  async startLink(provider, userId, returnTo) {
7100
+ try {
7101
+ return await this.buildLinkStart(provider, userId, returnTo);
7102
+ } catch (error) {
7103
+ this.failStart(error);
7104
+ }
7105
+ }
7106
+ async buildLinkStart(provider, userId, returnTo) {
6644
7107
  this.providerConfig(provider);
6645
7108
  const user = await this.users.getById(userId);
6646
7109
  if (user.status !== "active")
@@ -6722,27 +7185,27 @@ var OAuthService = class OAuthService2 {
6722
7185
  return providerConfig;
6723
7186
  }
6724
7187
  };
6725
- __decorate39([
6726
- Inject22(AUTH_CONFIG),
6727
- __metadata39("design:type", Object)
7188
+ __decorate40([
7189
+ Inject23(AUTH_CONFIG),
7190
+ __metadata40("design:type", Object)
6728
7191
  ], OAuthService.prototype, "config", void 0);
6729
- __decorate39([
7192
+ __decorate40([
6730
7193
  Log2(),
6731
- __metadata39("design:type", Object)
7194
+ __metadata40("design:type", Object)
6732
7195
  ], OAuthService.prototype, "logger", void 0);
6733
- OAuthService = __decorate39([
6734
- Injectable22(),
6735
- __metadata39("design:paramtypes", [typeof (_a24 = typeof OAuthStateService !== "undefined" && OAuthStateService) === "function" ? _a24 : Object, typeof (_b14 = typeof GoogleOAuthProvider !== "undefined" && GoogleOAuthProvider) === "function" ? _b14 : Object, typeof (_c10 = typeof GitHubOAuthProvider !== "undefined" && GitHubOAuthProvider) === "function" ? _c10 : Object, typeof (_d8 = typeof OAuthAccountService !== "undefined" && OAuthAccountService) === "function" ? _d8 : Object, typeof (_e5 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _e5 : Object, typeof (_f5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _f5 : Object, typeof (_g4 = typeof UserService !== "undefined" && UserService) === "function" ? _g4 : Object, typeof (_h3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _h3 : Object])
7196
+ OAuthService = __decorate40([
7197
+ Injectable23(),
7198
+ __metadata40("design:paramtypes", [typeof (_a25 = typeof OAuthStateService !== "undefined" && OAuthStateService) === "function" ? _a25 : Object, typeof (_b15 = typeof GoogleOAuthProvider !== "undefined" && GoogleOAuthProvider) === "function" ? _b15 : Object, typeof (_c10 = typeof GitHubOAuthProvider !== "undefined" && GitHubOAuthProvider) === "function" ? _c10 : Object, typeof (_d9 = typeof OAuthAccountService !== "undefined" && OAuthAccountService) === "function" ? _d9 : Object, typeof (_e7 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _e7 : Object, typeof (_f5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _f5 : Object, typeof (_g4 = typeof UserService !== "undefined" && UserService) === "function" ? _g4 : Object, typeof (_h3 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _h3 : Object])
6736
7199
  ], OAuthService);
6737
7200
 
6738
7201
  // src/oauth/GitHubOAuthController.ts
6739
- var __decorate40 = function(decorators, target, key, desc) {
7202
+ var __decorate41 = function(decorators, target, key, desc) {
6740
7203
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6741
7204
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6742
7205
  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;
6743
7206
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6744
7207
  };
6745
- var __metadata40 = function(k, v) {
7208
+ var __metadata41 = function(k, v) {
6746
7209
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6747
7210
  };
6748
7211
  var __param13 = function(paramIndex, decorator) {
@@ -6750,7 +7213,7 @@ var __param13 = function(paramIndex, decorator) {
6750
7213
  decorator(target, key, paramIndex);
6751
7214
  };
6752
7215
  };
6753
- var _a25;
7216
+ var _a26;
6754
7217
  var callbackKey = /* @__PURE__ */ __name((ctx, { clientIp }) => {
6755
7218
  const state = ctx.req.query("state") ?? "none";
6756
7219
  const fingerprint = createHash5("sha256").update(state).digest("base64url").slice(0, 24);
@@ -6775,52 +7238,52 @@ var GitHubOAuthController = class GitHubOAuthController2 {
6775
7238
  return this.oauth.startGitHubLink(userId, returnTo);
6776
7239
  }
6777
7240
  };
6778
- __decorate40([
7241
+ __decorate41([
6779
7242
  Get5("/start"),
6780
7243
  RateLimit3({ limit: 20, window: "15m", key: "ip" }),
6781
7244
  __param13(0, Ctx2()),
6782
7245
  __param13(1, Query2("returnTo")),
6783
- __metadata40("design:type", Function),
6784
- __metadata40("design:paramtypes", [Object, String]),
6785
- __metadata40("design:returntype", void 0)
7246
+ __metadata41("design:type", Function),
7247
+ __metadata41("design:paramtypes", [Object, String]),
7248
+ __metadata41("design:returntype", void 0)
6786
7249
  ], GitHubOAuthController.prototype, "start", null);
6787
- __decorate40([
7250
+ __decorate41([
6788
7251
  Get5("/callback"),
6789
7252
  RateLimit3({ limit: 20, window: "15m", key: callbackKey }),
6790
7253
  __param13(0, Ctx2()),
6791
7254
  __param13(1, Query2("code")),
6792
7255
  __param13(2, Query2("state")),
6793
7256
  __param13(3, Query2("error")),
6794
- __metadata40("design:type", Function),
6795
- __metadata40("design:paramtypes", [Object, String, String, String]),
6796
- __metadata40("design:returntype", Promise)
7257
+ __metadata41("design:type", Function),
7258
+ __metadata41("design:paramtypes", [Object, String, String, String]),
7259
+ __metadata41("design:returntype", Promise)
6797
7260
  ], GitHubOAuthController.prototype, "callback", null);
6798
- __decorate40([
7261
+ __decorate41([
6799
7262
  Post6("/link"),
6800
7263
  isAuth(),
6801
7264
  RateLimit3({ limit: 10, window: "15m", key: "user" }),
6802
7265
  __param13(0, User5("id")),
6803
7266
  __param13(1, Query2("returnTo")),
6804
- __metadata40("design:type", Function),
6805
- __metadata40("design:paramtypes", [String, String]),
6806
- __metadata40("design:returntype", void 0)
7267
+ __metadata41("design:type", Function),
7268
+ __metadata41("design:paramtypes", [String, String]),
7269
+ __metadata41("design:returntype", void 0)
6807
7270
  ], GitHubOAuthController.prototype, "link", null);
6808
- GitHubOAuthController = __decorate40([
7271
+ GitHubOAuthController = __decorate41([
6809
7272
  Controller6("/auth/oauth/github"),
6810
- __metadata40("design:paramtypes", [typeof (_a25 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a25 : Object])
7273
+ __metadata41("design:paramtypes", [typeof (_a26 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a26 : Object])
6811
7274
  ], GitHubOAuthController);
6812
7275
 
6813
7276
  // src/oauth/OAuthController.ts
6814
7277
  import { createHash as createHash6 } from "crypto";
6815
7278
  import { Controller as Controller7, Ctx as Ctx3, Get as Get6, Post as Post7, Query as Query3, User as User6 } from "najm-core";
6816
7279
  import { RateLimit as RateLimit4 } from "najm-rate";
6817
- var __decorate41 = function(decorators, target, key, desc) {
7280
+ var __decorate42 = function(decorators, target, key, desc) {
6818
7281
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6819
7282
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6820
7283
  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;
6821
7284
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6822
7285
  };
6823
- var __metadata41 = function(k, v) {
7286
+ var __metadata42 = function(k, v) {
6824
7287
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6825
7288
  };
6826
7289
  var __param14 = function(paramIndex, decorator) {
@@ -6828,7 +7291,7 @@ var __param14 = function(paramIndex, decorator) {
6828
7291
  decorator(target, key, paramIndex);
6829
7292
  };
6830
7293
  };
6831
- var _a26;
7294
+ var _a27;
6832
7295
  var callbackKey2 = /* @__PURE__ */ __name((ctx, { clientIp }) => {
6833
7296
  const ip = clientIp;
6834
7297
  const state = ctx.req.query("state") ?? "none";
@@ -6854,39 +7317,39 @@ var OAuthController = class OAuthController2 {
6854
7317
  return this.oauth.startGoogleLink(userId, returnTo);
6855
7318
  }
6856
7319
  };
6857
- __decorate41([
7320
+ __decorate42([
6858
7321
  Get6("/start"),
6859
7322
  RateLimit4({ limit: 20, window: "15m", key: "ip" }),
6860
7323
  __param14(0, Ctx3()),
6861
7324
  __param14(1, Query3("returnTo")),
6862
- __metadata41("design:type", Function),
6863
- __metadata41("design:paramtypes", [Object, String]),
6864
- __metadata41("design:returntype", void 0)
7325
+ __metadata42("design:type", Function),
7326
+ __metadata42("design:paramtypes", [Object, String]),
7327
+ __metadata42("design:returntype", void 0)
6865
7328
  ], OAuthController.prototype, "start", null);
6866
- __decorate41([
7329
+ __decorate42([
6867
7330
  Get6("/callback"),
6868
7331
  RateLimit4({ limit: 20, window: "15m", key: callbackKey2 }),
6869
7332
  __param14(0, Ctx3()),
6870
7333
  __param14(1, Query3("code")),
6871
7334
  __param14(2, Query3("state")),
6872
7335
  __param14(3, Query3("error")),
6873
- __metadata41("design:type", Function),
6874
- __metadata41("design:paramtypes", [Object, String, String, String]),
6875
- __metadata41("design:returntype", Promise)
7336
+ __metadata42("design:type", Function),
7337
+ __metadata42("design:paramtypes", [Object, String, String, String]),
7338
+ __metadata42("design:returntype", Promise)
6876
7339
  ], OAuthController.prototype, "callback", null);
6877
- __decorate41([
7340
+ __decorate42([
6878
7341
  Post7("/link"),
6879
7342
  isAuth(),
6880
7343
  RateLimit4({ limit: 10, window: "15m", key: "user" }),
6881
7344
  __param14(0, User6("id")),
6882
7345
  __param14(1, Query3("returnTo")),
6883
- __metadata41("design:type", Function),
6884
- __metadata41("design:paramtypes", [String, String]),
6885
- __metadata41("design:returntype", void 0)
7346
+ __metadata42("design:type", Function),
7347
+ __metadata42("design:paramtypes", [String, String]),
7348
+ __metadata42("design:returntype", void 0)
6886
7349
  ], OAuthController.prototype, "link", null);
6887
- OAuthController = __decorate41([
7350
+ OAuthController = __decorate42([
6888
7351
  Controller7("/auth/oauth/google"),
6889
- __metadata41("design:paramtypes", [typeof (_a26 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a26 : Object])
7352
+ __metadata42("design:paramtypes", [typeof (_a27 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a27 : Object])
6890
7353
  ], OAuthController);
6891
7354
 
6892
7355
  // src/oauth/index.ts
@@ -6915,13 +7378,13 @@ var credentialSetupChangeDto = z5.object({
6915
7378
  });
6916
7379
 
6917
7380
  // src/credentialSetup/CredentialSetupController.ts
6918
- var __decorate42 = function(decorators, target, key, desc) {
7381
+ var __decorate43 = function(decorators, target, key, desc) {
6919
7382
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6920
7383
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6921
7384
  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;
6922
7385
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6923
7386
  };
6924
- var __metadata42 = function(k, v) {
7387
+ var __metadata43 = function(k, v) {
6925
7388
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
6926
7389
  };
6927
7390
  var __param15 = function(paramIndex, decorator) {
@@ -6929,7 +7392,7 @@ var __param15 = function(paramIndex, decorator) {
6929
7392
  decorator(target, key, paramIndex);
6930
7393
  };
6931
7394
  };
6932
- var _a27;
7395
+ var _a28;
6933
7396
  var CredentialSetupController = class CredentialSetupController2 {
6934
7397
  static {
6935
7398
  __name(this, "CredentialSetupController");
@@ -6948,35 +7411,35 @@ var CredentialSetupController = class CredentialSetupController2 {
6948
7411
  return this.passwords.cancel();
6949
7412
  }
6950
7413
  };
6951
- __decorate42([
7414
+ __decorate43([
6952
7415
  Get7("/setup"),
6953
7416
  RateLimit5({ limit: 30, window: "15m", key: "ip" }),
6954
7417
  ResMsg6("auth.success.credentialSetupPending"),
6955
- __metadata42("design:type", Function),
6956
- __metadata42("design:paramtypes", []),
6957
- __metadata42("design:returntype", void 0)
7418
+ __metadata43("design:type", Function),
7419
+ __metadata43("design:paramtypes", []),
7420
+ __metadata43("design:returntype", void 0)
6958
7421
  ], CredentialSetupController.prototype, "status", null);
6959
- __decorate42([
7422
+ __decorate43([
6960
7423
  Post8("/change"),
6961
7424
  RateLimit5({ limit: 5, window: "15m", key: "ip" }),
6962
7425
  Validate6(credentialSetupChangeDto),
6963
7426
  ResMsg6("auth.success.credentialSetupPasswordReplaced"),
6964
7427
  __param15(0, Body7()),
6965
- __metadata42("design:type", Function),
6966
- __metadata42("design:paramtypes", [Object]),
6967
- __metadata42("design:returntype", void 0)
7428
+ __metadata43("design:type", Function),
7429
+ __metadata43("design:paramtypes", [Object]),
7430
+ __metadata43("design:returntype", void 0)
6968
7431
  ], CredentialSetupController.prototype, "change", null);
6969
- __decorate42([
7432
+ __decorate43([
6970
7433
  Post8("/cancel"),
6971
7434
  RateLimit5({ limit: 10, window: "15m", key: "ip" }),
6972
7435
  ResMsg6("auth.success.credentialSetupCancelled"),
6973
- __metadata42("design:type", Function),
6974
- __metadata42("design:paramtypes", []),
6975
- __metadata42("design:returntype", void 0)
7436
+ __metadata43("design:type", Function),
7437
+ __metadata43("design:paramtypes", []),
7438
+ __metadata43("design:returntype", void 0)
6976
7439
  ], CredentialSetupController.prototype, "cancel", null);
6977
- CredentialSetupController = __decorate42([
7440
+ CredentialSetupController = __decorate43([
6978
7441
  Controller8("/auth/credential-setup"),
6979
- __metadata42("design:paramtypes", [typeof (_a27 = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _a27 : Object])
7442
+ __metadata43("design:paramtypes", [typeof (_a28 = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _a28 : Object])
6980
7443
  ], CredentialSetupController);
6981
7444
 
6982
7445
  // src/credentialSetup/index.ts
@@ -7023,9 +7486,9 @@ var resolveGoogleConfig = /* @__PURE__ */ __name((config) => {
7023
7486
  const clientId = google.clientId ?? process.env.GOOGLE_CLIENT_ID ?? "";
7024
7487
  const clientSecret = google.clientSecret ?? process.env.GOOGLE_CLIENT_SECRET ?? "";
7025
7488
  if (!clientId)
7026
- throw Err15.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
7489
+ throw Err16.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
7027
7490
  if (!clientSecret)
7028
- throw Err15.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
7491
+ throw Err16.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
7029
7492
  const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
7030
7493
  const callbackUrl = google.callbackUrl ?? process.env.GOOGLE_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/google/callback`;
7031
7494
  return {
@@ -7047,9 +7510,9 @@ var resolveGitHubConfig = /* @__PURE__ */ __name((config) => {
7047
7510
  const clientId = github.clientId ?? process.env.GITHUB_CLIENT_ID ?? "";
7048
7511
  const clientSecret = github.clientSecret ?? process.env.GITHUB_CLIENT_SECRET ?? "";
7049
7512
  if (!clientId)
7050
- throw Err15.configRequired("auth.oauth.github", "GITHUB_CLIENT_ID");
7513
+ throw Err16.configRequired("auth.oauth.github", "GITHUB_CLIENT_ID");
7051
7514
  if (!clientSecret)
7052
- throw Err15.configRequired("auth.oauth.github", "GITHUB_CLIENT_SECRET");
7515
+ throw Err16.configRequired("auth.oauth.github", "GITHUB_CLIENT_SECRET");
7053
7516
  const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
7054
7517
  const callbackUrl = github.callbackUrl ?? process.env.GITHUB_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/github/callback`;
7055
7518
  return {
@@ -7117,10 +7580,10 @@ var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
7117
7580
  }
7118
7581
  };
7119
7582
  if (!finalConfig.jwt.accessSecret) {
7120
- throw Err15.configRequired("auth", "JWT_ACCESS_SECRET");
7583
+ throw Err16.configRequired("auth", "JWT_ACCESS_SECRET");
7121
7584
  }
7122
7585
  if (!finalConfig.jwt.refreshSecret) {
7123
- throw Err15.configRequired("auth", "JWT_REFRESH_SECRET");
7586
+ throw Err16.configRequired("auth", "JWT_REFRESH_SECRET");
7124
7587
  }
7125
7588
  return finalConfig;
7126
7589
  }, "resolveAuthConfig");
@@ -7338,6 +7801,7 @@ export {
7338
7801
  RoleService,
7339
7802
  RoleValidator,
7340
7803
  ScopeContext,
7804
+ SessionInvalidationService,
7341
7805
  TOKEN_STATUS,
7342
7806
  TOKEN_TYPE,
7343
7807
  TokenRepository,
@@ -7351,6 +7815,7 @@ export {
7351
7815
  assignRoleDto,
7352
7816
  assignRoleParams,
7353
7817
  auth,
7818
+ authEmailRateLimitKey,
7354
7819
  authIdentityRateLimitKey,
7355
7820
  authSchema,
7356
7821
  authSeed,