najm-auth 2.0.14 → 3.0.0
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/README.md +172 -50
- package/dist/{NajmAuthClient-Cn9bObLB.d.ts → NajmAuthClient-D2fSvQ_H.d.ts} +30 -5
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +15 -8
- package/dist/client/react/index.d.ts +10 -6
- package/dist/client/react/index.js +10 -3
- package/dist/client/server/index.d.ts +102 -2
- package/dist/client/server/index.js +203 -20
- package/dist/identity/ma.d.ts +1 -0
- package/dist/identity/ma.js +64 -0
- package/dist/index.d.ts +395 -91
- package/dist/index.js +1733 -862
- package/dist/ma-sNHnUGLO.d.ts +88 -0
- package/dist/schema/pg.d.ts +260 -1
- package/dist/schema/pg.js +13 -0
- package/dist/schema/sqlite.d.ts +284 -1
- package/dist/schema/sqlite.js +14 -1
- package/package.json +6 -1
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
|
|
9
|
+
import { Err as Err15, plugin } from "najm-core";
|
|
10
10
|
import { cache } from "najm-cache";
|
|
11
11
|
|
|
12
12
|
// src/auth.tokens.ts
|
|
@@ -102,6 +102,17 @@ var credentialSetupSessionsTable = pgTable("credential_setup_sessions", {
|
|
|
102
102
|
userPurposeIdx: index("credential_setup_sessions_user_purpose_idx").on(table.userId, table.purpose),
|
|
103
103
|
expiresAtIdx: index("credential_setup_sessions_expires_at_idx").on(table.expiresAt)
|
|
104
104
|
}));
|
|
105
|
+
var credentialSetupRequirementsTable = pgTable("credential_setup_requirements", {
|
|
106
|
+
userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }).notNull(),
|
|
107
|
+
purpose: text("purpose").notNull(),
|
|
108
|
+
temporaryCredentialKind: text("temporary_credential_kind"),
|
|
109
|
+
required: boolean("required").default(true).notNull(),
|
|
110
|
+
completedAt: timestamp("completed_at", { mode: "string" }),
|
|
111
|
+
createdAt: timestamp("created_at", { mode: "string" }).defaultNow(),
|
|
112
|
+
updatedAt: timestamp("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql`CURRENT_TIMESTAMP`)
|
|
113
|
+
}, (table) => ({
|
|
114
|
+
pk: primaryKey({ columns: [table.userId, table.purpose] })
|
|
115
|
+
}));
|
|
105
116
|
var rolePermissionsTable = pgTable("role_permissions", {
|
|
106
117
|
roleId: text("role_id").notNull().references(() => rolesTable.id, { onDelete: "cascade" }),
|
|
107
118
|
permissionId: text("permission_id").notNull().references(() => permissionsTable.id, { onDelete: "cascade" }),
|
|
@@ -114,13 +125,14 @@ var authSchema = {
|
|
|
114
125
|
oauthAccounts: oauthAccountsTable,
|
|
115
126
|
tokens: tokensTable,
|
|
116
127
|
credentialSetupSessions: credentialSetupSessionsTable,
|
|
128
|
+
credentialSetupRequirements: credentialSetupRequirementsTable,
|
|
117
129
|
roles: rolesTable,
|
|
118
130
|
permissions: permissionsTable,
|
|
119
131
|
rolePermissions: rolePermissionsTable
|
|
120
132
|
};
|
|
121
133
|
|
|
122
134
|
// src/schema/sqlite.ts
|
|
123
|
-
import { sqliteTable, text as text2, integer as integer2, uniqueIndex as uniqueIndex2, index as index2 } from "drizzle-orm/sqlite-core";
|
|
135
|
+
import { sqliteTable, text as text2, integer as integer2, primaryKey as primaryKey2, uniqueIndex as uniqueIndex2, index as index2 } from "drizzle-orm/sqlite-core";
|
|
124
136
|
import { sql as sql2 } from "drizzle-orm";
|
|
125
137
|
import { nanoid as nanoid2 } from "nanoid";
|
|
126
138
|
var baseFields2 = /* @__PURE__ */ __name((idLength = 5) => ({
|
|
@@ -194,6 +206,17 @@ var credentialSetupSessionsTable2 = sqliteTable("credential_setup_sessions", {
|
|
|
194
206
|
userPurposeIdx: index2("credential_setup_sessions_user_purpose_idx").on(table.userId, table.purpose),
|
|
195
207
|
expiresAtIdx: index2("credential_setup_sessions_expires_at_idx").on(table.expiresAt)
|
|
196
208
|
}));
|
|
209
|
+
var credentialSetupRequirementsTable2 = sqliteTable("credential_setup_requirements", {
|
|
210
|
+
userId: text2("user_id").references(() => usersTable2.id, { onDelete: "cascade" }).notNull(),
|
|
211
|
+
purpose: text2("purpose").notNull(),
|
|
212
|
+
temporaryCredentialKind: text2("temporary_credential_kind"),
|
|
213
|
+
required: integer2("required", { mode: "boolean" }).default(true).notNull(),
|
|
214
|
+
completedAt: text2("completed_at"),
|
|
215
|
+
createdAt: text2("created_at").$defaultFn(() => (/* @__PURE__ */ new Date()).toISOString()),
|
|
216
|
+
updatedAt: text2("updated_at").$defaultFn(() => (/* @__PURE__ */ new Date()).toISOString()).$onUpdate(() => sql2`(datetime('now'))`)
|
|
217
|
+
}, (table) => ({
|
|
218
|
+
pk: primaryKey2({ columns: [table.userId, table.purpose] })
|
|
219
|
+
}));
|
|
197
220
|
var rolePermissionsTable2 = sqliteTable("role_permissions", {
|
|
198
221
|
...baseFields2(10),
|
|
199
222
|
roleId: text2("role_id").notNull().references(() => rolesTable2.id, { onDelete: "cascade" }),
|
|
@@ -206,6 +229,7 @@ var authSchema2 = {
|
|
|
206
229
|
oauthAccounts: oauthAccountsTable2,
|
|
207
230
|
tokens: tokensTable2,
|
|
208
231
|
credentialSetupSessions: credentialSetupSessionsTable2,
|
|
232
|
+
credentialSetupRequirements: credentialSetupRequirementsTable2,
|
|
209
233
|
roles: rolesTable2,
|
|
210
234
|
permissions: permissionsTable2,
|
|
211
235
|
rolePermissions: rolePermissionsTable2
|
|
@@ -457,14 +481,15 @@ CookieManager = __decorate2([
|
|
|
457
481
|
], CookieManager);
|
|
458
482
|
|
|
459
483
|
// src/auth/AuthController.ts
|
|
460
|
-
import { Controller, Err as
|
|
484
|
+
import { Controller, Err as Err13 } from "najm-core";
|
|
461
485
|
import { Get, Post, ResMsg } from "najm-core";
|
|
462
486
|
import { Body, User as User2, Headers, Ctx } from "najm-core";
|
|
463
487
|
|
|
464
488
|
// src/auth/AuthService.ts
|
|
465
|
-
import { Injectable as
|
|
466
|
-
import { Err as
|
|
467
|
-
import {
|
|
489
|
+
import { Injectable as Injectable11, Inject as Inject11 } from "najm-core";
|
|
490
|
+
import { Err as Err12, Log } from "najm-core";
|
|
491
|
+
import { Transaction as Transaction4 } from "najm-database";
|
|
492
|
+
import { I18n as I18n8, I18nService as I18nService2 } from "najm-i18n";
|
|
468
493
|
import { EmailService, passwordResetTemplate, accountInviteTemplate } from "najm-email";
|
|
469
494
|
import { nanoid as nanoid5 } from "nanoid";
|
|
470
495
|
|
|
@@ -745,6 +770,17 @@ var UserValidator = class UserValidator2 {
|
|
|
745
770
|
Err(this.t("errors.emailExists"), 409);
|
|
746
771
|
}
|
|
747
772
|
}
|
|
773
|
+
/**
|
|
774
|
+
* Check that a normalized phone number is not already taken.
|
|
775
|
+
*/
|
|
776
|
+
async checkPhoneUnique(phone, excludeId) {
|
|
777
|
+
if (!phone)
|
|
778
|
+
return;
|
|
779
|
+
const existingUser = await this.userRepository.findByPhone(phone);
|
|
780
|
+
if (existingUser && existingUser.id !== excludeId) {
|
|
781
|
+
Err(this.t("errors.phoneExists"), 409);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
748
784
|
/**
|
|
749
785
|
* Check if user exists by ID
|
|
750
786
|
*/
|
|
@@ -827,6 +863,7 @@ var UserValidator = class UserValidator2 {
|
|
|
827
863
|
if (!password) {
|
|
828
864
|
Err("Password is required", 400);
|
|
829
865
|
}
|
|
866
|
+
this.validatePasswordLength(password);
|
|
830
867
|
const minLength = 8;
|
|
831
868
|
const hasUppercase = /[A-Z]/.test(password);
|
|
832
869
|
const hasLowercase = /[a-z]/.test(password);
|
|
@@ -844,6 +881,12 @@ var UserValidator = class UserValidator2 {
|
|
|
844
881
|
Err("Password must contain at least one number", 400);
|
|
845
882
|
}
|
|
846
883
|
}
|
|
884
|
+
/** Keep every byte passed to bcrypt significant. */
|
|
885
|
+
validatePasswordLength(password) {
|
|
886
|
+
if (new TextEncoder().encode(password).length > 72) {
|
|
887
|
+
Err("Password must be at most 72 bytes", 400);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
847
890
|
};
|
|
848
891
|
__decorate4([
|
|
849
892
|
I18n("users"),
|
|
@@ -1185,6 +1228,110 @@ var isEmpty = _isEmpty;
|
|
|
1185
1228
|
var isPath = /* @__PURE__ */ __name((img) => typeof img === "string" && img.trim().length > 0 && (img.startsWith("/") || img.startsWith("http") || img.startsWith("storage/")), "isPath");
|
|
1186
1229
|
var isFile = /* @__PURE__ */ __name((img) => !!img && typeof img !== "string" && img instanceof File, "isFile");
|
|
1187
1230
|
|
|
1231
|
+
// src/identity/presets.ts
|
|
1232
|
+
var compactPhone = /* @__PURE__ */ __name((value) => value.trim().replace(/[\s().-]+/g, ""), "compactPhone");
|
|
1233
|
+
var MOROCCO_LOCAL = /^0\d{9}$/;
|
|
1234
|
+
var MOROCCO_NATIONAL = /^212\d{9}$/;
|
|
1235
|
+
var MOROCCO_E164 = /^\+212\d{9}$/;
|
|
1236
|
+
var normalizeMoroccanPhone = /* @__PURE__ */ __name((value) => {
|
|
1237
|
+
const compact = compactPhone(value);
|
|
1238
|
+
if (MOROCCO_LOCAL.test(compact))
|
|
1239
|
+
return `+212${compact.slice(1)}`;
|
|
1240
|
+
if (MOROCCO_NATIONAL.test(compact))
|
|
1241
|
+
return `+${compact}`;
|
|
1242
|
+
if (MOROCCO_E164.test(compact))
|
|
1243
|
+
return compact;
|
|
1244
|
+
return null;
|
|
1245
|
+
}, "normalizeMoroccanPhone");
|
|
1246
|
+
var moroccoIdentityPreset = {
|
|
1247
|
+
name: "ma",
|
|
1248
|
+
normalize: normalizeMoroccanPhone
|
|
1249
|
+
};
|
|
1250
|
+
var TUNISIA_LOCAL = /^\d{8}$/;
|
|
1251
|
+
var TUNISIA_NATIONAL = /^216\d{8}$/;
|
|
1252
|
+
var TUNISIA_E164 = /^\+216\d{8}$/;
|
|
1253
|
+
var normalizeTunisianPhone = /* @__PURE__ */ __name((value) => {
|
|
1254
|
+
const compact = compactPhone(value);
|
|
1255
|
+
if (TUNISIA_LOCAL.test(compact))
|
|
1256
|
+
return `+216${compact}`;
|
|
1257
|
+
if (TUNISIA_NATIONAL.test(compact))
|
|
1258
|
+
return `+${compact}`;
|
|
1259
|
+
if (TUNISIA_E164.test(compact))
|
|
1260
|
+
return compact;
|
|
1261
|
+
return null;
|
|
1262
|
+
}, "normalizeTunisianPhone");
|
|
1263
|
+
var tunisiaIdentityPreset = {
|
|
1264
|
+
name: "tn",
|
|
1265
|
+
normalize: normalizeTunisianPhone
|
|
1266
|
+
};
|
|
1267
|
+
var IDENTITY_PRESETS = {
|
|
1268
|
+
ma: moroccoIdentityPreset,
|
|
1269
|
+
tn: tunisiaIdentityPreset
|
|
1270
|
+
};
|
|
1271
|
+
var DEFAULT_IDENTITY_PRESET = "ma";
|
|
1272
|
+
|
|
1273
|
+
// src/identity/resolver.ts
|
|
1274
|
+
var MAX_IDENTIFIER_LENGTH = 254;
|
|
1275
|
+
var E164 = /^\+[1-9]\d{7,14}$/;
|
|
1276
|
+
var normalizeE164 = /* @__PURE__ */ __name((value) => {
|
|
1277
|
+
const compact = compactPhone(value);
|
|
1278
|
+
const international = compact.startsWith("00") ? `+${compact.slice(2)}` : compact;
|
|
1279
|
+
return E164.test(international) ? international : null;
|
|
1280
|
+
}, "normalizeE164");
|
|
1281
|
+
var selectPreset = /* @__PURE__ */ __name((preset) => {
|
|
1282
|
+
if (preset === null)
|
|
1283
|
+
return null;
|
|
1284
|
+
if (preset === void 0)
|
|
1285
|
+
return IDENTITY_PRESETS[DEFAULT_IDENTITY_PRESET];
|
|
1286
|
+
if (typeof preset === "string") {
|
|
1287
|
+
const selected = IDENTITY_PRESETS[preset];
|
|
1288
|
+
if (!selected)
|
|
1289
|
+
throw new Error(`auth.identity.preset '${preset}' is not a built-in identity preset`);
|
|
1290
|
+
return selected;
|
|
1291
|
+
}
|
|
1292
|
+
if (typeof preset.normalize !== "function") {
|
|
1293
|
+
throw new Error("auth.identity.preset must expose a normalize(value) function");
|
|
1294
|
+
}
|
|
1295
|
+
return preset;
|
|
1296
|
+
}, "selectPreset");
|
|
1297
|
+
function createIdentityResolver(config) {
|
|
1298
|
+
const preset = selectPreset(config?.preset);
|
|
1299
|
+
const extend = config?.extend ?? [];
|
|
1300
|
+
if (extend.some((normalizer) => typeof normalizer !== "function")) {
|
|
1301
|
+
throw new Error("auth.identity.extend must contain only normalizer functions");
|
|
1302
|
+
}
|
|
1303
|
+
const pipeline = [
|
|
1304
|
+
...extend,
|
|
1305
|
+
...preset ? [preset.normalize] : [],
|
|
1306
|
+
normalizeE164
|
|
1307
|
+
];
|
|
1308
|
+
return (value) => {
|
|
1309
|
+
if (typeof value !== "string")
|
|
1310
|
+
return null;
|
|
1311
|
+
const trimmed = value.trim();
|
|
1312
|
+
if (!trimmed || trimmed.length > MAX_IDENTIFIER_LENGTH)
|
|
1313
|
+
return null;
|
|
1314
|
+
if (trimmed.includes("@"))
|
|
1315
|
+
return trimmed.toLowerCase();
|
|
1316
|
+
for (const normalize of pipeline) {
|
|
1317
|
+
const normalized = normalize(trimmed);
|
|
1318
|
+
if (normalized)
|
|
1319
|
+
return normalized;
|
|
1320
|
+
}
|
|
1321
|
+
return null;
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
__name(createIdentityResolver, "createIdentityResolver");
|
|
1325
|
+
var defaultResolver = createIdentityResolver();
|
|
1326
|
+
function normalizeAuthIdentifier(value) {
|
|
1327
|
+
return defaultResolver(value);
|
|
1328
|
+
}
|
|
1329
|
+
__name(normalizeAuthIdentifier, "normalizeAuthIdentifier");
|
|
1330
|
+
function isEmailIdentifier(value) {
|
|
1331
|
+
return value.includes("@");
|
|
1332
|
+
}
|
|
1333
|
+
__name(isEmailIdentifier, "isEmailIdentifier");
|
|
1334
|
+
|
|
1188
1335
|
// src/users/UserService.ts
|
|
1189
1336
|
import { Err as Err5 } from "najm-core";
|
|
1190
1337
|
var __decorate8 = function(decorators, target, key, desc) {
|
|
@@ -1209,6 +1356,7 @@ var _e;
|
|
|
1209
1356
|
var _f;
|
|
1210
1357
|
var _g;
|
|
1211
1358
|
var _h;
|
|
1359
|
+
var E164_PHONE = /^\+[1-9]\d{7,14}$/;
|
|
1212
1360
|
var UserService = class UserService2 {
|
|
1213
1361
|
static {
|
|
1214
1362
|
__name(this, "UserService");
|
|
@@ -1296,15 +1444,25 @@ var UserService = class UserService2 {
|
|
|
1296
1444
|
async getAuthRecordById(id) {
|
|
1297
1445
|
return await this.userRepository.getRawById(id);
|
|
1298
1446
|
}
|
|
1299
|
-
async create(data) {
|
|
1300
|
-
const { id, email: email2, name, image, emailVerified, password, roleId, role } = data;
|
|
1447
|
+
async create(data, options = {}) {
|
|
1448
|
+
const { id, email: email2, name, image, emailVerified, password, roleId, role, phone } = data;
|
|
1301
1449
|
if (!password || typeof password !== "string" || password.trim().length === 0) {
|
|
1302
1450
|
Err5("Password is required");
|
|
1303
1451
|
}
|
|
1304
|
-
this.userValidator.
|
|
1452
|
+
this.userValidator.validatePasswordLength(password);
|
|
1453
|
+
if (options.validatePasswordStrength !== false) {
|
|
1454
|
+
this.userValidator.validatePasswordStrength(password);
|
|
1455
|
+
}
|
|
1305
1456
|
let userId = id || nanoid3(10);
|
|
1306
1457
|
await this.userValidator.checkEmailUnique(data.email);
|
|
1307
1458
|
await this.userValidator.checkUserIdIsUnique(userId);
|
|
1459
|
+
const normalizedPhone = phone == null ? null : this.authConfig.identity?.resolve(phone) ?? normalizeAuthIdentifier(phone);
|
|
1460
|
+
if (phone != null && (!normalizedPhone || !E164_PHONE.test(normalizedPhone))) {
|
|
1461
|
+
Err5("A valid phone number is required", 400);
|
|
1462
|
+
}
|
|
1463
|
+
if (normalizedPhone) {
|
|
1464
|
+
await this.userValidator.checkPhoneUnique(normalizedPhone, userId);
|
|
1465
|
+
}
|
|
1308
1466
|
const hashedPassword = await this.encryptionService.hashPassword(password);
|
|
1309
1467
|
const resolvedRoleId = await this.resolveUserRole(roleId, role);
|
|
1310
1468
|
const userDetails = {
|
|
@@ -1315,6 +1473,7 @@ var UserService = class UserService2 {
|
|
|
1315
1473
|
password: hashedPassword,
|
|
1316
1474
|
roleId: resolvedRoleId,
|
|
1317
1475
|
emailVerified,
|
|
1476
|
+
...normalizedPhone ? { phone: normalizedPhone } : {},
|
|
1318
1477
|
status: data.status ?? this.authConfig.registrationMode ?? "active"
|
|
1319
1478
|
};
|
|
1320
1479
|
const newUser = await this.userRepository.create(userDetails);
|
|
@@ -1411,7 +1570,7 @@ __decorate8([
|
|
|
1411
1570
|
__decorate8([
|
|
1412
1571
|
Transaction(),
|
|
1413
1572
|
__metadata8("design:type", Function),
|
|
1414
|
-
__metadata8("design:paramtypes", [typeof (_g = typeof Record !== "undefined" && Record) === "function" ? _g : Object]),
|
|
1573
|
+
__metadata8("design:paramtypes", [typeof (_g = typeof Record !== "undefined" && Record) === "function" ? _g : Object, Object]),
|
|
1415
1574
|
__metadata8("design:returntype", typeof (_h = typeof Promise !== "undefined" && Promise) === "function" ? _h : Object)
|
|
1416
1575
|
], UserService.prototype, "create", null);
|
|
1417
1576
|
UserService = __decorate8([
|
|
@@ -1421,7 +1580,7 @@ UserService = __decorate8([
|
|
|
1421
1580
|
], UserService);
|
|
1422
1581
|
|
|
1423
1582
|
// src/tokens/TokenService.ts
|
|
1424
|
-
import { Injectable as Injectable6, Inject as
|
|
1583
|
+
import { Injectable as Injectable6, Inject as Inject8 } from "najm-core";
|
|
1425
1584
|
import { I18n as I18n5 } from "najm-i18n";
|
|
1426
1585
|
import { CacheService } from "najm-cache";
|
|
1427
1586
|
import { createHash } from "crypto";
|
|
@@ -1543,7 +1702,11 @@ TokenRepository = __decorate9([
|
|
|
1543
1702
|
|
|
1544
1703
|
// src/tokens/TokenService.ts
|
|
1545
1704
|
import timestring2 from "timestring";
|
|
1546
|
-
|
|
1705
|
+
|
|
1706
|
+
// src/credentialSetup/CredentialSetupRequirementRepository.ts
|
|
1707
|
+
import { and as and2, eq as eq5 } from "drizzle-orm";
|
|
1708
|
+
import { Err as Err6, Inject as Inject7, Repository as Repository4 } from "najm-core";
|
|
1709
|
+
import { DB as DB4 } from "najm-database";
|
|
1547
1710
|
var __decorate10 = function(decorators, target, key, desc) {
|
|
1548
1711
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1549
1712
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1553,10 +1716,82 @@ var __decorate10 = function(decorators, target, key, desc) {
|
|
|
1553
1716
|
var __metadata10 = function(k, v) {
|
|
1554
1717
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1555
1718
|
};
|
|
1719
|
+
var CredentialSetupRequirementRepository = class CredentialSetupRequirementRepository2 {
|
|
1720
|
+
static {
|
|
1721
|
+
__name(this, "CredentialSetupRequirementRepository");
|
|
1722
|
+
}
|
|
1723
|
+
db;
|
|
1724
|
+
schema;
|
|
1725
|
+
get requirements() {
|
|
1726
|
+
const requirements = this.schema.credentialSetupRequirements;
|
|
1727
|
+
if (!requirements) {
|
|
1728
|
+
Err6.invalidOperation("auth.schema.credentialSetupRequirements is required for credential-setup requirements");
|
|
1729
|
+
}
|
|
1730
|
+
return requirements;
|
|
1731
|
+
}
|
|
1732
|
+
get columns() {
|
|
1733
|
+
const requirements = this.requirements;
|
|
1734
|
+
return {
|
|
1735
|
+
userId: requirements.userId,
|
|
1736
|
+
purpose: requirements.purpose,
|
|
1737
|
+
temporaryCredentialKind: requirements.temporaryCredentialKind,
|
|
1738
|
+
required: requirements.required,
|
|
1739
|
+
completedAt: requirements.completedAt
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
async markRequired(userId, purpose, temporaryCredentialKind) {
|
|
1743
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1744
|
+
const [requirement] = await this.db.insert(this.requirements).values({ userId, purpose, temporaryCredentialKind, required: true }).onConflictDoUpdate({
|
|
1745
|
+
target: [this.requirements.userId, this.requirements.purpose],
|
|
1746
|
+
set: { temporaryCredentialKind, required: true, completedAt: null, updatedAt: now }
|
|
1747
|
+
}).returning(this.columns);
|
|
1748
|
+
return requirement;
|
|
1749
|
+
}
|
|
1750
|
+
async find(userId, purpose) {
|
|
1751
|
+
const [requirement] = await this.db.select(this.columns).from(this.requirements).where(and2(eq5(this.requirements.userId, userId), eq5(this.requirements.purpose, purpose))).limit(1);
|
|
1752
|
+
return requirement;
|
|
1753
|
+
}
|
|
1754
|
+
async listRequired(userId) {
|
|
1755
|
+
return this.db.select(this.columns).from(this.requirements).where(and2(eq5(this.requirements.userId, userId), eq5(this.requirements.required, true)));
|
|
1756
|
+
}
|
|
1757
|
+
/** Only a still-required row completes, so a replayed completion is a no-op. */
|
|
1758
|
+
async complete(userId, purpose) {
|
|
1759
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1760
|
+
const [requirement] = await this.db.update(this.requirements).set({ required: false, completedAt: now, updatedAt: now }).where(and2(eq5(this.requirements.userId, userId), eq5(this.requirements.purpose, purpose), eq5(this.requirements.required, true))).returning(this.columns);
|
|
1761
|
+
return requirement;
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
__decorate10([
|
|
1765
|
+
DB4(),
|
|
1766
|
+
__metadata10("design:type", Object)
|
|
1767
|
+
], CredentialSetupRequirementRepository.prototype, "db", void 0);
|
|
1768
|
+
__decorate10([
|
|
1769
|
+
Inject7(AUTH_SCHEMA),
|
|
1770
|
+
__metadata10("design:type", Object)
|
|
1771
|
+
], CredentialSetupRequirementRepository.prototype, "schema", void 0);
|
|
1772
|
+
CredentialSetupRequirementRepository = __decorate10([
|
|
1773
|
+
Repository4()
|
|
1774
|
+
], CredentialSetupRequirementRepository);
|
|
1775
|
+
|
|
1776
|
+
// src/credentialSetup/types.ts
|
|
1777
|
+
var PASSWORD_SETUP_PURPOSE = "password";
|
|
1778
|
+
|
|
1779
|
+
// src/tokens/TokenService.ts
|
|
1780
|
+
import { Err as Err7 } from "najm-core";
|
|
1781
|
+
var __decorate11 = function(decorators, target, key, desc) {
|
|
1782
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1783
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1784
|
+
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;
|
|
1785
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1786
|
+
};
|
|
1787
|
+
var __metadata11 = function(k, v) {
|
|
1788
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1789
|
+
};
|
|
1556
1790
|
var TokenService_1;
|
|
1557
1791
|
var _a6;
|
|
1558
1792
|
var _b4;
|
|
1559
1793
|
var _c2;
|
|
1794
|
+
var _d2;
|
|
1560
1795
|
var TokenService = class TokenService2 {
|
|
1561
1796
|
static {
|
|
1562
1797
|
__name(this, "TokenService");
|
|
@@ -1567,12 +1802,14 @@ var TokenService = class TokenService2 {
|
|
|
1567
1802
|
tokenRepository;
|
|
1568
1803
|
cookieManager;
|
|
1569
1804
|
cache;
|
|
1805
|
+
credentialSetupRequirements;
|
|
1570
1806
|
config;
|
|
1571
1807
|
t;
|
|
1572
|
-
constructor(tokenRepository, cookieManager, cache2) {
|
|
1808
|
+
constructor(tokenRepository, cookieManager, cache2, credentialSetupRequirements) {
|
|
1573
1809
|
this.tokenRepository = tokenRepository;
|
|
1574
1810
|
this.cookieManager = cookieManager;
|
|
1575
1811
|
this.cache = cache2;
|
|
1812
|
+
this.credentialSetupRequirements = credentialSetupRequirements;
|
|
1576
1813
|
}
|
|
1577
1814
|
/**
|
|
1578
1815
|
* Get blacklist key prefix
|
|
@@ -1612,7 +1849,7 @@ var TokenService = class TokenService2 {
|
|
|
1612
1849
|
if (authorization?.startsWith("Bearer ")) {
|
|
1613
1850
|
return authorization.split(" ")[1];
|
|
1614
1851
|
}
|
|
1615
|
-
|
|
1852
|
+
Err7(this.t("errors.tokenMissing"), 401);
|
|
1616
1853
|
}
|
|
1617
1854
|
/**
|
|
1618
1855
|
* Verify access token and check blacklist
|
|
@@ -1623,7 +1860,7 @@ var TokenService = class TokenService2 {
|
|
|
1623
1860
|
try {
|
|
1624
1861
|
payload = jwt.verify(token, this.config.jwt.accessSecret);
|
|
1625
1862
|
} catch {
|
|
1626
|
-
|
|
1863
|
+
Err7(this.t("errors.tokenVerificationFailed"), 401);
|
|
1627
1864
|
}
|
|
1628
1865
|
const sessionKey = this.sessionVersionKey(payload.userId);
|
|
1629
1866
|
const blacklistKey = payload.jti ? `${this.blacklistPrefix}${payload.jti}` : null;
|
|
@@ -1636,15 +1873,15 @@ var TokenService = class TokenService2 {
|
|
|
1636
1873
|
const values = await this.getCacheValues(keys);
|
|
1637
1874
|
const valueByKey = new Map(keys.map((key, i) => [key, values[i]]));
|
|
1638
1875
|
if (blacklistKey && valueByKey.get(blacklistKey) != null) {
|
|
1639
|
-
|
|
1876
|
+
Err7(this.t("errors.tokenRevoked"), 401);
|
|
1640
1877
|
}
|
|
1641
1878
|
if (familyKey && valueByKey.get(familyKey) != null) {
|
|
1642
|
-
|
|
1879
|
+
Err7(this.t("errors.tokenRevoked"), 401);
|
|
1643
1880
|
}
|
|
1644
1881
|
const activeSessionVersion = this.parseSessionVersion(valueByKey.get(sessionKey) ?? null);
|
|
1645
1882
|
const tokenSessionVersion = payload.sessionVersion ?? 0;
|
|
1646
1883
|
if (tokenSessionVersion !== activeSessionVersion) {
|
|
1647
|
-
|
|
1884
|
+
Err7(this.t("errors.tokenRevoked"), 401);
|
|
1648
1885
|
}
|
|
1649
1886
|
return payload;
|
|
1650
1887
|
}
|
|
@@ -1653,13 +1890,13 @@ var TokenService = class TokenService2 {
|
|
|
1653
1890
|
try {
|
|
1654
1891
|
decoded = jwt.verify(token, this.config.jwt.refreshSecret);
|
|
1655
1892
|
} catch {
|
|
1656
|
-
|
|
1893
|
+
Err7(this.t("errors.tokenVerificationFailed"), 401);
|
|
1657
1894
|
}
|
|
1658
1895
|
if (decoded.type && decoded.type !== "refresh") {
|
|
1659
|
-
|
|
1896
|
+
Err7(this.t("errors.tokenVerificationFailed"), 401);
|
|
1660
1897
|
}
|
|
1661
1898
|
if (!decoded.tokenFamily) {
|
|
1662
|
-
|
|
1899
|
+
Err7(this.t("errors.tokenVerificationFailed"), 401);
|
|
1663
1900
|
}
|
|
1664
1901
|
return { userId: decoded.userId, tokenFamily: decoded.tokenFamily };
|
|
1665
1902
|
}
|
|
@@ -1678,12 +1915,12 @@ var TokenService = class TokenService2 {
|
|
|
1678
1915
|
async resolveRefreshSessionFromCookie() {
|
|
1679
1916
|
const refreshToken = this.cookieManager.getRefreshToken();
|
|
1680
1917
|
if (!refreshToken) {
|
|
1681
|
-
|
|
1918
|
+
Err7(this.t("errors.refreshTokenMissing"), 401);
|
|
1682
1919
|
}
|
|
1683
1920
|
const { userId, tokenFamily } = this.verifyRefreshToken(refreshToken);
|
|
1684
1921
|
const stored = await this.tokenRepository.getByFamily(tokenFamily);
|
|
1685
1922
|
if (!stored || stored.userId !== userId) {
|
|
1686
|
-
|
|
1923
|
+
Err7(this.t("errors.refreshTokenInvalid"), 401);
|
|
1687
1924
|
}
|
|
1688
1925
|
const presentedHash = this.hashToken(refreshToken);
|
|
1689
1926
|
if (presentedHash === stored.token) {
|
|
@@ -1693,7 +1930,7 @@ var TokenService = class TokenService2 {
|
|
|
1693
1930
|
if (canRecover) {
|
|
1694
1931
|
return { userId, tokenFamily };
|
|
1695
1932
|
}
|
|
1696
|
-
|
|
1933
|
+
Err7(this.t("errors.refreshTokenInvalid"), 401);
|
|
1697
1934
|
}
|
|
1698
1935
|
async resolveUserFromCookie() {
|
|
1699
1936
|
return (await this.resolveRefreshSessionFromCookie()).userId;
|
|
@@ -1870,12 +2107,12 @@ var TokenService = class TokenService2 {
|
|
|
1870
2107
|
async refreshTokens() {
|
|
1871
2108
|
const refreshToken = this.cookieManager.getRefreshToken();
|
|
1872
2109
|
if (!refreshToken) {
|
|
1873
|
-
|
|
2110
|
+
Err7(this.t("errors.refreshTokenMissing"), 401);
|
|
1874
2111
|
}
|
|
1875
2112
|
const { userId, tokenFamily } = this.verifyRefreshToken(refreshToken);
|
|
1876
2113
|
const stored = await this.tokenRepository.getByFamily(tokenFamily);
|
|
1877
2114
|
if (!stored || stored.userId !== userId) {
|
|
1878
|
-
|
|
2115
|
+
Err7(this.t("errors.refreshTokenInvalid"), 401);
|
|
1879
2116
|
}
|
|
1880
2117
|
const presentedHash = this.hashToken(refreshToken);
|
|
1881
2118
|
await this.requireActiveRefreshUser(userId, tokenFamily);
|
|
@@ -1886,18 +2123,25 @@ var TokenService = class TokenService2 {
|
|
|
1886
2123
|
if (canRecover) {
|
|
1887
2124
|
const claimed = await this.tokenRepository.markPreviousUsed(tokenFamily, presentedHash);
|
|
1888
2125
|
if (!claimed?.length) {
|
|
1889
|
-
|
|
2126
|
+
Err7(this.t("errors.refreshTokenInvalid"), 401);
|
|
1890
2127
|
}
|
|
1891
2128
|
return this.generateTokens(userId, tokenFamily);
|
|
1892
2129
|
}
|
|
1893
2130
|
await this.revokeSuspectRefreshFamily(userId, tokenFamily);
|
|
1894
|
-
|
|
2131
|
+
Err7(this.t("errors.refreshTokenInvalid"), 401);
|
|
1895
2132
|
}
|
|
1896
2133
|
async requireActiveRefreshUser(userId, tokenFamily) {
|
|
1897
2134
|
const user = await this.tokenRepository.getUser(userId);
|
|
1898
2135
|
if (!user || user.status !== "active") {
|
|
1899
2136
|
await this.revokeFamily(tokenFamily);
|
|
1900
|
-
|
|
2137
|
+
Err7(this.t("errors.refreshTokenInvalid"), 401);
|
|
2138
|
+
}
|
|
2139
|
+
const requirement = await this.credentialSetupRequirements?.find(userId, PASSWORD_SETUP_PURPOSE);
|
|
2140
|
+
if (requirement?.required) {
|
|
2141
|
+
await this.revokeFamily(tokenFamily);
|
|
2142
|
+
this.cookieManager.clearRefreshToken();
|
|
2143
|
+
this.cookieManager.clearSessionCookie();
|
|
2144
|
+
Err7(this.t("errors.credentialSetupRequired"), 403);
|
|
1901
2145
|
}
|
|
1902
2146
|
return user;
|
|
1903
2147
|
}
|
|
@@ -1931,7 +2175,7 @@ var TokenService = class TokenService2 {
|
|
|
1931
2175
|
const userId = await this.resolveUserFromCookie();
|
|
1932
2176
|
const user = await this.getUserById(userId);
|
|
1933
2177
|
if (!user) {
|
|
1934
|
-
|
|
2178
|
+
Err7(this.t("errors.refreshTokenInvalid"), 401);
|
|
1935
2179
|
}
|
|
1936
2180
|
return user;
|
|
1937
2181
|
}
|
|
@@ -2073,15 +2317,15 @@ var TokenService = class TokenService2 {
|
|
|
2073
2317
|
try {
|
|
2074
2318
|
decoded = jwt.verify(token, this.config.jwt.refreshSecret);
|
|
2075
2319
|
} catch {
|
|
2076
|
-
|
|
2320
|
+
Err7(this.t("errors.resetTokenExpired"));
|
|
2077
2321
|
}
|
|
2078
2322
|
if (decoded.type !== "reset" && decoded.type !== "invite" || !decoded.jti) {
|
|
2079
|
-
|
|
2323
|
+
Err7(this.t("errors.invalidResetToken"));
|
|
2080
2324
|
}
|
|
2081
2325
|
const key = `${this.resetTokenPrefix}${decoded.userId}`;
|
|
2082
2326
|
const storedJti = await this.cache.get(key);
|
|
2083
2327
|
if (!storedJti || storedJti !== decoded.jti) {
|
|
2084
|
-
|
|
2328
|
+
Err7(this.t("errors.invalidResetToken"));
|
|
2085
2329
|
}
|
|
2086
2330
|
await this.cache.del(key);
|
|
2087
2331
|
return decoded.userId;
|
|
@@ -2090,37 +2334,196 @@ var TokenService = class TokenService2 {
|
|
|
2090
2334
|
return this.parseSessionVersion(await this.cache.get(this.sessionVersionKey(userId)));
|
|
2091
2335
|
}
|
|
2092
2336
|
};
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2337
|
+
__decorate11([
|
|
2338
|
+
Inject8(AUTH_CONFIG),
|
|
2339
|
+
__metadata11("design:type", Object)
|
|
2096
2340
|
], TokenService.prototype, "config", void 0);
|
|
2097
|
-
|
|
2341
|
+
__decorate11([
|
|
2098
2342
|
I18n5("auth"),
|
|
2099
|
-
|
|
2343
|
+
__metadata11("design:type", Object)
|
|
2100
2344
|
], TokenService.prototype, "t", void 0);
|
|
2101
|
-
TokenService = TokenService_1 =
|
|
2345
|
+
TokenService = TokenService_1 = __decorate11([
|
|
2102
2346
|
Injectable6(),
|
|
2103
|
-
|
|
2347
|
+
__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])
|
|
2104
2348
|
], TokenService);
|
|
2105
2349
|
|
|
2106
2350
|
// src/auth/AuthService.ts
|
|
2107
2351
|
import timestring3 from "timestring";
|
|
2108
2352
|
|
|
2109
2353
|
// src/auth/AuthSessionService.ts
|
|
2354
|
+
import { Injectable as Injectable8 } from "najm-core";
|
|
2355
|
+
import { Err as Err9 } from "najm-core";
|
|
2356
|
+
|
|
2357
|
+
// src/credentialSetup/CredentialSetupRequirementService.ts
|
|
2110
2358
|
import { Injectable as Injectable7 } from "najm-core";
|
|
2111
|
-
import {
|
|
2112
|
-
|
|
2359
|
+
import { Transaction as Transaction2 } from "najm-database";
|
|
2360
|
+
|
|
2361
|
+
// src/identity/temporaryCredential.ts
|
|
2362
|
+
var EXACT_TEMPORARY_CREDENTIAL_KIND = "exact";
|
|
2363
|
+
var exactKind = {
|
|
2364
|
+
name: EXACT_TEMPORARY_CREDENTIAL_KIND,
|
|
2365
|
+
normalize: /* @__PURE__ */ __name((value) => value, "normalize")
|
|
2366
|
+
};
|
|
2367
|
+
var MOROCCAN_CIN_TEMPORARY_CREDENTIAL_KIND = "ma-cin";
|
|
2368
|
+
var MOROCCAN_CIN = /^[a-z]{1,3}\d{5,17}$/i;
|
|
2369
|
+
function isMoroccanCin(value) {
|
|
2370
|
+
const trimmed = value.trim();
|
|
2371
|
+
return trimmed.length >= 8 && trimmed.length <= 20 && MOROCCAN_CIN.test(trimmed);
|
|
2372
|
+
}
|
|
2373
|
+
__name(isMoroccanCin, "isMoroccanCin");
|
|
2374
|
+
function normalizeMoroccanCin(value) {
|
|
2375
|
+
return isMoroccanCin(value) ? value.trim().toLowerCase() : value;
|
|
2376
|
+
}
|
|
2377
|
+
__name(normalizeMoroccanCin, "normalizeMoroccanCin");
|
|
2378
|
+
var moroccanCinKind = {
|
|
2379
|
+
name: MOROCCAN_CIN_TEMPORARY_CREDENTIAL_KIND,
|
|
2380
|
+
normalize: normalizeMoroccanCin,
|
|
2381
|
+
isTemporaryShape: isMoroccanCin
|
|
2382
|
+
};
|
|
2383
|
+
var KINDS = /* @__PURE__ */ new Map([
|
|
2384
|
+
[exactKind.name, exactKind],
|
|
2385
|
+
[moroccanCinKind.name, moroccanCinKind]
|
|
2386
|
+
]);
|
|
2387
|
+
function resolveTemporaryCredentialKind(name) {
|
|
2388
|
+
const kind = KINDS.get(name?.trim() || EXACT_TEMPORARY_CREDENTIAL_KIND);
|
|
2389
|
+
if (!kind) {
|
|
2390
|
+
throw new Error(`Unknown temporary credential kind '${name}'`);
|
|
2391
|
+
}
|
|
2392
|
+
return kind;
|
|
2393
|
+
}
|
|
2394
|
+
__name(resolveTemporaryCredentialKind, "resolveTemporaryCredentialKind");
|
|
2395
|
+
function isTemporaryCredentialKind(name) {
|
|
2396
|
+
return KINDS.has(name);
|
|
2397
|
+
}
|
|
2398
|
+
__name(isTemporaryCredentialKind, "isTemporaryCredentialKind");
|
|
2399
|
+
function toTemporaryCredential(input) {
|
|
2400
|
+
if (typeof input === "string") {
|
|
2401
|
+
return { kind: EXACT_TEMPORARY_CREDENTIAL_KIND, value: input };
|
|
2402
|
+
}
|
|
2403
|
+
if (!input || typeof input.value !== "string") {
|
|
2404
|
+
throw new Error("temporaryCredential must be a string or { kind, value }");
|
|
2405
|
+
}
|
|
2406
|
+
return { kind: input.kind || EXACT_TEMPORARY_CREDENTIAL_KIND, value: input.value };
|
|
2407
|
+
}
|
|
2408
|
+
__name(toTemporaryCredential, "toTemporaryCredential");
|
|
2409
|
+
function moroccanCinTemporaryCredential(value) {
|
|
2410
|
+
if (!isMoroccanCin(value)) {
|
|
2411
|
+
throw new Error("moroccanCinTemporaryCredential requires a valid Moroccan CIN");
|
|
2412
|
+
}
|
|
2413
|
+
return { kind: MOROCCAN_CIN_TEMPORARY_CREDENTIAL_KIND, value };
|
|
2414
|
+
}
|
|
2415
|
+
__name(moroccanCinTemporaryCredential, "moroccanCinTemporaryCredential");
|
|
2416
|
+
|
|
2417
|
+
// src/credentialSetup/purpose.ts
|
|
2418
|
+
import { Err as Err8 } from "najm-core";
|
|
2419
|
+
var PURPOSE_PATTERN = /^[a-z0-9](?:[a-z0-9:_-]{0,62}[a-z0-9])?$/;
|
|
2420
|
+
function normalizeSetupPurpose(purpose) {
|
|
2421
|
+
const normalized = purpose?.trim().toLowerCase();
|
|
2422
|
+
if (!normalized || !PURPOSE_PATTERN.test(normalized)) {
|
|
2423
|
+
Err8("Credential setup purpose must be 1-64 lowercase letters, numbers, colon, underscore, or hyphen", 500);
|
|
2424
|
+
}
|
|
2425
|
+
return normalized;
|
|
2426
|
+
}
|
|
2427
|
+
__name(normalizeSetupPurpose, "normalizeSetupPurpose");
|
|
2428
|
+
|
|
2429
|
+
// src/credentialSetup/CredentialSetupRequirementService.ts
|
|
2430
|
+
var __decorate12 = function(decorators, target, key, desc) {
|
|
2113
2431
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2114
2432
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2115
2433
|
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;
|
|
2116
2434
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2117
2435
|
};
|
|
2118
|
-
var
|
|
2436
|
+
var __metadata12 = function(k, v) {
|
|
2119
2437
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2120
2438
|
};
|
|
2121
2439
|
var _a7;
|
|
2122
2440
|
var _b5;
|
|
2123
2441
|
var _c3;
|
|
2442
|
+
var CredentialSetupRequirementService = class CredentialSetupRequirementService2 {
|
|
2443
|
+
static {
|
|
2444
|
+
__name(this, "CredentialSetupRequirementService");
|
|
2445
|
+
}
|
|
2446
|
+
repository;
|
|
2447
|
+
tokens;
|
|
2448
|
+
constructor(repository, tokens) {
|
|
2449
|
+
this.repository = repository;
|
|
2450
|
+
this.tokens = tokens;
|
|
2451
|
+
}
|
|
2452
|
+
/**
|
|
2453
|
+
* Idempotent. Re-marking clears a previous completion, and revokes the
|
|
2454
|
+
* user's current sessions so an already signed-in browser cannot skip it.
|
|
2455
|
+
*/
|
|
2456
|
+
async markRequired(userId, purpose, options = {}) {
|
|
2457
|
+
const kind = options.temporaryCredentialKind ?? null;
|
|
2458
|
+
if (kind)
|
|
2459
|
+
resolveTemporaryCredentialKind(kind);
|
|
2460
|
+
const requirement = await this.repository.markRequired(userId, normalizeSetupPurpose(purpose), kind);
|
|
2461
|
+
await this.tokens.invalidateUserAccessTokens(userId);
|
|
2462
|
+
await this.tokens.revokeAllForUser(userId);
|
|
2463
|
+
return requirement;
|
|
2464
|
+
}
|
|
2465
|
+
async find(userId, purpose) {
|
|
2466
|
+
const requirement = await this.repository.find(userId, normalizeSetupPurpose(purpose));
|
|
2467
|
+
return requirement?.required ? requirement : void 0;
|
|
2468
|
+
}
|
|
2469
|
+
async isRequired(userId, purpose) {
|
|
2470
|
+
return Boolean(await this.find(userId, purpose));
|
|
2471
|
+
}
|
|
2472
|
+
async listRequired(userId) {
|
|
2473
|
+
return this.repository.listRequired(userId);
|
|
2474
|
+
}
|
|
2475
|
+
/** Returns the completed row, or `undefined` when nothing was still required. */
|
|
2476
|
+
async completeRequirement(userId, purpose) {
|
|
2477
|
+
return this.repository.complete(userId, normalizeSetupPurpose(purpose));
|
|
2478
|
+
}
|
|
2479
|
+
};
|
|
2480
|
+
__decorate12([
|
|
2481
|
+
Transaction2({ retries: 2 }),
|
|
2482
|
+
__metadata12("design:type", Function),
|
|
2483
|
+
__metadata12("design:paramtypes", [String, String, Object]),
|
|
2484
|
+
__metadata12("design:returntype", typeof (_c3 = typeof Promise !== "undefined" && Promise) === "function" ? _c3 : Object)
|
|
2485
|
+
], CredentialSetupRequirementService.prototype, "markRequired", null);
|
|
2486
|
+
CredentialSetupRequirementService = __decorate12([
|
|
2487
|
+
Injectable7(),
|
|
2488
|
+
__metadata12("design:paramtypes", [typeof (_a7 = typeof CredentialSetupRequirementRepository !== "undefined" && CredentialSetupRequirementRepository) === "function" ? _a7 : Object, typeof (_b5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _b5 : Object])
|
|
2489
|
+
], CredentialSetupRequirementService);
|
|
2490
|
+
|
|
2491
|
+
// src/credentialSetup/errors.ts
|
|
2492
|
+
import { BaseError } from "najm-core";
|
|
2493
|
+
var CREDENTIAL_SETUP_CODES = {
|
|
2494
|
+
/** Login succeeded but the account must replace its credential first. */
|
|
2495
|
+
REQUIRED: "AUTH_CREDENTIAL_SETUP_REQUIRED",
|
|
2496
|
+
/** No setup cookie was presented. */
|
|
2497
|
+
SESSION_REQUIRED: "AUTH_CREDENTIAL_SETUP_SESSION_REQUIRED",
|
|
2498
|
+
/** The setup cookie is unknown, already used, or expired. */
|
|
2499
|
+
SESSION_INVALID: "AUTH_CREDENTIAL_SETUP_SESSION_INVALID",
|
|
2500
|
+
/** Nothing was still required for this user and purpose. */
|
|
2501
|
+
ALREADY_COMPLETED: "AUTH_CREDENTIAL_SETUP_ALREADY_COMPLETED",
|
|
2502
|
+
/** The replacement failed the configured policy. */
|
|
2503
|
+
PASSWORD_REJECTED: "AUTH_CREDENTIAL_SETUP_PASSWORD_REJECTED",
|
|
2504
|
+
/** The replacement is the credential being replaced. */
|
|
2505
|
+
SAME_PASSWORD: "AUTH_CREDENTIAL_SETUP_SAME_PASSWORD",
|
|
2506
|
+
/** OAuth cannot mint a session while a requirement is outstanding. */
|
|
2507
|
+
OAUTH_BLOCKED: "oauth_credential_setup_required"
|
|
2508
|
+
};
|
|
2509
|
+
var credentialSetupError = /* @__PURE__ */ __name((code, message, status = 400) => {
|
|
2510
|
+
throw new BaseError(code, message, status);
|
|
2511
|
+
}, "credentialSetupError");
|
|
2512
|
+
|
|
2513
|
+
// src/auth/AuthSessionService.ts
|
|
2514
|
+
var __decorate13 = function(decorators, target, key, desc) {
|
|
2515
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2516
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2517
|
+
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;
|
|
2518
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2519
|
+
};
|
|
2520
|
+
var __metadata13 = function(k, v) {
|
|
2521
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2522
|
+
};
|
|
2523
|
+
var _a8;
|
|
2524
|
+
var _b6;
|
|
2525
|
+
var _c4;
|
|
2526
|
+
var _d3;
|
|
2124
2527
|
var AuthSessionService = class AuthSessionService2 {
|
|
2125
2528
|
static {
|
|
2126
2529
|
__name(this, "AuthSessionService");
|
|
@@ -2128,14 +2531,19 @@ var AuthSessionService = class AuthSessionService2 {
|
|
|
2128
2531
|
tokenService;
|
|
2129
2532
|
userService;
|
|
2130
2533
|
cookieManager;
|
|
2131
|
-
|
|
2534
|
+
credentialSetupRequirements;
|
|
2535
|
+
constructor(tokenService, userService, cookieManager, credentialSetupRequirements) {
|
|
2132
2536
|
this.tokenService = tokenService;
|
|
2133
2537
|
this.userService = userService;
|
|
2134
2538
|
this.cookieManager = cookieManager;
|
|
2539
|
+
this.credentialSetupRequirements = credentialSetupRequirements;
|
|
2135
2540
|
}
|
|
2136
2541
|
async establish(user) {
|
|
2137
2542
|
if (user.status !== "active") {
|
|
2138
|
-
|
|
2543
|
+
Err9("oauth_account_inactive", 403);
|
|
2544
|
+
}
|
|
2545
|
+
if (await this.credentialSetupRequirements?.isRequired(user.id, PASSWORD_SETUP_PURPOSE)) {
|
|
2546
|
+
credentialSetupError(CREDENTIAL_SETUP_CODES.REQUIRED, "Credential setup is required before a session can be established", 403);
|
|
2139
2547
|
}
|
|
2140
2548
|
await this.tokenService.deleteExpiredSessions();
|
|
2141
2549
|
const generated = await this.tokenService.generateTokens(user.id);
|
|
@@ -2158,93 +2566,485 @@ var AuthSessionService = class AuthSessionService2 {
|
|
|
2158
2566
|
return { ...tokens, user };
|
|
2159
2567
|
}
|
|
2160
2568
|
};
|
|
2161
|
-
AuthSessionService =
|
|
2162
|
-
|
|
2163
|
-
|
|
2569
|
+
AuthSessionService = __decorate13([
|
|
2570
|
+
Injectable8(),
|
|
2571
|
+
__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])
|
|
2164
2572
|
], AuthSessionService);
|
|
2165
2573
|
|
|
2166
|
-
// src/
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
if (typeof value !== "string")
|
|
2170
|
-
return null;
|
|
2171
|
-
const trimmed = value.trim();
|
|
2172
|
-
if (!trimmed || trimmed.length > 254)
|
|
2173
|
-
return null;
|
|
2174
|
-
if (trimmed.includes("@")) {
|
|
2175
|
-
return trimmed.toLowerCase();
|
|
2176
|
-
}
|
|
2177
|
-
const compact = trimmed.replace(/[\s().-]+/g, "");
|
|
2178
|
-
const international = compact.startsWith("00") ? `+${compact.slice(2)}` : compact;
|
|
2179
|
-
return PHONE_PATTERN.test(international) ? international : null;
|
|
2180
|
-
}
|
|
2181
|
-
__name(normalizeAuthIdentifier, "normalizeAuthIdentifier");
|
|
2182
|
-
function isEmailIdentifier(value) {
|
|
2183
|
-
return value.includes("@");
|
|
2184
|
-
}
|
|
2185
|
-
__name(isEmailIdentifier, "isEmailIdentifier");
|
|
2574
|
+
// src/credentialSetup/PasswordSetupService.ts
|
|
2575
|
+
import { Inject as Inject10, Injectable as Injectable10 } from "najm-core";
|
|
2576
|
+
import { I18n as I18n7 } from "najm-i18n";
|
|
2186
2577
|
|
|
2187
|
-
// src/
|
|
2188
|
-
|
|
2578
|
+
// src/credentialSetup/CredentialSetupService.ts
|
|
2579
|
+
import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
|
|
2580
|
+
import { CookieService as CookieService2 } from "najm-cookies";
|
|
2581
|
+
import { Err as Err11, Injectable as Injectable9 } from "najm-core";
|
|
2582
|
+
import { Transaction as Transaction3 } from "najm-database";
|
|
2583
|
+
import { I18n as I18n6 } from "najm-i18n";
|
|
2584
|
+
|
|
2585
|
+
// src/credentialSetup/CredentialSetupRepository.ts
|
|
2586
|
+
import { and as and3, eq as eq6, gt, isNull as isNull2, lt as lt2 } from "drizzle-orm";
|
|
2587
|
+
import { Err as Err10, Inject as Inject9, Repository as Repository5 } from "najm-core";
|
|
2588
|
+
import { DB as DB5 } from "najm-database";
|
|
2589
|
+
var __decorate14 = function(decorators, target, key, desc) {
|
|
2189
2590
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2190
2591
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2191
2592
|
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;
|
|
2192
2593
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2193
2594
|
};
|
|
2194
|
-
var
|
|
2595
|
+
var __metadata14 = function(k, v) {
|
|
2195
2596
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2196
2597
|
};
|
|
2197
|
-
var
|
|
2198
|
-
var _b6;
|
|
2199
|
-
var _c4;
|
|
2200
|
-
var _d2;
|
|
2201
|
-
var _e2;
|
|
2202
|
-
var _f2;
|
|
2203
|
-
var _g2;
|
|
2204
|
-
var _h2;
|
|
2205
|
-
var AuthService = class AuthService2 {
|
|
2598
|
+
var CredentialSetupRepository = class CredentialSetupRepository2 {
|
|
2206
2599
|
static {
|
|
2207
|
-
__name(this, "
|
|
2600
|
+
__name(this, "CredentialSetupRepository");
|
|
2208
2601
|
}
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
config;
|
|
2218
|
-
t;
|
|
2219
|
-
logger;
|
|
2220
|
-
dummyHash;
|
|
2221
|
-
constructor(tokenService, userService, userValidator, encryptionService, cookieManager, i18nService, emailService, authSessionService) {
|
|
2222
|
-
this.tokenService = tokenService;
|
|
2223
|
-
this.userService = userService;
|
|
2224
|
-
this.userValidator = userValidator;
|
|
2225
|
-
this.encryptionService = encryptionService;
|
|
2226
|
-
this.cookieManager = cookieManager;
|
|
2227
|
-
this.i18nService = i18nService;
|
|
2228
|
-
this.emailService = emailService;
|
|
2229
|
-
this.authSessionService = authSessionService;
|
|
2602
|
+
db;
|
|
2603
|
+
schema;
|
|
2604
|
+
get sessions() {
|
|
2605
|
+
const sessions = this.schema.credentialSetupSessions;
|
|
2606
|
+
if (!sessions) {
|
|
2607
|
+
Err10.invalidOperation("auth.schema.credentialSetupSessions is required to use CredentialSetupService");
|
|
2608
|
+
}
|
|
2609
|
+
return sessions;
|
|
2230
2610
|
}
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2611
|
+
async replaceActive(data) {
|
|
2612
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2613
|
+
await this.db.update(this.sessions).set({ revokedAt: now, updatedAt: now }).where(and3(eq6(this.sessions.userId, data.userId), eq6(this.sessions.purpose, data.purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt)));
|
|
2614
|
+
const [session] = await this.db.insert(this.sessions).values(data).returning({
|
|
2615
|
+
userId: this.sessions.userId,
|
|
2616
|
+
purpose: this.sessions.purpose,
|
|
2617
|
+
expiresAt: this.sessions.expiresAt
|
|
2618
|
+
});
|
|
2619
|
+
return session;
|
|
2235
2620
|
}
|
|
2236
|
-
|
|
2237
|
-
const
|
|
2238
|
-
|
|
2621
|
+
async findActive(tokenHash, purpose) {
|
|
2622
|
+
const [session] = await this.db.select({
|
|
2623
|
+
userId: this.sessions.userId,
|
|
2624
|
+
purpose: this.sessions.purpose,
|
|
2625
|
+
expiresAt: this.sessions.expiresAt
|
|
2626
|
+
}).from(this.sessions).where(and3(eq6(this.sessions.tokenHash, tokenHash), eq6(this.sessions.purpose, purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt), gt(this.sessions.expiresAt, (/* @__PURE__ */ new Date()).toISOString()))).limit(1);
|
|
2627
|
+
return session;
|
|
2239
2628
|
}
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2629
|
+
async consume(tokenHash, purpose) {
|
|
2630
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2631
|
+
const [session] = await this.db.update(this.sessions).set({ consumedAt: now, updatedAt: now }).where(and3(eq6(this.sessions.tokenHash, tokenHash), eq6(this.sessions.purpose, purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt), gt(this.sessions.expiresAt, now))).returning({
|
|
2632
|
+
userId: this.sessions.userId,
|
|
2633
|
+
purpose: this.sessions.purpose,
|
|
2634
|
+
expiresAt: this.sessions.expiresAt
|
|
2635
|
+
});
|
|
2636
|
+
return session;
|
|
2243
2637
|
}
|
|
2244
|
-
async
|
|
2245
|
-
|
|
2638
|
+
async revoke(tokenHash, purpose) {
|
|
2639
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2640
|
+
const [session] = await this.db.update(this.sessions).set({ revokedAt: now, updatedAt: now }).where(and3(eq6(this.sessions.tokenHash, tokenHash), eq6(this.sessions.purpose, purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt))).returning({ userId: this.sessions.userId });
|
|
2641
|
+
return session;
|
|
2246
2642
|
}
|
|
2247
|
-
async
|
|
2643
|
+
async deleteExpired() {
|
|
2644
|
+
return this.db.delete(this.sessions).where(lt2(this.sessions.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning({ userId: this.sessions.userId });
|
|
2645
|
+
}
|
|
2646
|
+
};
|
|
2647
|
+
__decorate14([
|
|
2648
|
+
DB5(),
|
|
2649
|
+
__metadata14("design:type", Object)
|
|
2650
|
+
], CredentialSetupRepository.prototype, "db", void 0);
|
|
2651
|
+
__decorate14([
|
|
2652
|
+
Inject9(AUTH_SCHEMA),
|
|
2653
|
+
__metadata14("design:type", Object)
|
|
2654
|
+
], CredentialSetupRepository.prototype, "schema", void 0);
|
|
2655
|
+
CredentialSetupRepository = __decorate14([
|
|
2656
|
+
Repository5()
|
|
2657
|
+
], CredentialSetupRepository);
|
|
2658
|
+
|
|
2659
|
+
// src/credentialSetup/CredentialSetupService.ts
|
|
2660
|
+
var __decorate15 = function(decorators, target, key, desc) {
|
|
2661
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2662
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2663
|
+
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;
|
|
2664
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2665
|
+
};
|
|
2666
|
+
var __metadata15 = function(k, v) {
|
|
2667
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2668
|
+
};
|
|
2669
|
+
var _a9;
|
|
2670
|
+
var _b7;
|
|
2671
|
+
var _c5;
|
|
2672
|
+
var _d4;
|
|
2673
|
+
var _e2;
|
|
2674
|
+
var _f2;
|
|
2675
|
+
var _g2;
|
|
2676
|
+
var DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME = "najm.credential-setup";
|
|
2677
|
+
var DEFAULT_CREDENTIAL_SETUP_TTL_MS = 10 * 60 * 1e3;
|
|
2678
|
+
var MAX_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2679
|
+
var COOKIE_NAME_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
2680
|
+
var CredentialSetupService = class CredentialSetupService2 {
|
|
2681
|
+
static {
|
|
2682
|
+
__name(this, "CredentialSetupService");
|
|
2683
|
+
}
|
|
2684
|
+
repository;
|
|
2685
|
+
tokens;
|
|
2686
|
+
authCookies;
|
|
2687
|
+
cookies;
|
|
2688
|
+
t;
|
|
2689
|
+
constructor(repository, tokens, authCookies, cookies2) {
|
|
2690
|
+
this.repository = repository;
|
|
2691
|
+
this.tokens = tokens;
|
|
2692
|
+
this.authCookies = authCookies;
|
|
2693
|
+
this.cookies = cookies2;
|
|
2694
|
+
}
|
|
2695
|
+
/**
|
|
2696
|
+
* Revoke normal auth sessions and issue a single-purpose, short-lived,
|
|
2697
|
+
* browser-session cookie. No access or refresh token is minted.
|
|
2698
|
+
*/
|
|
2699
|
+
async begin(userId, options) {
|
|
2700
|
+
const resolved = this.resolveOptions(options);
|
|
2701
|
+
const token = randomBytes2(32).toString("base64url");
|
|
2702
|
+
const expiresAt = new Date(Date.now() + resolved.ttlMs).toISOString();
|
|
2703
|
+
await this.repository.deleteExpired();
|
|
2704
|
+
await this.repository.replaceActive({
|
|
2705
|
+
userId,
|
|
2706
|
+
purpose: resolved.purpose,
|
|
2707
|
+
tokenHash: this.hashToken(token),
|
|
2708
|
+
expiresAt
|
|
2709
|
+
});
|
|
2710
|
+
await this.tokens.invalidateUserAccessTokens(userId);
|
|
2711
|
+
await this.tokens.revokeAllForUser(userId);
|
|
2712
|
+
this.authCookies.clearRefreshToken();
|
|
2713
|
+
this.authCookies.clearSessionCookie();
|
|
2714
|
+
this.setCookie(token, resolved);
|
|
2715
|
+
return { purpose: resolved.purpose, expiresAt };
|
|
2716
|
+
}
|
|
2717
|
+
/** Validate and return the current active setup session without consuming it. */
|
|
2718
|
+
async require(options) {
|
|
2719
|
+
const resolved = this.resolveOptions(options);
|
|
2720
|
+
const token = this.cookies.get(resolved.cookieName);
|
|
2721
|
+
if (!token)
|
|
2722
|
+
this.sessionRequired();
|
|
2723
|
+
const session = await this.repository.findActive(this.hashToken(token), resolved.purpose);
|
|
2724
|
+
if (!session) {
|
|
2725
|
+
this.clearCookie(resolved);
|
|
2726
|
+
this.sessionInvalid();
|
|
2727
|
+
}
|
|
2728
|
+
return session;
|
|
2729
|
+
}
|
|
2730
|
+
/**
|
|
2731
|
+
* Atomically consume the setup session and execute the application-owned
|
|
2732
|
+
* credential mutation in the same database transaction. If the callback
|
|
2733
|
+
* fails, consumption rolls back and the browser may safely retry.
|
|
2734
|
+
*/
|
|
2735
|
+
async consume(options, complete) {
|
|
2736
|
+
const resolved = this.resolveOptions(options);
|
|
2737
|
+
const token = this.cookies.get(resolved.cookieName);
|
|
2738
|
+
if (!token)
|
|
2739
|
+
this.sessionRequired();
|
|
2740
|
+
const session = await this.repository.consume(this.hashToken(token), resolved.purpose);
|
|
2741
|
+
if (!session) {
|
|
2742
|
+
this.clearCookie(resolved);
|
|
2743
|
+
this.sessionInvalid();
|
|
2744
|
+
}
|
|
2745
|
+
const result = await complete(session);
|
|
2746
|
+
this.clearCookie(resolved);
|
|
2747
|
+
return result;
|
|
2748
|
+
}
|
|
2749
|
+
async cancel(options) {
|
|
2750
|
+
const resolved = this.resolveOptions(options);
|
|
2751
|
+
const token = this.cookies.get(resolved.cookieName);
|
|
2752
|
+
if (token) {
|
|
2753
|
+
await this.repository.revoke(this.hashToken(token), resolved.purpose);
|
|
2754
|
+
}
|
|
2755
|
+
this.clearCookie(resolved);
|
|
2756
|
+
return { cancelled: true };
|
|
2757
|
+
}
|
|
2758
|
+
async pruneExpired() {
|
|
2759
|
+
await this.repository.deleteExpired();
|
|
2760
|
+
}
|
|
2761
|
+
/** Tolerates direct construction outside DI, where `t` is not injected. */
|
|
2762
|
+
message(key, fallback) {
|
|
2763
|
+
try {
|
|
2764
|
+
return this.t?.(key) || fallback;
|
|
2765
|
+
} catch {
|
|
2766
|
+
return fallback;
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
sessionRequired() {
|
|
2770
|
+
return credentialSetupError(CREDENTIAL_SETUP_CODES.SESSION_REQUIRED, this.message("errors.credentialSetupSessionRequired", "Credential setup session is required"), 401);
|
|
2771
|
+
}
|
|
2772
|
+
sessionInvalid() {
|
|
2773
|
+
return credentialSetupError(CREDENTIAL_SETUP_CODES.SESSION_INVALID, this.message("errors.credentialSetupSessionInvalid", "Credential setup session is invalid or expired"), 401);
|
|
2774
|
+
}
|
|
2775
|
+
resolveOptions(options) {
|
|
2776
|
+
const purpose = normalizeSetupPurpose(options.purpose);
|
|
2777
|
+
const cookieName = options.cookieName?.trim() || DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME;
|
|
2778
|
+
const ttlMs = options.ttlMs ?? DEFAULT_CREDENTIAL_SETUP_TTL_MS;
|
|
2779
|
+
const cookiePath = options.cookiePath ?? "/";
|
|
2780
|
+
if (!COOKIE_NAME_PATTERN.test(cookieName) || cookieName.length > 128) {
|
|
2781
|
+
Err11("Credential setup cookie name is invalid", 500);
|
|
2782
|
+
}
|
|
2783
|
+
if (!Number.isInteger(ttlMs) || ttlMs < 1e3 || ttlMs > MAX_TTL_MS) {
|
|
2784
|
+
Err11("Credential setup ttlMs must be an integer between 1000 and 86400000", 500);
|
|
2785
|
+
}
|
|
2786
|
+
if (!cookiePath.startsWith("/") || cookiePath.includes(";") || cookiePath.includes("\\")) {
|
|
2787
|
+
Err11("Credential setup cookiePath must be a same-origin path", 500);
|
|
2788
|
+
}
|
|
2789
|
+
return { purpose, cookieName, ttlMs, cookiePath };
|
|
2790
|
+
}
|
|
2791
|
+
hashToken(token) {
|
|
2792
|
+
return createHash2("sha256").update(token).digest("hex");
|
|
2793
|
+
}
|
|
2794
|
+
setCookie(token, options) {
|
|
2795
|
+
this.cookies.setSession(options.cookieName, token, {
|
|
2796
|
+
httpOnly: true,
|
|
2797
|
+
path: options.cookiePath,
|
|
2798
|
+
sameSite: "Strict",
|
|
2799
|
+
secure: process.env.NODE_ENV === "production"
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2802
|
+
clearCookie(options) {
|
|
2803
|
+
this.cookies.delete(options.cookieName, {
|
|
2804
|
+
path: options.cookiePath,
|
|
2805
|
+
secure: process.env.NODE_ENV === "production"
|
|
2806
|
+
});
|
|
2807
|
+
}
|
|
2808
|
+
};
|
|
2809
|
+
__decorate15([
|
|
2810
|
+
I18n6("auth"),
|
|
2811
|
+
__metadata15("design:type", Object)
|
|
2812
|
+
], CredentialSetupService.prototype, "t", void 0);
|
|
2813
|
+
__decorate15([
|
|
2814
|
+
Transaction3({ retries: 2 }),
|
|
2815
|
+
__metadata15("design:type", Function),
|
|
2816
|
+
__metadata15("design:paramtypes", [String, Object]),
|
|
2817
|
+
__metadata15("design:returntype", typeof (_e2 = typeof Promise !== "undefined" && Promise) === "function" ? _e2 : Object)
|
|
2818
|
+
], CredentialSetupService.prototype, "begin", null);
|
|
2819
|
+
__decorate15([
|
|
2820
|
+
Transaction3({ retries: 2 }),
|
|
2821
|
+
__metadata15("design:type", Function),
|
|
2822
|
+
__metadata15("design:paramtypes", [Object, Function]),
|
|
2823
|
+
__metadata15("design:returntype", typeof (_f2 = typeof Promise !== "undefined" && Promise) === "function" ? _f2 : Object)
|
|
2824
|
+
], CredentialSetupService.prototype, "consume", null);
|
|
2825
|
+
__decorate15([
|
|
2826
|
+
Transaction3({ retries: 2 }),
|
|
2827
|
+
__metadata15("design:type", Function),
|
|
2828
|
+
__metadata15("design:paramtypes", [Object]),
|
|
2829
|
+
__metadata15("design:returntype", typeof (_g2 = typeof Promise !== "undefined" && Promise) === "function" ? _g2 : Object)
|
|
2830
|
+
], CredentialSetupService.prototype, "cancel", null);
|
|
2831
|
+
CredentialSetupService = __decorate15([
|
|
2832
|
+
Injectable9(),
|
|
2833
|
+
__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])
|
|
2834
|
+
], CredentialSetupService);
|
|
2835
|
+
|
|
2836
|
+
// src/credentialSetup/PasswordSetupService.ts
|
|
2837
|
+
var __decorate16 = function(decorators, target, key, desc) {
|
|
2838
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2839
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2840
|
+
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;
|
|
2841
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2842
|
+
};
|
|
2843
|
+
var __metadata16 = function(k, v) {
|
|
2844
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2845
|
+
};
|
|
2846
|
+
var _a10;
|
|
2847
|
+
var _b8;
|
|
2848
|
+
var _c6;
|
|
2849
|
+
var _d5;
|
|
2850
|
+
var _e3;
|
|
2851
|
+
var _f3;
|
|
2852
|
+
var PasswordSetupService = class PasswordSetupService2 {
|
|
2853
|
+
static {
|
|
2854
|
+
__name(this, "PasswordSetupService");
|
|
2855
|
+
}
|
|
2856
|
+
setup;
|
|
2857
|
+
requirements;
|
|
2858
|
+
users;
|
|
2859
|
+
userRecords;
|
|
2860
|
+
validator;
|
|
2861
|
+
encryption;
|
|
2862
|
+
config;
|
|
2863
|
+
t;
|
|
2864
|
+
constructor(setup, requirements, users, userRecords, validator, encryption) {
|
|
2865
|
+
this.setup = setup;
|
|
2866
|
+
this.requirements = requirements;
|
|
2867
|
+
this.users = users;
|
|
2868
|
+
this.userRecords = userRecords;
|
|
2869
|
+
this.validator = validator;
|
|
2870
|
+
this.encryption = encryption;
|
|
2871
|
+
}
|
|
2872
|
+
/** Tolerates direct construction outside DI, where `t` is not injected. */
|
|
2873
|
+
message(key, fallback) {
|
|
2874
|
+
try {
|
|
2875
|
+
return this.t?.(key) || fallback;
|
|
2876
|
+
} catch {
|
|
2877
|
+
return fallback;
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
get options() {
|
|
2881
|
+
const { cookieName, ttlMs } = this.config.credentialSetup.password;
|
|
2882
|
+
return { purpose: PASSWORD_SETUP_PURPOSE, cookieName, ttlMs };
|
|
2883
|
+
}
|
|
2884
|
+
pending(session) {
|
|
2885
|
+
return {
|
|
2886
|
+
nextStep: "credential_setup",
|
|
2887
|
+
setupRequired: true,
|
|
2888
|
+
purpose: session.purpose,
|
|
2889
|
+
expiresAt: session.expiresAt
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2892
|
+
/** Revoke normal sessions and hand the browser a short-lived setup cookie. */
|
|
2893
|
+
async begin(userId) {
|
|
2894
|
+
return this.pending(await this.setup.begin(userId, this.options));
|
|
2895
|
+
}
|
|
2896
|
+
/** Read the active setup session without consuming it. */
|
|
2897
|
+
async status() {
|
|
2898
|
+
return this.pending(await this.setup.require(this.options));
|
|
2899
|
+
}
|
|
2900
|
+
/**
|
|
2901
|
+
* Everything that can fail on the user's input is checked against the
|
|
2902
|
+
* *unconsumed* session, so a mistyped replacement leaves the browser able to
|
|
2903
|
+
* retry. Only the two writes that must agree — the password and the
|
|
2904
|
+
* requirement — happen inside the one-time consumption.
|
|
2905
|
+
*/
|
|
2906
|
+
async change(newPassword) {
|
|
2907
|
+
const { userId } = await this.setup.require(this.options);
|
|
2908
|
+
const password = await this.validateReplacement(userId, newPassword);
|
|
2909
|
+
const hashed = await this.encryption.hashPassword(password);
|
|
2910
|
+
await this.setup.consume(this.options, (session) => this.persist(session.userId, hashed));
|
|
2911
|
+
return { changed: true, signInAgain: true };
|
|
2912
|
+
}
|
|
2913
|
+
async cancel() {
|
|
2914
|
+
return this.setup.cancel(this.options);
|
|
2915
|
+
}
|
|
2916
|
+
async validateReplacement(userId, submitted) {
|
|
2917
|
+
const requirement = await this.requirements.find(userId, PASSWORD_SETUP_PURPOSE);
|
|
2918
|
+
if (!requirement) {
|
|
2919
|
+
credentialSetupError(CREDENTIAL_SETUP_CODES.ALREADY_COMPLETED, this.message("errors.credentialSetupAlreadyCompleted", "The password was already replaced. Please sign in again."), 409);
|
|
2920
|
+
}
|
|
2921
|
+
const kind = resolveTemporaryCredentialKind(requirement.temporaryCredentialKind);
|
|
2922
|
+
const newPassword = this.validatePolicy(submitted);
|
|
2923
|
+
if (kind.isTemporaryShape?.(newPassword)) {
|
|
2924
|
+
credentialSetupError(CREDENTIAL_SETUP_CODES.PASSWORD_REJECTED, this.message("errors.credentialSetupTemporaryShape", "Choose a password that is not your temporary credential."), 400);
|
|
2925
|
+
}
|
|
2926
|
+
const user = await this.users.getAuthRecordById(userId);
|
|
2927
|
+
if (!user?.password) {
|
|
2928
|
+
credentialSetupError(CREDENTIAL_SETUP_CODES.SESSION_INVALID, this.message("errors.invalidCredentials", "Invalid email or password"), 401);
|
|
2929
|
+
}
|
|
2930
|
+
if (await this.isCurrentPassword(newPassword, kind.normalize(newPassword), user.password)) {
|
|
2931
|
+
credentialSetupError(CREDENTIAL_SETUP_CODES.SAME_PASSWORD, this.message("errors.credentialSetupSamePassword", "Choose a password different from your current one."), 400);
|
|
2932
|
+
}
|
|
2933
|
+
return newPassword;
|
|
2934
|
+
}
|
|
2935
|
+
/**
|
|
2936
|
+
* Runs inside the setup-session consumption transaction, so the password
|
|
2937
|
+
* update, the requirement completion, and the one-time session all commit or
|
|
2938
|
+
* roll back together.
|
|
2939
|
+
*/
|
|
2940
|
+
async persist(userId, password) {
|
|
2941
|
+
await this.userRecords.update(userId, { password });
|
|
2942
|
+
const completed = await this.requirements.completeRequirement(userId, PASSWORD_SETUP_PURPOSE);
|
|
2943
|
+
if (!completed) {
|
|
2944
|
+
credentialSetupError(CREDENTIAL_SETUP_CODES.ALREADY_COMPLETED, this.message("errors.credentialSetupAlreadyCompleted", "The password was already replaced. Please sign in again."), 409);
|
|
2945
|
+
}
|
|
2946
|
+
return userId;
|
|
2947
|
+
}
|
|
2948
|
+
validatePolicy(submitted) {
|
|
2949
|
+
const parsed = this.config.credentialSetup.password.passwordSchema.safeParse(submitted);
|
|
2950
|
+
if (!parsed.success) {
|
|
2951
|
+
credentialSetupError(CREDENTIAL_SETUP_CODES.PASSWORD_REJECTED, parsed.error.issues[0]?.message ?? this.message("errors.credentialSetupPasswordRejected", "Choose a different password."), 422);
|
|
2952
|
+
}
|
|
2953
|
+
return parsed.data;
|
|
2954
|
+
}
|
|
2955
|
+
/**
|
|
2956
|
+
* The stored hash is of the *normalized* temporary credential, so a
|
|
2957
|
+
* differently-cased retype has to be compared in both forms.
|
|
2958
|
+
*/
|
|
2959
|
+
async isCurrentPassword(submitted, normalized, storedHash) {
|
|
2960
|
+
if (await this.validator.comparePassword(submitted, storedHash))
|
|
2961
|
+
return true;
|
|
2962
|
+
if (normalized === submitted)
|
|
2963
|
+
return false;
|
|
2964
|
+
return this.validator.comparePassword(normalized, storedHash);
|
|
2965
|
+
}
|
|
2966
|
+
};
|
|
2967
|
+
__decorate16([
|
|
2968
|
+
Inject10(AUTH_CONFIG),
|
|
2969
|
+
__metadata16("design:type", Object)
|
|
2970
|
+
], PasswordSetupService.prototype, "config", void 0);
|
|
2971
|
+
__decorate16([
|
|
2972
|
+
I18n7("auth"),
|
|
2973
|
+
__metadata16("design:type", Object)
|
|
2974
|
+
], PasswordSetupService.prototype, "t", void 0);
|
|
2975
|
+
PasswordSetupService = __decorate16([
|
|
2976
|
+
Injectable10(),
|
|
2977
|
+
__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])
|
|
2978
|
+
], PasswordSetupService);
|
|
2979
|
+
|
|
2980
|
+
// src/auth/AuthService.ts
|
|
2981
|
+
var __decorate17 = function(decorators, target, key, desc) {
|
|
2982
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2983
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2984
|
+
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;
|
|
2985
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2986
|
+
};
|
|
2987
|
+
var __metadata17 = function(k, v) {
|
|
2988
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2989
|
+
};
|
|
2990
|
+
var _a11;
|
|
2991
|
+
var _b9;
|
|
2992
|
+
var _c7;
|
|
2993
|
+
var _d6;
|
|
2994
|
+
var _e4;
|
|
2995
|
+
var _f4;
|
|
2996
|
+
var _g3;
|
|
2997
|
+
var _h2;
|
|
2998
|
+
var _j;
|
|
2999
|
+
var _k;
|
|
3000
|
+
var _l;
|
|
3001
|
+
var AuthService = class AuthService2 {
|
|
3002
|
+
static {
|
|
3003
|
+
__name(this, "AuthService");
|
|
3004
|
+
}
|
|
3005
|
+
tokenService;
|
|
3006
|
+
userService;
|
|
3007
|
+
userValidator;
|
|
3008
|
+
encryptionService;
|
|
3009
|
+
cookieManager;
|
|
3010
|
+
i18nService;
|
|
3011
|
+
emailService;
|
|
3012
|
+
authSessionService;
|
|
3013
|
+
credentialSetupRequirements;
|
|
3014
|
+
passwordSetup;
|
|
3015
|
+
config;
|
|
3016
|
+
t;
|
|
3017
|
+
logger;
|
|
3018
|
+
dummyHash;
|
|
3019
|
+
constructor(tokenService, userService, userValidator, encryptionService, cookieManager, i18nService, emailService, authSessionService, credentialSetupRequirements, passwordSetup) {
|
|
3020
|
+
this.tokenService = tokenService;
|
|
3021
|
+
this.userService = userService;
|
|
3022
|
+
this.userValidator = userValidator;
|
|
3023
|
+
this.encryptionService = encryptionService;
|
|
3024
|
+
this.cookieManager = cookieManager;
|
|
3025
|
+
this.i18nService = i18nService;
|
|
3026
|
+
this.emailService = emailService;
|
|
3027
|
+
this.authSessionService = authSessionService;
|
|
3028
|
+
this.credentialSetupRequirements = credentialSetupRequirements;
|
|
3029
|
+
this.passwordSetup = passwordSetup;
|
|
3030
|
+
}
|
|
3031
|
+
isLockoutActive(lockoutUntil) {
|
|
3032
|
+
if (!lockoutUntil)
|
|
3033
|
+
return false;
|
|
3034
|
+
return new Date(lockoutUntil).getTime() > Date.now();
|
|
3035
|
+
}
|
|
3036
|
+
nextLockoutUntil() {
|
|
3037
|
+
const durationMs = timestring3(this.config.lockout.duration, "ms");
|
|
3038
|
+
return new Date(Date.now() + durationMs).toISOString();
|
|
3039
|
+
}
|
|
3040
|
+
getDummyHash() {
|
|
3041
|
+
this.dummyHash ??= this.encryptionService.hashPassword("najm-auth-dummy-password");
|
|
3042
|
+
return this.dummyHash;
|
|
3043
|
+
}
|
|
3044
|
+
async warmupPasswordHash() {
|
|
3045
|
+
await this.getDummyHash();
|
|
3046
|
+
}
|
|
3047
|
+
async registerUser(body) {
|
|
2248
3048
|
return await this.userService.create({
|
|
2249
3049
|
name: body.name,
|
|
2250
3050
|
email: body.email,
|
|
@@ -2268,6 +3068,7 @@ var AuthService = class AuthService2 {
|
|
|
2268
3068
|
id: body.id,
|
|
2269
3069
|
name: body.name,
|
|
2270
3070
|
email: body.email,
|
|
3071
|
+
phone: body.phone,
|
|
2271
3072
|
role: body.role,
|
|
2272
3073
|
roleId: body.roleId,
|
|
2273
3074
|
image: body.image,
|
|
@@ -2298,24 +3099,79 @@ var AuthService = class AuthService2 {
|
|
|
2298
3099
|
* Returns the created (sanitized) user so the caller can link `userId`.
|
|
2299
3100
|
*/
|
|
2300
3101
|
async provisionUser(body) {
|
|
2301
|
-
const
|
|
3102
|
+
const input = body;
|
|
3103
|
+
if (input.requireCredentialSetup) {
|
|
3104
|
+
return this.provisionWithCredentialSetup(input);
|
|
3105
|
+
}
|
|
3106
|
+
if (input.temporaryCredential) {
|
|
3107
|
+
Err12("provisionUser requires requireCredentialSetup when a temporaryCredential is supplied", 400);
|
|
3108
|
+
}
|
|
3109
|
+
const password = typeof input.password === "string" ? input.password.trim() : "";
|
|
2302
3110
|
if (password) {
|
|
2303
3111
|
return this.userService.create({
|
|
2304
|
-
id:
|
|
2305
|
-
name:
|
|
2306
|
-
email:
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
3112
|
+
id: input.id,
|
|
3113
|
+
name: input.name,
|
|
3114
|
+
email: input.email,
|
|
3115
|
+
phone: input.phone,
|
|
3116
|
+
role: input.role,
|
|
3117
|
+
roleId: input.roleId,
|
|
3118
|
+
image: input.image,
|
|
2310
3119
|
password,
|
|
2311
|
-
status:
|
|
3120
|
+
status: input.status ?? "active"
|
|
2312
3121
|
});
|
|
2313
3122
|
}
|
|
2314
|
-
return this.inviteUser(
|
|
3123
|
+
return this.inviteUser(input);
|
|
3124
|
+
}
|
|
3125
|
+
/**
|
|
3126
|
+
* Create the account and mark the durable requirement in one transaction, so
|
|
3127
|
+
* a user never exists holding a temporary credential that nothing forces
|
|
3128
|
+
* them to replace. No session is issued here.
|
|
3129
|
+
*/
|
|
3130
|
+
async provisionWithCredentialSetup(body) {
|
|
3131
|
+
if (body.password != null) {
|
|
3132
|
+
Err12("provisionUser cannot set a password and a temporaryCredential at the same time", 400);
|
|
3133
|
+
}
|
|
3134
|
+
if (!body.temporaryCredential) {
|
|
3135
|
+
Err12("provisionUser requires a temporaryCredential when credential setup is required", 400);
|
|
3136
|
+
}
|
|
3137
|
+
if (!this.credentialSetupRequirements) {
|
|
3138
|
+
Err12.invalidOperation("Credential setup is unavailable: CredentialSetupRequirementService is not registered");
|
|
3139
|
+
}
|
|
3140
|
+
const temporary = toTemporaryCredential(body.temporaryCredential);
|
|
3141
|
+
const kind = resolveTemporaryCredentialKind(temporary.kind);
|
|
3142
|
+
if (kind.isTemporaryShape && !kind.isTemporaryShape(temporary.value)) {
|
|
3143
|
+
Err12(`Invalid temporary credential for kind '${kind.name}'`, 400);
|
|
3144
|
+
}
|
|
3145
|
+
const password = kind.normalize(temporary.value);
|
|
3146
|
+
if (!password?.trim()) {
|
|
3147
|
+
Err12("provisionUser requires a non-empty temporaryCredential", 400);
|
|
3148
|
+
}
|
|
3149
|
+
const user = await this.userService.create({
|
|
3150
|
+
id: body.id,
|
|
3151
|
+
name: body.name,
|
|
3152
|
+
email: body.email,
|
|
3153
|
+
phone: body.phone,
|
|
3154
|
+
role: body.role,
|
|
3155
|
+
roleId: body.roleId,
|
|
3156
|
+
image: body.image,
|
|
3157
|
+
password,
|
|
3158
|
+
status: body.status ?? "active"
|
|
3159
|
+
}, { validatePasswordStrength: false });
|
|
3160
|
+
await this.credentialSetupRequirements.markRequired(user.id, body.requireCredentialSetup, {
|
|
3161
|
+
temporaryCredentialKind: kind.name
|
|
3162
|
+
});
|
|
3163
|
+
return user;
|
|
2315
3164
|
}
|
|
2316
3165
|
async loginUser(body) {
|
|
2317
|
-
const user = await this.
|
|
2318
|
-
|
|
3166
|
+
const { user, requirement } = await this.authenticate(body, { kind: "active" });
|
|
3167
|
+
if (requirement) {
|
|
3168
|
+
if (!this.passwordSetup) {
|
|
3169
|
+
Err12.invalidOperation("Credential setup is required but PasswordSetupService is not registered");
|
|
3170
|
+
}
|
|
3171
|
+
return this.passwordSetup.begin(user.id);
|
|
3172
|
+
}
|
|
3173
|
+
const session = await this.establishSession(user);
|
|
3174
|
+
return { ...session, nextStep: "authenticated" };
|
|
2319
3175
|
}
|
|
2320
3176
|
/**
|
|
2321
3177
|
* Verify credentials and account policy without minting access/refresh
|
|
@@ -2323,7 +3179,7 @@ var AuthService = class AuthService2 {
|
|
|
2323
3179
|
* this before issuing a purpose-bound CredentialSetupService session.
|
|
2324
3180
|
*/
|
|
2325
3181
|
async verifyCredentials(body) {
|
|
2326
|
-
return this.
|
|
3182
|
+
return (await this.authenticate(body, { kind: "active" })).user;
|
|
2327
3183
|
}
|
|
2328
3184
|
/**
|
|
2329
3185
|
* Verify a pending, unverified account for one exact application role.
|
|
@@ -2332,17 +3188,22 @@ var AuthService = class AuthService2 {
|
|
|
2332
3188
|
*/
|
|
2333
3189
|
async verifyPendingCredentials(body, expectedRole) {
|
|
2334
3190
|
if (!expectedRole.trim()) {
|
|
2335
|
-
|
|
3191
|
+
Err12(this.t("errors.invalidCredentials"), 401);
|
|
2336
3192
|
}
|
|
2337
|
-
return this.
|
|
3193
|
+
return (await this.authenticate(body, {
|
|
2338
3194
|
kind: "pending",
|
|
2339
3195
|
expectedRole: expectedRole.trim().toLowerCase()
|
|
2340
|
-
});
|
|
3196
|
+
})).user;
|
|
2341
3197
|
}
|
|
2342
|
-
|
|
2343
|
-
|
|
3198
|
+
/**
|
|
3199
|
+
* The one credential path. Resolves identity, the durable setup requirement,
|
|
3200
|
+
* and the credential normalization that requirement implies — in that order —
|
|
3201
|
+
* before a single hash comparison decides the outcome. Nothing about the
|
|
3202
|
+
* requirement is revealed until credentials and account policy have passed.
|
|
3203
|
+
*/
|
|
3204
|
+
async authenticate(body, policy) {
|
|
2344
3205
|
const rawIdentifier = "identifier" in body ? body.identifier : body.email;
|
|
2345
|
-
const identifier = normalizeAuthIdentifier(rawIdentifier);
|
|
3206
|
+
const identifier = this.config.identity?.resolve(rawIdentifier) ?? normalizeAuthIdentifier(rawIdentifier);
|
|
2346
3207
|
let user;
|
|
2347
3208
|
if (identifier && isEmailIdentifier(identifier)) {
|
|
2348
3209
|
user = await this.userService.findByEmailInsensitive(identifier);
|
|
@@ -2356,42 +3217,65 @@ var AuthService = class AuthService2 {
|
|
|
2356
3217
|
user.lockoutUntil = null;
|
|
2357
3218
|
}
|
|
2358
3219
|
if (user && this.isLockoutActive(user.lockoutUntil)) {
|
|
2359
|
-
|
|
3220
|
+
Err12(this.t("errors.accountLocked"), 423);
|
|
2360
3221
|
}
|
|
2361
|
-
const
|
|
2362
|
-
const
|
|
3222
|
+
const requirement = await this.credentialSetupRequirements?.find(user?.id ?? "", PASSWORD_SETUP_PURPOSE);
|
|
3223
|
+
const { credential, kindUnavailable } = this.resolveLoginCredential(body.password, requirement);
|
|
3224
|
+
const storedHash = kindUnavailable || !user?.password ? await this.getDummyHash() : user.password;
|
|
3225
|
+
const isValid = await this.userValidator.comparePassword(credential, storedHash);
|
|
2363
3226
|
if (!user || !isValid) {
|
|
2364
3227
|
if (user) {
|
|
2365
3228
|
const attempts = await this.userService.incrementFailedAttempts(user.id);
|
|
2366
3229
|
if (attempts >= this.config.lockout.maxAttempts) {
|
|
2367
3230
|
await this.userService.setLockout(user.id, this.nextLockoutUntil());
|
|
2368
|
-
|
|
3231
|
+
Err12(this.t("errors.accountLocked"), 423);
|
|
2369
3232
|
}
|
|
2370
3233
|
}
|
|
2371
|
-
|
|
3234
|
+
Err12(this.t("errors.invalidCredentials"), 401);
|
|
2372
3235
|
}
|
|
2373
3236
|
if (policy.kind === "pending") {
|
|
2374
3237
|
const role = typeof user.role === "string" ? user.role.toLowerCase() : "";
|
|
2375
3238
|
if (user.status !== "pending" || user.emailVerified || role !== policy.expectedRole) {
|
|
2376
|
-
|
|
3239
|
+
Err12(this.t("errors.invalidCredentials"), 401);
|
|
2377
3240
|
}
|
|
2378
3241
|
} else {
|
|
2379
3242
|
if (user.status !== "active") {
|
|
2380
|
-
|
|
3243
|
+
Err12(this.t("errors.accountInactive"), 403);
|
|
2381
3244
|
}
|
|
2382
3245
|
if (this.config.requireVerifiedEmail && !user.emailVerified) {
|
|
2383
|
-
|
|
3246
|
+
Err12(this.t("errors.emailNotVerified"), 403);
|
|
2384
3247
|
}
|
|
2385
3248
|
}
|
|
2386
3249
|
if ((user.failedLoginAttempts ?? 0) > 0 || user.lockoutUntil) {
|
|
2387
3250
|
await this.userService.resetFailedAttempts(user.id);
|
|
2388
3251
|
}
|
|
2389
3252
|
const { password: _, failedLoginAttempts: __, lockoutUntil: ___, ...sanitized } = user;
|
|
2390
|
-
return sanitized;
|
|
3253
|
+
return { user: sanitized, requirement };
|
|
3254
|
+
}
|
|
3255
|
+
/**
|
|
3256
|
+
* A user-chosen password is compared byte-for-byte. Only an active
|
|
3257
|
+
* requirement, and only its own stored kind, can transform the submitted
|
|
3258
|
+
* value — so lowercasing a CIN never leaks into normal logins.
|
|
3259
|
+
*/
|
|
3260
|
+
resolveLoginCredential(password, requirement) {
|
|
3261
|
+
if (!requirement)
|
|
3262
|
+
return { credential: password, kindUnavailable: false };
|
|
3263
|
+
try {
|
|
3264
|
+
const kind = resolveTemporaryCredentialKind(requirement.temporaryCredentialKind);
|
|
3265
|
+
return { credential: kind.normalize(password), kindUnavailable: false };
|
|
3266
|
+
} catch (error) {
|
|
3267
|
+
this.logger.error("Unresolvable temporary credential kind on an active requirement", {
|
|
3268
|
+
userId: requirement.userId,
|
|
3269
|
+
purpose: requirement.purpose,
|
|
3270
|
+
kind: requirement.temporaryCredentialKind,
|
|
3271
|
+
error
|
|
3272
|
+
});
|
|
3273
|
+
return { credential: password, kindUnavailable: true };
|
|
3274
|
+
}
|
|
2391
3275
|
}
|
|
2392
3276
|
/** Establish a complete normal auth session for an already verified user. */
|
|
2393
3277
|
async establishSession(user) {
|
|
2394
|
-
this.authSessionService ??= new AuthSessionService(this.tokenService, this.userService, this.cookieManager);
|
|
3278
|
+
this.authSessionService ??= new AuthSessionService(this.tokenService, this.userService, this.cookieManager, this.credentialSetupRequirements);
|
|
2395
3279
|
return this.authSessionService.establish(user);
|
|
2396
3280
|
}
|
|
2397
3281
|
async refreshTokens() {
|
|
@@ -2509,11 +3393,11 @@ var AuthService = class AuthService2 {
|
|
|
2509
3393
|
async changePassword(userId, currentPassword, newPassword) {
|
|
2510
3394
|
const user = await this.userService.getAuthRecordById(userId);
|
|
2511
3395
|
if (!user?.password) {
|
|
2512
|
-
|
|
3396
|
+
Err12(this.t("errors.invalidCredentials"), 401);
|
|
2513
3397
|
}
|
|
2514
3398
|
const isValid = await this.userValidator.comparePassword(currentPassword, user.password);
|
|
2515
3399
|
if (!isValid) {
|
|
2516
|
-
|
|
3400
|
+
Err12(this.t("errors.invalidCredentials"), 401);
|
|
2517
3401
|
}
|
|
2518
3402
|
this.userValidator.validatePasswordStrength(newPassword);
|
|
2519
3403
|
await this.userService.update(userId, { password: newPassword });
|
|
@@ -2534,33 +3418,39 @@ var AuthService = class AuthService2 {
|
|
|
2534
3418
|
return { message: this.t("success.passwordReset") };
|
|
2535
3419
|
}
|
|
2536
3420
|
};
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
3421
|
+
__decorate17([
|
|
3422
|
+
Inject11(AUTH_CONFIG),
|
|
3423
|
+
__metadata17("design:type", Object)
|
|
2540
3424
|
], AuthService.prototype, "config", void 0);
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
3425
|
+
__decorate17([
|
|
3426
|
+
I18n8("auth"),
|
|
3427
|
+
__metadata17("design:type", Object)
|
|
2544
3428
|
], AuthService.prototype, "t", void 0);
|
|
2545
|
-
|
|
3429
|
+
__decorate17([
|
|
2546
3430
|
Log(),
|
|
2547
|
-
|
|
3431
|
+
__metadata17("design:type", Object)
|
|
2548
3432
|
], AuthService.prototype, "logger", void 0);
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
3433
|
+
__decorate17([
|
|
3434
|
+
Transaction4(),
|
|
3435
|
+
__metadata17("design:type", Function),
|
|
3436
|
+
__metadata17("design:paramtypes", [Object]),
|
|
3437
|
+
__metadata17("design:returntype", typeof (_l = typeof Promise !== "undefined" && Promise) === "function" ? _l : Object)
|
|
3438
|
+
], AuthService.prototype, "provisionWithCredentialSetup", null);
|
|
3439
|
+
AuthService = __decorate17([
|
|
3440
|
+
Injectable11(),
|
|
3441
|
+
__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])
|
|
2552
3442
|
], AuthService);
|
|
2553
3443
|
|
|
2554
3444
|
// src/auth/AuthGuard.ts
|
|
2555
3445
|
import { Service as Service2, User } from "najm-core";
|
|
2556
3446
|
import { createGuard } from "najm-guard";
|
|
2557
|
-
var
|
|
3447
|
+
var __decorate18 = function(decorators, target, key, desc) {
|
|
2558
3448
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2559
3449
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2560
3450
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2561
3451
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2562
3452
|
};
|
|
2563
|
-
var
|
|
3453
|
+
var __metadata18 = function(k, v) {
|
|
2564
3454
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2565
3455
|
};
|
|
2566
3456
|
var __param3 = function(paramIndex, decorator) {
|
|
@@ -2576,13 +3466,13 @@ var AuthGuard = class AuthGuard2 {
|
|
|
2576
3466
|
return !!user;
|
|
2577
3467
|
}
|
|
2578
3468
|
};
|
|
2579
|
-
|
|
3469
|
+
__decorate18([
|
|
2580
3470
|
__param3(0, User()),
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
3471
|
+
__metadata18("design:type", Function),
|
|
3472
|
+
__metadata18("design:paramtypes", [Object]),
|
|
3473
|
+
__metadata18("design:returntype", Boolean)
|
|
2584
3474
|
], AuthGuard.prototype, "canActivate", null);
|
|
2585
|
-
AuthGuard =
|
|
3475
|
+
AuthGuard = __decorate18([
|
|
2586
3476
|
Service2()
|
|
2587
3477
|
], AuthGuard);
|
|
2588
3478
|
var isAuth = createGuard(AuthGuard);
|
|
@@ -2591,13 +3481,13 @@ var isAuth = createGuard(AuthGuard);
|
|
|
2591
3481
|
import { Service as Service3 } from "najm-core";
|
|
2592
3482
|
import { GuardParams, Role as RequestRole } from "najm-core";
|
|
2593
3483
|
import { composeGuards, createGuard as createGuard2 } from "najm-guard";
|
|
2594
|
-
var
|
|
3484
|
+
var __decorate19 = function(decorators, target, key, desc) {
|
|
2595
3485
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2596
3486
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2597
3487
|
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;
|
|
2598
3488
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2599
3489
|
};
|
|
2600
|
-
var
|
|
3490
|
+
var __metadata19 = function(k, v) {
|
|
2601
3491
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2602
3492
|
};
|
|
2603
3493
|
var __param4 = function(paramIndex, decorator) {
|
|
@@ -2620,14 +3510,14 @@ var RoleGuard = class RoleGuard2 {
|
|
|
2620
3510
|
return false;
|
|
2621
3511
|
}
|
|
2622
3512
|
};
|
|
2623
|
-
|
|
3513
|
+
__decorate19([
|
|
2624
3514
|
__param4(0, GuardParams()),
|
|
2625
3515
|
__param4(1, RequestRole()),
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
3516
|
+
__metadata19("design:type", Function),
|
|
3517
|
+
__metadata19("design:paramtypes", [Object, String]),
|
|
3518
|
+
__metadata19("design:returntype", void 0)
|
|
2629
3519
|
], RoleGuard.prototype, "canActivate", null);
|
|
2630
|
-
RoleGuard =
|
|
3520
|
+
RoleGuard = __decorate19([
|
|
2631
3521
|
Service3()
|
|
2632
3522
|
], RoleGuard);
|
|
2633
3523
|
var Role = createGuard2(RoleGuard);
|
|
@@ -2637,7 +3527,23 @@ var isAdministrator = composeGuards(isAuth(), Role(ROLE_GROUPS.ADMINISTRATORS));
|
|
|
2637
3527
|
// src/auth/AuthController.ts
|
|
2638
3528
|
import { Validate } from "najm-validation";
|
|
2639
3529
|
import { RateLimit } from "najm-rate";
|
|
2640
|
-
import { createHash as
|
|
3530
|
+
import { createHash as createHash3 } from "crypto";
|
|
3531
|
+
|
|
3532
|
+
// src/identity/requestResolver.ts
|
|
3533
|
+
var CONTEXT_RESOLVER_KEY = "najm.auth.identityResolver";
|
|
3534
|
+
var defaultResolver2 = createIdentityResolver();
|
|
3535
|
+
function setRequestIdentityResolver(context, resolver) {
|
|
3536
|
+
context.set(CONTEXT_RESOLVER_KEY, resolver);
|
|
3537
|
+
}
|
|
3538
|
+
__name(setRequestIdentityResolver, "setRequestIdentityResolver");
|
|
3539
|
+
function getRequestIdentityResolver(context) {
|
|
3540
|
+
try {
|
|
3541
|
+
return context.get(CONTEXT_RESOLVER_KEY) ?? defaultResolver2;
|
|
3542
|
+
} catch {
|
|
3543
|
+
return defaultResolver2;
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
__name(getRequestIdentityResolver, "getRequestIdentityResolver");
|
|
2641
3547
|
|
|
2642
3548
|
// src/users/UserDto.ts
|
|
2643
3549
|
import { z } from "zod";
|
|
@@ -2670,14 +3576,17 @@ var userIdParam = z.object({
|
|
|
2670
3576
|
id: z.string().min(1, "User ID is required")
|
|
2671
3577
|
});
|
|
2672
3578
|
var identifierField = z.string().trim().min(1).max(254);
|
|
3579
|
+
var loginCredentialField = z.string().min(1, "Password is required").refine((v) => new TextEncoder().encode(v).length <= 72, "Password must be at most 72 bytes");
|
|
2673
3580
|
var loginDto = z.union([
|
|
2674
3581
|
z.object({
|
|
2675
3582
|
identifier: identifierField,
|
|
2676
|
-
password:
|
|
3583
|
+
password: loginCredentialField,
|
|
3584
|
+
rememberMe: z.boolean().optional()
|
|
2677
3585
|
}),
|
|
2678
3586
|
z.object({
|
|
2679
3587
|
email: emailField,
|
|
2680
|
-
password:
|
|
3588
|
+
password: loginCredentialField,
|
|
3589
|
+
rememberMe: z.boolean().optional()
|
|
2681
3590
|
})
|
|
2682
3591
|
]);
|
|
2683
3592
|
var changePasswordDto = z.object({
|
|
@@ -2710,13 +3619,13 @@ var userListQuery = z.object({
|
|
|
2710
3619
|
});
|
|
2711
3620
|
|
|
2712
3621
|
// src/auth/AuthController.ts
|
|
2713
|
-
var
|
|
3622
|
+
var __decorate20 = function(decorators, target, key, desc) {
|
|
2714
3623
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2715
3624
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2716
3625
|
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;
|
|
2717
3626
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2718
3627
|
};
|
|
2719
|
-
var
|
|
3628
|
+
var __metadata20 = function(k, v) {
|
|
2720
3629
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2721
3630
|
};
|
|
2722
3631
|
var __param5 = function(paramIndex, decorator) {
|
|
@@ -2724,8 +3633,8 @@ var __param5 = function(paramIndex, decorator) {
|
|
|
2724
3633
|
decorator(target, key, paramIndex);
|
|
2725
3634
|
};
|
|
2726
3635
|
};
|
|
2727
|
-
var
|
|
2728
|
-
var hashKeyPart = /* @__PURE__ */ __name((value) =>
|
|
3636
|
+
var _a12;
|
|
3637
|
+
var hashKeyPart = /* @__PURE__ */ __name((value) => createHash3("sha256").update(value).digest("base64url").slice(0, 32), "hashKeyPart");
|
|
2729
3638
|
var cookieFingerprint = /* @__PURE__ */ __name(() => (ctx) => {
|
|
2730
3639
|
const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
|
|
2731
3640
|
const cookie = ctx.req.raw.headers.get("cookie") ?? "";
|
|
@@ -2737,7 +3646,7 @@ var authIdentityRateLimitKey = /* @__PURE__ */ __name(async (ctx) => {
|
|
|
2737
3646
|
try {
|
|
2738
3647
|
const body = await ctx.req.json();
|
|
2739
3648
|
const identity = body?.identifier ?? body?.email;
|
|
2740
|
-
const normalizedIdentity =
|
|
3649
|
+
const normalizedIdentity = getRequestIdentityResolver(ctx)(identity);
|
|
2741
3650
|
if (normalizedIdentity) {
|
|
2742
3651
|
return `${ip}:${hashKeyPart(normalizedIdentity)}`;
|
|
2743
3652
|
}
|
|
@@ -2767,7 +3676,7 @@ var AuthController = class AuthController2 {
|
|
|
2767
3676
|
}
|
|
2768
3677
|
async recoverSession(recoveryRequest, ctx) {
|
|
2769
3678
|
if (recoveryRequest !== "1") {
|
|
2770
|
-
|
|
3679
|
+
Err13("Invalid session recovery request", 400);
|
|
2771
3680
|
}
|
|
2772
3681
|
ctx.header("Cache-Control", "private, no-store");
|
|
2773
3682
|
ctx.header("Vary", "Cookie");
|
|
@@ -2789,123 +3698,123 @@ var AuthController = class AuthController2 {
|
|
|
2789
3698
|
return this.authService.resetPassword(body.token, body.newPassword);
|
|
2790
3699
|
}
|
|
2791
3700
|
};
|
|
2792
|
-
|
|
3701
|
+
__decorate20([
|
|
2793
3702
|
Post("/register"),
|
|
2794
3703
|
RateLimit({ limit: 5, window: "15m", key: authIdentityRateLimitKey }),
|
|
2795
3704
|
Validate(registerDto),
|
|
2796
3705
|
ResMsg("auth.success.register"),
|
|
2797
3706
|
__param5(0, Body()),
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
3707
|
+
__metadata20("design:type", Function),
|
|
3708
|
+
__metadata20("design:paramtypes", [Object]),
|
|
3709
|
+
__metadata20("design:returntype", Promise)
|
|
2801
3710
|
], AuthController.prototype, "registerUser", null);
|
|
2802
|
-
|
|
3711
|
+
__decorate20([
|
|
2803
3712
|
Post("/login"),
|
|
2804
3713
|
RateLimit({ limit: 5, window: "15m", key: authIdentityRateLimitKey, message: "Too many login attempts. Please try again later." }),
|
|
2805
3714
|
Validate(loginDto),
|
|
2806
3715
|
ResMsg("auth.success.login"),
|
|
2807
3716
|
__param5(0, Body()),
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
3717
|
+
__metadata20("design:type", Function),
|
|
3718
|
+
__metadata20("design:paramtypes", [Object]),
|
|
3719
|
+
__metadata20("design:returntype", Promise)
|
|
2811
3720
|
], AuthController.prototype, "loginUser", null);
|
|
2812
|
-
|
|
3721
|
+
__decorate20([
|
|
2813
3722
|
Post("/invite"),
|
|
2814
3723
|
isAdmin(),
|
|
2815
3724
|
RateLimit({ limit: 20, window: "15m", key: "user" }),
|
|
2816
3725
|
Validate(inviteUserDto),
|
|
2817
3726
|
ResMsg("auth.success.accountInviteSent"),
|
|
2818
3727
|
__param5(0, Body()),
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
3728
|
+
__metadata20("design:type", Function),
|
|
3729
|
+
__metadata20("design:paramtypes", [Object]),
|
|
3730
|
+
__metadata20("design:returntype", Promise)
|
|
2822
3731
|
], AuthController.prototype, "inviteUser", null);
|
|
2823
|
-
|
|
3732
|
+
__decorate20([
|
|
2824
3733
|
Post("/refresh"),
|
|
2825
3734
|
RateLimit({ limit: 15, window: "15m", key: cookieFingerprint() }),
|
|
2826
3735
|
ResMsg("auth.success.tokenRefreshed"),
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
3736
|
+
__metadata20("design:type", Function),
|
|
3737
|
+
__metadata20("design:paramtypes", []),
|
|
3738
|
+
__metadata20("design:returntype", Promise)
|
|
2830
3739
|
], AuthController.prototype, "refreshTokens", null);
|
|
2831
|
-
|
|
3740
|
+
__decorate20([
|
|
2832
3741
|
Post("/session/recover"),
|
|
2833
3742
|
RateLimit({ limit: 120, window: "1m", key: cookieFingerprint() }),
|
|
2834
3743
|
ResMsg("auth.success.sessionRecovered"),
|
|
2835
3744
|
__param5(0, Headers("x-najm-session-recovery")),
|
|
2836
3745
|
__param5(1, Ctx()),
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
3746
|
+
__metadata20("design:type", Function),
|
|
3747
|
+
__metadata20("design:paramtypes", [String, Object]),
|
|
3748
|
+
__metadata20("design:returntype", Promise)
|
|
2840
3749
|
], AuthController.prototype, "recoverSession", null);
|
|
2841
|
-
|
|
3750
|
+
__decorate20([
|
|
2842
3751
|
Post("/logout"),
|
|
2843
3752
|
isAuth(),
|
|
2844
3753
|
RateLimit({ limit: 10, window: "15m", key: "user" }),
|
|
2845
3754
|
__param5(0, User2("id")),
|
|
2846
3755
|
__param5(1, Headers("authorization")),
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
3756
|
+
__metadata20("design:type", Function),
|
|
3757
|
+
__metadata20("design:paramtypes", [String, String]),
|
|
3758
|
+
__metadata20("design:returntype", Promise)
|
|
2850
3759
|
], AuthController.prototype, "logoutUser", null);
|
|
2851
|
-
|
|
3760
|
+
__decorate20([
|
|
2852
3761
|
Post("/change-password"),
|
|
2853
3762
|
isAuth(),
|
|
2854
3763
|
Validate(changePasswordDto),
|
|
2855
3764
|
ResMsg("auth.success.passwordChanged"),
|
|
2856
3765
|
__param5(0, User2("id")),
|
|
2857
3766
|
__param5(1, Body()),
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
3767
|
+
__metadata20("design:type", Function),
|
|
3768
|
+
__metadata20("design:paramtypes", [String, Object]),
|
|
3769
|
+
__metadata20("design:returntype", Promise)
|
|
2861
3770
|
], AuthController.prototype, "changePassword", null);
|
|
2862
|
-
|
|
3771
|
+
__decorate20([
|
|
2863
3772
|
Get("/me"),
|
|
2864
3773
|
RateLimit({ limit: 30, window: "1m", key: cookieFingerprint() }),
|
|
2865
3774
|
ResMsg("auth.users.success.retrieved"),
|
|
2866
3775
|
__param5(0, Headers("authorization")),
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
3776
|
+
__metadata20("design:type", Function),
|
|
3777
|
+
__metadata20("design:paramtypes", [String]),
|
|
3778
|
+
__metadata20("design:returntype", Promise)
|
|
2870
3779
|
], AuthController.prototype, "userProfile", null);
|
|
2871
|
-
|
|
3780
|
+
__decorate20([
|
|
2872
3781
|
Post("/forgot-password"),
|
|
2873
3782
|
RateLimit({ limit: 3, window: "15m", key: authIdentityRateLimitKey, message: "Too many password reset requests. Please try again later." }),
|
|
2874
3783
|
Validate(resetPasswordDto),
|
|
2875
3784
|
ResMsg("auth.success.passwordResetSent"),
|
|
2876
3785
|
__param5(0, Body()),
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
3786
|
+
__metadata20("design:type", Function),
|
|
3787
|
+
__metadata20("design:paramtypes", [Object]),
|
|
3788
|
+
__metadata20("design:returntype", Promise)
|
|
2880
3789
|
], AuthController.prototype, "forgotPassword", null);
|
|
2881
|
-
|
|
3790
|
+
__decorate20([
|
|
2882
3791
|
Post("/reset-password"),
|
|
2883
3792
|
RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many password reset attempts. Please try again later." }),
|
|
2884
3793
|
Validate(confirmResetPasswordDto),
|
|
2885
3794
|
ResMsg("auth.success.passwordReset"),
|
|
2886
3795
|
__param5(0, Body()),
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
3796
|
+
__metadata20("design:type", Function),
|
|
3797
|
+
__metadata20("design:paramtypes", [Object]),
|
|
3798
|
+
__metadata20("design:returntype", Promise)
|
|
2890
3799
|
], AuthController.prototype, "resetPassword", null);
|
|
2891
|
-
AuthController =
|
|
3800
|
+
AuthController = __decorate20([
|
|
2892
3801
|
Controller("/auth"),
|
|
2893
|
-
|
|
3802
|
+
__metadata20("design:paramtypes", [typeof (_a12 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a12 : Object])
|
|
2894
3803
|
], AuthController);
|
|
2895
3804
|
|
|
2896
3805
|
// src/auth/AuthResolver.ts
|
|
2897
|
-
import { APP, Container, DI, Inject as
|
|
3806
|
+
import { APP, Container, DI, Inject as Inject12, LOGGER, Meta, Service as Service4 } from "najm-core";
|
|
2898
3807
|
import { USER, ROLE, PERMISSIONS } from "najm-guard";
|
|
2899
|
-
var
|
|
3808
|
+
var __decorate21 = function(decorators, target, key, desc) {
|
|
2900
3809
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2901
3810
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2902
3811
|
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;
|
|
2903
3812
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2904
3813
|
};
|
|
2905
|
-
var
|
|
3814
|
+
var __metadata21 = function(k, v) {
|
|
2906
3815
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2907
3816
|
};
|
|
2908
|
-
var
|
|
3817
|
+
var _a13;
|
|
2909
3818
|
var AuthResolver = class AuthResolver2 {
|
|
2910
3819
|
static {
|
|
2911
3820
|
__name(this, "AuthResolver");
|
|
@@ -3016,27 +3925,76 @@ var AuthResolver = class AuthResolver2 {
|
|
|
3016
3925
|
await next();
|
|
3017
3926
|
});
|
|
3018
3927
|
}
|
|
3019
|
-
async onReady() {
|
|
3020
|
-
const authService = await this.container.resolve(AuthService);
|
|
3021
|
-
await authService.warmupPasswordHash();
|
|
3928
|
+
async onReady() {
|
|
3929
|
+
const authService = await this.container.resolve(AuthService);
|
|
3930
|
+
await authService.warmupPasswordHash();
|
|
3931
|
+
}
|
|
3932
|
+
};
|
|
3933
|
+
__decorate21([
|
|
3934
|
+
DI(),
|
|
3935
|
+
__metadata21("design:type", typeof (_a13 = typeof Container !== "undefined" && Container) === "function" ? _a13 : Object)
|
|
3936
|
+
], AuthResolver.prototype, "container", void 0);
|
|
3937
|
+
__decorate21([
|
|
3938
|
+
Inject12(APP),
|
|
3939
|
+
__metadata21("design:type", Object)
|
|
3940
|
+
], AuthResolver.prototype, "app", void 0);
|
|
3941
|
+
__decorate21([
|
|
3942
|
+
Inject12(LOGGER),
|
|
3943
|
+
__metadata21("design:type", Object)
|
|
3944
|
+
], AuthResolver.prototype, "log", void 0);
|
|
3945
|
+
AuthResolver = __decorate21([
|
|
3946
|
+
Service4(),
|
|
3947
|
+
Meta({ layer: "plugin", order: 30 })
|
|
3948
|
+
], AuthResolver);
|
|
3949
|
+
|
|
3950
|
+
// src/auth/AuthIdentityContextService.ts
|
|
3951
|
+
import { DI as DI2, Inject as Inject13, INJECTION_TYPES, Meta as Meta2, Service as Service5 } from "najm-core";
|
|
3952
|
+
var __decorate22 = function(decorators, target, key, desc) {
|
|
3953
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3954
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3955
|
+
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;
|
|
3956
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3957
|
+
};
|
|
3958
|
+
var __metadata22 = function(k, v) {
|
|
3959
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3960
|
+
};
|
|
3961
|
+
var __param6 = function(paramIndex, decorator) {
|
|
3962
|
+
return function(target, key) {
|
|
3963
|
+
decorator(target, key, paramIndex);
|
|
3964
|
+
};
|
|
3965
|
+
};
|
|
3966
|
+
var AuthIdentityContextService = class AuthIdentityContextService2 {
|
|
3967
|
+
static {
|
|
3968
|
+
__name(this, "AuthIdentityContextService");
|
|
3969
|
+
}
|
|
3970
|
+
config;
|
|
3971
|
+
container;
|
|
3972
|
+
constructor(config) {
|
|
3973
|
+
this.config = config;
|
|
3974
|
+
}
|
|
3975
|
+
async configure() {
|
|
3976
|
+
this.container.setInjection({
|
|
3977
|
+
type: INJECTION_TYPES.MIDDLEWARE,
|
|
3978
|
+
scope: "global",
|
|
3979
|
+
name: "auth-identity-context",
|
|
3980
|
+
order: 14,
|
|
3981
|
+
handler: /* @__PURE__ */ __name(async (context, next) => {
|
|
3982
|
+
setRequestIdentityResolver(context, this.config.identity.resolve);
|
|
3983
|
+
return next();
|
|
3984
|
+
}, "handler")
|
|
3985
|
+
});
|
|
3022
3986
|
}
|
|
3023
3987
|
};
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
],
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
__metadata16("design:type", Object)
|
|
3035
|
-
], AuthResolver.prototype, "log", void 0);
|
|
3036
|
-
AuthResolver = __decorate16([
|
|
3037
|
-
Service4(),
|
|
3038
|
-
Meta({ layer: "plugin", order: 30 })
|
|
3039
|
-
], AuthResolver);
|
|
3988
|
+
__decorate22([
|
|
3989
|
+
DI2(),
|
|
3990
|
+
__metadata22("design:type", Object)
|
|
3991
|
+
], AuthIdentityContextService.prototype, "container", void 0);
|
|
3992
|
+
AuthIdentityContextService = __decorate22([
|
|
3993
|
+
Service5(),
|
|
3994
|
+
Meta2({ layer: "plugin", order: 14 }),
|
|
3995
|
+
__param6(0, Inject13(AUTH_CONFIG)),
|
|
3996
|
+
__metadata22("design:paramtypes", [Object])
|
|
3997
|
+
], AuthIdentityContextService);
|
|
3040
3998
|
|
|
3041
3999
|
// src/auth/runAsUser.ts
|
|
3042
4000
|
import { randomUUID } from "crypto";
|
|
@@ -3069,7 +4027,8 @@ var AUTH_MODULE = [
|
|
|
3069
4027
|
EncryptionService,
|
|
3070
4028
|
AuthGuard,
|
|
3071
4029
|
AuthController,
|
|
3072
|
-
AuthResolver
|
|
4030
|
+
AuthResolver,
|
|
4031
|
+
AuthIdentityContextService
|
|
3073
4032
|
];
|
|
3074
4033
|
|
|
3075
4034
|
// src/users/index.ts
|
|
@@ -3180,21 +4139,21 @@ var assignRoleDto = z2.object({
|
|
|
3180
4139
|
});
|
|
3181
4140
|
|
|
3182
4141
|
// src/roles/RoleController.ts
|
|
3183
|
-
var
|
|
4142
|
+
var __decorate23 = function(decorators, target, key, desc) {
|
|
3184
4143
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3185
4144
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3186
4145
|
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;
|
|
3187
4146
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3188
4147
|
};
|
|
3189
|
-
var
|
|
4148
|
+
var __metadata23 = function(k, v) {
|
|
3190
4149
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3191
4150
|
};
|
|
3192
|
-
var
|
|
4151
|
+
var __param7 = function(paramIndex, decorator) {
|
|
3193
4152
|
return function(target, key) {
|
|
3194
4153
|
decorator(target, key, paramIndex);
|
|
3195
4154
|
};
|
|
3196
4155
|
};
|
|
3197
|
-
var
|
|
4156
|
+
var _a14;
|
|
3198
4157
|
var RoleController = class RoleController2 {
|
|
3199
4158
|
static {
|
|
3200
4159
|
__name(this, "RoleController");
|
|
@@ -3219,35 +4178,35 @@ var RoleController = class RoleController2 {
|
|
|
3219
4178
|
return this.roleService.delete(params.id);
|
|
3220
4179
|
}
|
|
3221
4180
|
};
|
|
3222
|
-
|
|
4181
|
+
__decorate23([
|
|
3223
4182
|
Get2(),
|
|
3224
4183
|
isAdmin(),
|
|
3225
4184
|
ResMsg2("roles.success.retrieved"),
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
4185
|
+
__metadata23("design:type", Function),
|
|
4186
|
+
__metadata23("design:paramtypes", []),
|
|
4187
|
+
__metadata23("design:returntype", Promise)
|
|
3229
4188
|
], RoleController.prototype, "getRoles", null);
|
|
3230
|
-
|
|
4189
|
+
__decorate23([
|
|
3231
4190
|
Get2("/:id"),
|
|
3232
4191
|
isAdmin(),
|
|
3233
4192
|
Validate2({ params: roleIdParam }),
|
|
3234
4193
|
ResMsg2("roles.success.retrieved"),
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
4194
|
+
__param7(0, Params()),
|
|
4195
|
+
__metadata23("design:type", Function),
|
|
4196
|
+
__metadata23("design:paramtypes", [Object]),
|
|
4197
|
+
__metadata23("design:returntype", Promise)
|
|
3239
4198
|
], RoleController.prototype, "getRole", null);
|
|
3240
|
-
|
|
4199
|
+
__decorate23([
|
|
3241
4200
|
Post2(),
|
|
3242
4201
|
isAdmin(),
|
|
3243
4202
|
Validate2(createRoleDto),
|
|
3244
4203
|
ResMsg2("roles.success.created"),
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
4204
|
+
__param7(0, Body2()),
|
|
4205
|
+
__metadata23("design:type", Function),
|
|
4206
|
+
__metadata23("design:paramtypes", [Object]),
|
|
4207
|
+
__metadata23("design:returntype", Promise)
|
|
3249
4208
|
], RoleController.prototype, "createRole", null);
|
|
3250
|
-
|
|
4209
|
+
__decorate23([
|
|
3251
4210
|
Put("/:id"),
|
|
3252
4211
|
isAdmin(),
|
|
3253
4212
|
Validate2({
|
|
@@ -3255,44 +4214,44 @@ __decorate17([
|
|
|
3255
4214
|
body: updateRoleDto
|
|
3256
4215
|
}),
|
|
3257
4216
|
ResMsg2("roles.success.updated"),
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
4217
|
+
__param7(0, Params()),
|
|
4218
|
+
__param7(1, Body2()),
|
|
4219
|
+
__metadata23("design:type", Function),
|
|
4220
|
+
__metadata23("design:paramtypes", [Object, Object]),
|
|
4221
|
+
__metadata23("design:returntype", Promise)
|
|
3263
4222
|
], RoleController.prototype, "updateRole", null);
|
|
3264
|
-
|
|
4223
|
+
__decorate23([
|
|
3265
4224
|
Delete("/:id"),
|
|
3266
4225
|
isAdmin(),
|
|
3267
4226
|
Validate2({ params: roleIdParam }),
|
|
3268
4227
|
ResMsg2("roles.success.deleted"),
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
4228
|
+
__param7(0, Params()),
|
|
4229
|
+
__metadata23("design:type", Function),
|
|
4230
|
+
__metadata23("design:paramtypes", [Object]),
|
|
4231
|
+
__metadata23("design:returntype", Promise)
|
|
3273
4232
|
], RoleController.prototype, "deleteRole", null);
|
|
3274
|
-
RoleController =
|
|
4233
|
+
RoleController = __decorate23([
|
|
3275
4234
|
Controller2("/roles"),
|
|
3276
|
-
|
|
4235
|
+
__metadata23("design:paramtypes", [typeof (_a14 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a14 : Object])
|
|
3277
4236
|
], RoleController);
|
|
3278
4237
|
|
|
3279
4238
|
// src/users/UserController.ts
|
|
3280
4239
|
import { Validate as Validate3 } from "najm-validation";
|
|
3281
|
-
var
|
|
4240
|
+
var __decorate24 = function(decorators, target, key, desc) {
|
|
3282
4241
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3283
4242
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3284
4243
|
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;
|
|
3285
4244
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3286
4245
|
};
|
|
3287
|
-
var
|
|
4246
|
+
var __metadata24 = function(k, v) {
|
|
3288
4247
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3289
4248
|
};
|
|
3290
|
-
var
|
|
4249
|
+
var __param8 = function(paramIndex, decorator) {
|
|
3291
4250
|
return function(target, key) {
|
|
3292
4251
|
decorator(target, key, paramIndex);
|
|
3293
4252
|
};
|
|
3294
4253
|
};
|
|
3295
|
-
var
|
|
4254
|
+
var _a15;
|
|
3296
4255
|
var UserController = class UserController2 {
|
|
3297
4256
|
static {
|
|
3298
4257
|
__name(this, "UserController");
|
|
@@ -3339,75 +4298,75 @@ var UserController = class UserController2 {
|
|
|
3339
4298
|
return this.userService.removeRole(params.userId);
|
|
3340
4299
|
}
|
|
3341
4300
|
};
|
|
3342
|
-
|
|
4301
|
+
__decorate24([
|
|
3343
4302
|
Get3(),
|
|
3344
4303
|
isAdmin(),
|
|
3345
4304
|
Validate3({ query: userListQuery }),
|
|
3346
4305
|
ResMsg3("users.success.retrieved"),
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
4306
|
+
__param8(0, Query()),
|
|
4307
|
+
__metadata24("design:type", Function),
|
|
4308
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4309
|
+
__metadata24("design:returntype", Promise)
|
|
3351
4310
|
], UserController.prototype, "getUsers", null);
|
|
3352
|
-
|
|
4311
|
+
__decorate24([
|
|
3353
4312
|
Get3("/lang"),
|
|
3354
4313
|
isAuth(),
|
|
3355
4314
|
ResMsg3("users.success.retrieved"),
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
4315
|
+
__metadata24("design:type", Function),
|
|
4316
|
+
__metadata24("design:paramtypes", []),
|
|
4317
|
+
__metadata24("design:returntype", Promise)
|
|
3359
4318
|
], UserController.prototype, "getLang", null);
|
|
3360
|
-
|
|
4319
|
+
__decorate24([
|
|
3361
4320
|
Post3("/lang/:language"),
|
|
3362
4321
|
isAuth(),
|
|
3363
4322
|
Validate3({ params: languageParam }),
|
|
3364
4323
|
ResMsg3("users.success.updated"),
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
4324
|
+
__param8(0, Params2()),
|
|
4325
|
+
__metadata24("design:type", Function),
|
|
4326
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4327
|
+
__metadata24("design:returntype", Promise)
|
|
3369
4328
|
], UserController.prototype, "updateLang", null);
|
|
3370
|
-
|
|
4329
|
+
__decorate24([
|
|
3371
4330
|
Get3("/:id"),
|
|
3372
4331
|
isAdmin(),
|
|
3373
4332
|
Validate3({ params: userIdParam }),
|
|
3374
4333
|
ResMsg3("users.success.retrieved"),
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
4334
|
+
__param8(0, Params2()),
|
|
4335
|
+
__metadata24("design:type", Function),
|
|
4336
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4337
|
+
__metadata24("design:returntype", Promise)
|
|
3379
4338
|
], UserController.prototype, "getUser", null);
|
|
3380
|
-
|
|
4339
|
+
__decorate24([
|
|
3381
4340
|
Get3("/email/:email"),
|
|
3382
4341
|
isAdmin(),
|
|
3383
4342
|
Validate3({ params: emailParam }),
|
|
3384
4343
|
ResMsg3("users.success.retrieved"),
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
4344
|
+
__param8(0, Params2()),
|
|
4345
|
+
__metadata24("design:type", Function),
|
|
4346
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4347
|
+
__metadata24("design:returntype", Promise)
|
|
3389
4348
|
], UserController.prototype, "getByEmail", null);
|
|
3390
|
-
|
|
4349
|
+
__decorate24([
|
|
3391
4350
|
Get3("/role/:userId"),
|
|
3392
4351
|
isAdmin(),
|
|
3393
4352
|
Validate3({ params: userIdInParam }),
|
|
3394
4353
|
ResMsg3("users.success.retrieved"),
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
4354
|
+
__param8(0, Params2()),
|
|
4355
|
+
__metadata24("design:type", Function),
|
|
4356
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4357
|
+
__metadata24("design:returntype", Promise)
|
|
3399
4358
|
], UserController.prototype, "getRole", null);
|
|
3400
|
-
|
|
4359
|
+
__decorate24([
|
|
3401
4360
|
Post3(),
|
|
3402
4361
|
isAdmin(),
|
|
3403
4362
|
Validate3(createUserDto),
|
|
3404
4363
|
ResMsg3("users.success.created"),
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
4364
|
+
__param8(0, Body3()),
|
|
4365
|
+
__metadata24("design:type", Function),
|
|
4366
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4367
|
+
__metadata24("design:returntype", Promise)
|
|
3409
4368
|
], UserController.prototype, "create", null);
|
|
3410
|
-
|
|
4369
|
+
__decorate24([
|
|
3411
4370
|
Put2("/:id"),
|
|
3412
4371
|
isAdmin(),
|
|
3413
4372
|
Validate3({
|
|
@@ -3415,53 +4374,53 @@ __decorate18([
|
|
|
3415
4374
|
body: updateUserDto
|
|
3416
4375
|
}),
|
|
3417
4376
|
ResMsg3("users.success.updated"),
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
4377
|
+
__param8(0, Params2()),
|
|
4378
|
+
__param8(1, Body3()),
|
|
4379
|
+
__metadata24("design:type", Function),
|
|
4380
|
+
__metadata24("design:paramtypes", [Object, Object]),
|
|
4381
|
+
__metadata24("design:returntype", Promise)
|
|
3423
4382
|
], UserController.prototype, "update", null);
|
|
3424
|
-
|
|
4383
|
+
__decorate24([
|
|
3425
4384
|
Delete2("/:id"),
|
|
3426
4385
|
isAdmin(),
|
|
3427
4386
|
Validate3({ params: userIdParam }),
|
|
3428
4387
|
ResMsg3("users.success.deleted"),
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
4388
|
+
__param8(0, Params2()),
|
|
4389
|
+
__metadata24("design:type", Function),
|
|
4390
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4391
|
+
__metadata24("design:returntype", Promise)
|
|
3433
4392
|
], UserController.prototype, "delete", null);
|
|
3434
|
-
|
|
4393
|
+
__decorate24([
|
|
3435
4394
|
Delete2(),
|
|
3436
4395
|
isAdmin(),
|
|
3437
4396
|
ResMsg3("users.success.allDeleted"),
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
4397
|
+
__metadata24("design:type", Function),
|
|
4398
|
+
__metadata24("design:paramtypes", []),
|
|
4399
|
+
__metadata24("design:returntype", Promise)
|
|
3441
4400
|
], UserController.prototype, "deleteAll", null);
|
|
3442
|
-
|
|
4401
|
+
__decorate24([
|
|
3443
4402
|
Post3("/assign/:userId/:roleId"),
|
|
3444
4403
|
isAdmin(),
|
|
3445
4404
|
Validate3({ params: assignRoleParams }),
|
|
3446
4405
|
ResMsg3("users.success.updated"),
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
4406
|
+
__param8(0, Params2()),
|
|
4407
|
+
__metadata24("design:type", Function),
|
|
4408
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4409
|
+
__metadata24("design:returntype", Promise)
|
|
3451
4410
|
], UserController.prototype, "assignRole", null);
|
|
3452
|
-
|
|
4411
|
+
__decorate24([
|
|
3453
4412
|
Delete2("/remove/:userId"),
|
|
3454
4413
|
isAdmin(),
|
|
3455
4414
|
Validate3({ params: userIdInParam }),
|
|
3456
4415
|
ResMsg3("users.success.updated"),
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
4416
|
+
__param8(0, Params2()),
|
|
4417
|
+
__metadata24("design:type", Function),
|
|
4418
|
+
__metadata24("design:paramtypes", [Object]),
|
|
4419
|
+
__metadata24("design:returntype", Promise)
|
|
3461
4420
|
], UserController.prototype, "removeRole", null);
|
|
3462
|
-
UserController =
|
|
4421
|
+
UserController = __decorate24([
|
|
3463
4422
|
Controller3("/users"),
|
|
3464
|
-
|
|
4423
|
+
__metadata24("design:paramtypes", [typeof (_a15 = typeof UserService !== "undefined" && UserService) === "function" ? _a15 : Object])
|
|
3465
4424
|
], UserController);
|
|
3466
4425
|
|
|
3467
4426
|
// src/permissions/index.ts
|
|
@@ -3481,16 +4440,16 @@ __export(permissions_exports, {
|
|
|
3481
4440
|
});
|
|
3482
4441
|
|
|
3483
4442
|
// src/permissions/PermissionRepository.ts
|
|
3484
|
-
import { eq as
|
|
3485
|
-
import { Repository as
|
|
3486
|
-
import { DB as
|
|
3487
|
-
var
|
|
4443
|
+
import { eq as eq7, and as and4 } from "drizzle-orm";
|
|
4444
|
+
import { Repository as Repository6, Inject as Inject14 } from "najm-core";
|
|
4445
|
+
import { DB as DB6 } from "najm-database";
|
|
4446
|
+
var __decorate25 = function(decorators, target, key, desc) {
|
|
3488
4447
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3489
4448
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3490
4449
|
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;
|
|
3491
4450
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3492
4451
|
};
|
|
3493
|
-
var
|
|
4452
|
+
var __metadata25 = function(k, v) {
|
|
3494
4453
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3495
4454
|
};
|
|
3496
4455
|
var PermissionRepository = class PermissionRepository2 {
|
|
@@ -3512,26 +4471,26 @@ var PermissionRepository = class PermissionRepository2 {
|
|
|
3512
4471
|
return await this.db.select().from(this.permissions);
|
|
3513
4472
|
}
|
|
3514
4473
|
async getById(id) {
|
|
3515
|
-
const [existingPermission] = await this.db.select().from(this.permissions).where(
|
|
4474
|
+
const [existingPermission] = await this.db.select().from(this.permissions).where(eq7(this.permissions.id, id));
|
|
3516
4475
|
return existingPermission;
|
|
3517
4476
|
}
|
|
3518
4477
|
async getByName(name) {
|
|
3519
|
-
const [existingPermission] = await this.db.select().from(this.permissions).where(
|
|
4478
|
+
const [existingPermission] = await this.db.select().from(this.permissions).where(eq7(this.permissions.name, name));
|
|
3520
4479
|
return existingPermission;
|
|
3521
4480
|
}
|
|
3522
4481
|
async getByResource(resource) {
|
|
3523
|
-
return await this.db.select().from(this.permissions).where(
|
|
4482
|
+
return await this.db.select().from(this.permissions).where(eq7(this.permissions.resource, resource));
|
|
3524
4483
|
}
|
|
3525
4484
|
async create(data) {
|
|
3526
4485
|
const [newPermission] = await this.db.insert(this.permissions).values(data).returning();
|
|
3527
4486
|
return newPermission;
|
|
3528
4487
|
}
|
|
3529
4488
|
async update(id, data) {
|
|
3530
|
-
const [updatedPermission] = await this.db.update(this.permissions).set(data).where(
|
|
4489
|
+
const [updatedPermission] = await this.db.update(this.permissions).set(data).where(eq7(this.permissions.id, id)).returning();
|
|
3531
4490
|
return updatedPermission;
|
|
3532
4491
|
}
|
|
3533
4492
|
async delete(id) {
|
|
3534
|
-
const [deletedPermission] = await this.db.delete(this.permissions).where(
|
|
4493
|
+
const [deletedPermission] = await this.db.delete(this.permissions).where(eq7(this.permissions.id, id)).returning();
|
|
3535
4494
|
return deletedPermission;
|
|
3536
4495
|
}
|
|
3537
4496
|
async getPermissionsByRole(roleId) {
|
|
@@ -3541,25 +4500,25 @@ var PermissionRepository = class PermissionRepository2 {
|
|
|
3541
4500
|
description: this.permissions.description,
|
|
3542
4501
|
resource: this.permissions.resource,
|
|
3543
4502
|
action: this.permissions.action
|
|
3544
|
-
}).from(this.rolePermissions).leftJoin(this.permissions,
|
|
4503
|
+
}).from(this.rolePermissions).leftJoin(this.permissions, eq7(this.rolePermissions.permissionId, this.permissions.id)).where(eq7(this.rolePermissions.roleId, roleId));
|
|
3545
4504
|
}
|
|
3546
4505
|
async getRolesByPermission(permissionId) {
|
|
3547
4506
|
return await this.db.select({
|
|
3548
4507
|
id: this.roles.id,
|
|
3549
4508
|
name: this.roles.name,
|
|
3550
4509
|
description: this.roles.description
|
|
3551
|
-
}).from(this.rolePermissions).leftJoin(this.roles,
|
|
4510
|
+
}).from(this.rolePermissions).leftJoin(this.roles, eq7(this.rolePermissions.roleId, this.roles.id)).where(eq7(this.rolePermissions.permissionId, permissionId));
|
|
3552
4511
|
}
|
|
3553
4512
|
async assignPermissionToRole(roleId, permissionId) {
|
|
3554
4513
|
const [newRolePermission] = await this.db.insert(this.rolePermissions).values({ roleId, permissionId }).returning();
|
|
3555
4514
|
return newRolePermission;
|
|
3556
4515
|
}
|
|
3557
4516
|
async removePermissionFromRole(roleId, permissionId) {
|
|
3558
|
-
const [deletedRolePermission] = await this.db.delete(this.rolePermissions).where(
|
|
4517
|
+
const [deletedRolePermission] = await this.db.delete(this.rolePermissions).where(and4(eq7(this.rolePermissions.roleId, roleId), eq7(this.rolePermissions.permissionId, permissionId))).returning();
|
|
3559
4518
|
return deletedRolePermission;
|
|
3560
4519
|
}
|
|
3561
4520
|
async checkRoleHasPermission(roleId, permissionId) {
|
|
3562
|
-
const [rolePermission] = await this.db.select().from(this.rolePermissions).where(
|
|
4521
|
+
const [rolePermission] = await this.db.select().from(this.rolePermissions).where(and4(eq7(this.rolePermissions.roleId, roleId), eq7(this.rolePermissions.permissionId, permissionId)));
|
|
3563
4522
|
return !!rolePermission;
|
|
3564
4523
|
}
|
|
3565
4524
|
async deleteAll() {
|
|
@@ -3568,32 +4527,32 @@ var PermissionRepository = class PermissionRepository2 {
|
|
|
3568
4527
|
return deletedPermissions;
|
|
3569
4528
|
}
|
|
3570
4529
|
};
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
4530
|
+
__decorate25([
|
|
4531
|
+
DB6(),
|
|
4532
|
+
__metadata25("design:type", Object)
|
|
3574
4533
|
], PermissionRepository.prototype, "db", void 0);
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
4534
|
+
__decorate25([
|
|
4535
|
+
Inject14(AUTH_SCHEMA),
|
|
4536
|
+
__metadata25("design:type", Object)
|
|
3578
4537
|
], PermissionRepository.prototype, "schema", void 0);
|
|
3579
|
-
PermissionRepository =
|
|
3580
|
-
|
|
4538
|
+
PermissionRepository = __decorate25([
|
|
4539
|
+
Repository6()
|
|
3581
4540
|
], PermissionRepository);
|
|
3582
4541
|
|
|
3583
4542
|
// src/permissions/PermissionGuards.ts
|
|
3584
|
-
import { Injectable as
|
|
4543
|
+
import { Injectable as Injectable12 } from "najm-core";
|
|
3585
4544
|
import { GuardParams as GuardParams2, User as User3 } from "najm-core";
|
|
3586
4545
|
import { createGuard as createGuard4, composeGuards as composeGuards3 } from "najm-guard";
|
|
3587
|
-
var
|
|
4546
|
+
var __decorate26 = function(decorators, target, key, desc) {
|
|
3588
4547
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3589
4548
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3590
4549
|
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;
|
|
3591
4550
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3592
4551
|
};
|
|
3593
|
-
var
|
|
4552
|
+
var __metadata26 = function(k, v) {
|
|
3594
4553
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3595
4554
|
};
|
|
3596
|
-
var
|
|
4555
|
+
var __param9 = function(paramIndex, decorator) {
|
|
3597
4556
|
return function(target, key) {
|
|
3598
4557
|
decorator(target, key, paramIndex);
|
|
3599
4558
|
};
|
|
@@ -3626,15 +4585,15 @@ var PermissionGuard = class PermissionGuard2 {
|
|
|
3626
4585
|
return false;
|
|
3627
4586
|
}
|
|
3628
4587
|
};
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
4588
|
+
__decorate26([
|
|
4589
|
+
__param9(0, GuardParams2()),
|
|
4590
|
+
__param9(1, User3("permissions")),
|
|
4591
|
+
__metadata26("design:type", Function),
|
|
4592
|
+
__metadata26("design:paramtypes", [String, Array]),
|
|
4593
|
+
__metadata26("design:returntype", Object)
|
|
3635
4594
|
], PermissionGuard.prototype, "canActivate", null);
|
|
3636
|
-
PermissionGuard =
|
|
3637
|
-
|
|
4595
|
+
PermissionGuard = __decorate26([
|
|
4596
|
+
Injectable12()
|
|
3638
4597
|
], PermissionGuard);
|
|
3639
4598
|
var Permission = createGuard4(PermissionGuard);
|
|
3640
4599
|
var Can = /* @__PURE__ */ __name((permission) => composeGuards3(isAuth(), Permission(permission))(), "Can");
|
|
@@ -3645,23 +4604,23 @@ import { Get as Get4, Post as Post4, Put as Put3, Delete as Delete3, ResMsg as R
|
|
|
3645
4604
|
import { Params as Params3, Body as Body4 } from "najm-core";
|
|
3646
4605
|
|
|
3647
4606
|
// src/permissions/PermissionService.ts
|
|
3648
|
-
import { Injectable as
|
|
4607
|
+
import { Injectable as Injectable14 } from "najm-core";
|
|
3649
4608
|
|
|
3650
4609
|
// src/permissions/PermissionValidator.ts
|
|
3651
|
-
import { Injectable as
|
|
3652
|
-
import { I18n as
|
|
3653
|
-
import { Err as
|
|
3654
|
-
var
|
|
4610
|
+
import { Injectable as Injectable13 } from "najm-core";
|
|
4611
|
+
import { I18n as I18n9 } from "najm-i18n";
|
|
4612
|
+
import { Err as Err14 } from "najm-core";
|
|
4613
|
+
var __decorate27 = function(decorators, target, key, desc) {
|
|
3655
4614
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3656
4615
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3657
4616
|
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;
|
|
3658
4617
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3659
4618
|
};
|
|
3660
|
-
var
|
|
4619
|
+
var __metadata27 = function(k, v) {
|
|
3661
4620
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3662
4621
|
};
|
|
3663
|
-
var
|
|
3664
|
-
var
|
|
4622
|
+
var _a16;
|
|
4623
|
+
var _b10;
|
|
3665
4624
|
var PermissionValidator = class PermissionValidator2 {
|
|
3666
4625
|
static {
|
|
3667
4626
|
__name(this, "PermissionValidator");
|
|
@@ -3679,7 +4638,7 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3679
4638
|
async checkPermissionExists(id) {
|
|
3680
4639
|
const permission = await this.permissionRepository.getById(id);
|
|
3681
4640
|
if (!permission) {
|
|
3682
|
-
|
|
4641
|
+
Err14(this.t("errors.notFound"), 404);
|
|
3683
4642
|
}
|
|
3684
4643
|
return permission;
|
|
3685
4644
|
}
|
|
@@ -3689,7 +4648,7 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3689
4648
|
async checkPermissionExistsByName(name) {
|
|
3690
4649
|
const permission = await this.permissionRepository.getByName(name);
|
|
3691
4650
|
if (!permission) {
|
|
3692
|
-
|
|
4651
|
+
Err14(this.t("errors.notFound"), 404);
|
|
3693
4652
|
}
|
|
3694
4653
|
return permission;
|
|
3695
4654
|
}
|
|
@@ -3701,7 +4660,7 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3701
4660
|
return;
|
|
3702
4661
|
const existingPermission = await this.permissionRepository.getByName(name);
|
|
3703
4662
|
if (existingPermission && existingPermission.id !== excludeId) {
|
|
3704
|
-
|
|
4663
|
+
Err14(this.t("errors.nameExists"), 409);
|
|
3705
4664
|
}
|
|
3706
4665
|
}
|
|
3707
4666
|
/**
|
|
@@ -3724,32 +4683,32 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3724
4683
|
await this.checkPermissionExists(permissionId);
|
|
3725
4684
|
const hasPermission = await this.permissionRepository.checkRoleHasPermission(roleId, permissionId);
|
|
3726
4685
|
if (hasPermission) {
|
|
3727
|
-
|
|
4686
|
+
Err14(this.t("errors.roleAlreadyHasPermission"), 409);
|
|
3728
4687
|
}
|
|
3729
4688
|
}
|
|
3730
4689
|
};
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
4690
|
+
__decorate27([
|
|
4691
|
+
I18n9("permissions"),
|
|
4692
|
+
__metadata27("design:type", Object)
|
|
3734
4693
|
], PermissionValidator.prototype, "t", void 0);
|
|
3735
|
-
PermissionValidator =
|
|
3736
|
-
|
|
3737
|
-
|
|
4694
|
+
PermissionValidator = __decorate27([
|
|
4695
|
+
Injectable13(),
|
|
4696
|
+
__metadata27("design:paramtypes", [typeof (_a16 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a16 : Object, typeof (_b10 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b10 : Object])
|
|
3738
4697
|
], PermissionValidator);
|
|
3739
4698
|
|
|
3740
4699
|
// src/permissions/PermissionService.ts
|
|
3741
|
-
var
|
|
4700
|
+
var __decorate28 = function(decorators, target, key, desc) {
|
|
3742
4701
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3743
4702
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3744
4703
|
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;
|
|
3745
4704
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3746
4705
|
};
|
|
3747
|
-
var
|
|
4706
|
+
var __metadata28 = function(k, v) {
|
|
3748
4707
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3749
4708
|
};
|
|
3750
|
-
var
|
|
3751
|
-
var
|
|
3752
|
-
var
|
|
4709
|
+
var _a17;
|
|
4710
|
+
var _b11;
|
|
4711
|
+
var _c8;
|
|
3753
4712
|
var PermissionService = class PermissionService2 {
|
|
3754
4713
|
static {
|
|
3755
4714
|
__name(this, "PermissionService");
|
|
@@ -3854,9 +4813,9 @@ var PermissionService = class PermissionService2 {
|
|
|
3854
4813
|
return await this.permissionRepository.deleteAll();
|
|
3855
4814
|
}
|
|
3856
4815
|
};
|
|
3857
|
-
PermissionService =
|
|
3858
|
-
|
|
3859
|
-
|
|
4816
|
+
PermissionService = __decorate28([
|
|
4817
|
+
Injectable14(),
|
|
4818
|
+
__metadata28("design:paramtypes", [typeof (_a17 = typeof PermissionRepository !== "undefined" && PermissionRepository) === "function" ? _a17 : Object, typeof (_b11 = typeof PermissionValidator !== "undefined" && PermissionValidator) === "function" ? _b11 : Object, typeof (_c8 = typeof RoleService !== "undefined" && RoleService) === "function" ? _c8 : Object])
|
|
3860
4819
|
], PermissionService);
|
|
3861
4820
|
|
|
3862
4821
|
// src/permissions/PermissionController.ts
|
|
@@ -3889,21 +4848,21 @@ var checkPermissionDto = z3.object({
|
|
|
3889
4848
|
});
|
|
3890
4849
|
|
|
3891
4850
|
// src/permissions/PermissionController.ts
|
|
3892
|
-
var
|
|
4851
|
+
var __decorate29 = function(decorators, target, key, desc) {
|
|
3893
4852
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3894
4853
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3895
4854
|
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;
|
|
3896
4855
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3897
4856
|
};
|
|
3898
|
-
var
|
|
4857
|
+
var __metadata29 = function(k, v) {
|
|
3899
4858
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
3900
4859
|
};
|
|
3901
|
-
var
|
|
4860
|
+
var __param10 = function(paramIndex, decorator) {
|
|
3902
4861
|
return function(target, key) {
|
|
3903
4862
|
decorator(target, key, paramIndex);
|
|
3904
4863
|
};
|
|
3905
4864
|
};
|
|
3906
|
-
var
|
|
4865
|
+
var _a18;
|
|
3907
4866
|
var PermissionController = class PermissionController2 {
|
|
3908
4867
|
static {
|
|
3909
4868
|
__name(this, "PermissionController");
|
|
@@ -3949,101 +4908,101 @@ var PermissionController = class PermissionController2 {
|
|
|
3949
4908
|
return this.permissionService.deleteAll();
|
|
3950
4909
|
}
|
|
3951
4910
|
};
|
|
3952
|
-
|
|
4911
|
+
__decorate29([
|
|
3953
4912
|
Get4(),
|
|
3954
4913
|
ResMsg4("permissions.success.retrieved"),
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
4914
|
+
__metadata29("design:type", Function),
|
|
4915
|
+
__metadata29("design:paramtypes", []),
|
|
4916
|
+
__metadata29("design:returntype", Promise)
|
|
3958
4917
|
], PermissionController.prototype, "getPermissions", null);
|
|
3959
|
-
|
|
4918
|
+
__decorate29([
|
|
3960
4919
|
Get4("/:id"),
|
|
3961
4920
|
Validate4({ params: permissionIdParam }),
|
|
3962
4921
|
ResMsg4("permissions.success.retrieved"),
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
4922
|
+
__param10(0, Params3()),
|
|
4923
|
+
__metadata29("design:type", Function),
|
|
4924
|
+
__metadata29("design:paramtypes", [Object]),
|
|
4925
|
+
__metadata29("design:returntype", Promise)
|
|
3967
4926
|
], PermissionController.prototype, "getPermission", null);
|
|
3968
|
-
|
|
4927
|
+
__decorate29([
|
|
3969
4928
|
Post4(),
|
|
3970
4929
|
Validate4(createPermissionDto),
|
|
3971
4930
|
ResMsg4({ message: "Permission created successfully", status: 201 }),
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
4931
|
+
__param10(0, Body4()),
|
|
4932
|
+
__metadata29("design:type", Function),
|
|
4933
|
+
__metadata29("design:paramtypes", [Object]),
|
|
4934
|
+
__metadata29("design:returntype", Promise)
|
|
3976
4935
|
], PermissionController.prototype, "create", null);
|
|
3977
|
-
|
|
4936
|
+
__decorate29([
|
|
3978
4937
|
Put3("/:id"),
|
|
3979
4938
|
Validate4({
|
|
3980
4939
|
params: permissionIdParam,
|
|
3981
4940
|
body: updatePermissionDto
|
|
3982
4941
|
}),
|
|
3983
4942
|
ResMsg4("permissions.success.updated"),
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
4943
|
+
__param10(0, Params3()),
|
|
4944
|
+
__param10(1, Body4()),
|
|
4945
|
+
__metadata29("design:type", Function),
|
|
4946
|
+
__metadata29("design:paramtypes", [Object, Object]),
|
|
4947
|
+
__metadata29("design:returntype", Promise)
|
|
3989
4948
|
], PermissionController.prototype, "update", null);
|
|
3990
|
-
|
|
4949
|
+
__decorate29([
|
|
3991
4950
|
Delete3("/:id"),
|
|
3992
4951
|
Validate4({ params: permissionIdParam }),
|
|
3993
4952
|
ResMsg4("permissions.success.deleted"),
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
4953
|
+
__param10(0, Params3()),
|
|
4954
|
+
__metadata29("design:type", Function),
|
|
4955
|
+
__metadata29("design:paramtypes", [Object]),
|
|
4956
|
+
__metadata29("design:returntype", Promise)
|
|
3998
4957
|
], PermissionController.prototype, "delete", null);
|
|
3999
|
-
|
|
4958
|
+
__decorate29([
|
|
4000
4959
|
Get4("/role/:id"),
|
|
4001
4960
|
Validate4({ params: roleIdParam }),
|
|
4002
4961
|
ResMsg4("permissions.success.retrieved"),
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4962
|
+
__param10(0, Params3()),
|
|
4963
|
+
__metadata29("design:type", Function),
|
|
4964
|
+
__metadata29("design:paramtypes", [Object]),
|
|
4965
|
+
__metadata29("design:returntype", Promise)
|
|
4007
4966
|
], PermissionController.prototype, "getByRole", null);
|
|
4008
|
-
|
|
4967
|
+
__decorate29([
|
|
4009
4968
|
Get4("/roles/:id"),
|
|
4010
4969
|
Validate4({ params: permissionIdParam }),
|
|
4011
4970
|
ResMsg4("permissions.success.retrieved"),
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4971
|
+
__param10(0, Params3()),
|
|
4972
|
+
__metadata29("design:type", Function),
|
|
4973
|
+
__metadata29("design:paramtypes", [Object]),
|
|
4974
|
+
__metadata29("design:returntype", Promise)
|
|
4016
4975
|
], PermissionController.prototype, "getRolesByPermission", null);
|
|
4017
|
-
|
|
4976
|
+
__decorate29([
|
|
4018
4977
|
Post4("/assign/:roleId/:permissionId"),
|
|
4019
4978
|
Validate4({ params: assignPermissionDto }),
|
|
4020
4979
|
ResMsg4("permissions.success.assigned"),
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4980
|
+
__param10(0, Params3()),
|
|
4981
|
+
__metadata29("design:type", Function),
|
|
4982
|
+
__metadata29("design:paramtypes", [Object]),
|
|
4983
|
+
__metadata29("design:returntype", Promise)
|
|
4025
4984
|
], PermissionController.prototype, "assignToRole", null);
|
|
4026
|
-
|
|
4985
|
+
__decorate29([
|
|
4027
4986
|
Delete3("/remove/:roleId/:permissionId"),
|
|
4028
4987
|
Validate4({ params: assignPermissionDto }),
|
|
4029
4988
|
ResMsg4("permissions.success.removed"),
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4989
|
+
__param10(0, Params3()),
|
|
4990
|
+
__metadata29("design:type", Function),
|
|
4991
|
+
__metadata29("design:paramtypes", [Object]),
|
|
4992
|
+
__metadata29("design:returntype", Promise)
|
|
4034
4993
|
], PermissionController.prototype, "removeFromRole", null);
|
|
4035
|
-
|
|
4994
|
+
__decorate29([
|
|
4036
4995
|
Delete3(),
|
|
4037
4996
|
isAdmin(),
|
|
4038
4997
|
ResMsg4("permissions.success.allDeleted"),
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4998
|
+
__metadata29("design:type", Function),
|
|
4999
|
+
__metadata29("design:paramtypes", []),
|
|
5000
|
+
__metadata29("design:returntype", Promise)
|
|
4042
5001
|
], PermissionController.prototype, "deleteAll", null);
|
|
4043
|
-
PermissionController =
|
|
5002
|
+
PermissionController = __decorate29([
|
|
4044
5003
|
Controller4("/permissions"),
|
|
4045
5004
|
isAdmin(),
|
|
4046
|
-
|
|
5005
|
+
__metadata29("design:paramtypes", [typeof (_a18 = typeof PermissionService !== "undefined" && PermissionService) === "function" ? _a18 : Object])
|
|
4047
5006
|
], PermissionController);
|
|
4048
5007
|
|
|
4049
5008
|
// src/tokens/index.ts
|
|
@@ -4088,7 +5047,7 @@ var revokeTokenDto = z4.object({
|
|
|
4088
5047
|
});
|
|
4089
5048
|
|
|
4090
5049
|
// src/ownership/scopedOwnership.ts
|
|
4091
|
-
import { aliasedTable, eq as
|
|
5050
|
+
import { aliasedTable, eq as eq8, getTableColumns, sql as sql4 } from "drizzle-orm";
|
|
4092
5051
|
var DEFAULT_ADMIN_ROLES = ["admin"];
|
|
4093
5052
|
var DRIZZLE_NAME = Symbol.for("drizzle:Name");
|
|
4094
5053
|
var DRIZZLE_BASE_NAME = Symbol.for("drizzle:BaseName");
|
|
@@ -4175,8 +5134,8 @@ function compile(steps) {
|
|
|
4175
5134
|
return (uid, query) => {
|
|
4176
5135
|
let q = query;
|
|
4177
5136
|
for (const j of joins)
|
|
4178
|
-
q = q.innerJoin(j.table,
|
|
4179
|
-
return { query: q, condition:
|
|
5137
|
+
q = q.innerJoin(j.table, eq8(j.left, j.right));
|
|
5138
|
+
return { query: q, condition: eq8(owner.col, uid) };
|
|
4180
5139
|
};
|
|
4181
5140
|
}
|
|
4182
5141
|
__name(compile, "compile");
|
|
@@ -4250,18 +5209,18 @@ function own(table, opts) {
|
|
|
4250
5209
|
__name(own, "own");
|
|
4251
5210
|
|
|
4252
5211
|
// src/ownership/configureOwnership.ts
|
|
4253
|
-
import { Injectable as
|
|
5212
|
+
import { Injectable as Injectable15, Inject as Inject15, User as User4, Body as Body5, Params as Params4 } from "najm-core";
|
|
4254
5213
|
import { createGuard as createGuard5, composeGuards as composeGuards4 } from "najm-guard";
|
|
4255
|
-
var
|
|
5214
|
+
var __decorate30 = function(decorators, target, key, desc) {
|
|
4256
5215
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4257
5216
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4258
5217
|
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;
|
|
4259
5218
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
4260
5219
|
};
|
|
4261
|
-
var
|
|
5220
|
+
var __metadata30 = function(k, v) {
|
|
4262
5221
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4263
5222
|
};
|
|
4264
|
-
var
|
|
5223
|
+
var __param11 = function(paramIndex, decorator) {
|
|
4265
5224
|
return function(target, key) {
|
|
4266
5225
|
decorator(target, key, paramIndex);
|
|
4267
5226
|
};
|
|
@@ -4278,7 +5237,7 @@ function toSingular(plural) {
|
|
|
4278
5237
|
}
|
|
4279
5238
|
__name(toSingular, "toSingular");
|
|
4280
5239
|
function createResourceGuards(ownershipClass, resourceType, resource, options) {
|
|
4281
|
-
var
|
|
5240
|
+
var _a26, _b15;
|
|
4282
5241
|
const writeGuard = options?.adminGuard ?? isAdmin;
|
|
4283
5242
|
let AccessGuard = class AccessGuard {
|
|
4284
5243
|
static {
|
|
@@ -4290,19 +5249,19 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
|
|
|
4290
5249
|
return allowed ? { owner: user } : false;
|
|
4291
5250
|
}
|
|
4292
5251
|
};
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
5252
|
+
__decorate30([
|
|
5253
|
+
Inject15(ownershipClass),
|
|
5254
|
+
__metadata30("design:type", Object)
|
|
4296
5255
|
], AccessGuard.prototype, "ownership", void 0);
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
5256
|
+
__decorate30([
|
|
5257
|
+
__param11(0, User4()),
|
|
5258
|
+
__param11(1, Params4("id")),
|
|
5259
|
+
__metadata30("design:type", Function),
|
|
5260
|
+
__metadata30("design:paramtypes", [Object, String]),
|
|
5261
|
+
__metadata30("design:returntype", typeof (_a26 = typeof Promise !== "undefined" && Promise) === "function" ? _a26 : Object)
|
|
4303
5262
|
], AccessGuard.prototype, "canActivate", null);
|
|
4304
|
-
AccessGuard =
|
|
4305
|
-
|
|
5263
|
+
AccessGuard = __decorate30([
|
|
5264
|
+
Injectable15()
|
|
4306
5265
|
], AccessGuard);
|
|
4307
5266
|
let ListGuard = class ListGuard {
|
|
4308
5267
|
static {
|
|
@@ -4314,18 +5273,18 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
|
|
|
4314
5273
|
return { filter: ids };
|
|
4315
5274
|
}
|
|
4316
5275
|
};
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
5276
|
+
__decorate30([
|
|
5277
|
+
Inject15(ownershipClass),
|
|
5278
|
+
__metadata30("design:type", Object)
|
|
4320
5279
|
], ListGuard.prototype, "ownership", void 0);
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
5280
|
+
__decorate30([
|
|
5281
|
+
__param11(0, User4()),
|
|
5282
|
+
__metadata30("design:type", Function),
|
|
5283
|
+
__metadata30("design:paramtypes", [Object]),
|
|
5284
|
+
__metadata30("design:returntype", typeof (_b15 = typeof Promise !== "undefined" && Promise) === "function" ? _b15 : Object)
|
|
4326
5285
|
], ListGuard.prototype, "canActivate", null);
|
|
4327
|
-
ListGuard =
|
|
4328
|
-
|
|
5286
|
+
ListGuard = __decorate30([
|
|
5287
|
+
Injectable15()
|
|
4329
5288
|
], ListGuard);
|
|
4330
5289
|
const access = createGuard5(AccessGuard);
|
|
4331
5290
|
const list = createGuard5(ListGuard);
|
|
@@ -4456,11 +5415,11 @@ function configureOwnership(config) {
|
|
|
4456
5415
|
}
|
|
4457
5416
|
}
|
|
4458
5417
|
};
|
|
4459
|
-
GeneratedOwnershipService =
|
|
4460
|
-
|
|
5418
|
+
GeneratedOwnershipService = __decorate30([
|
|
5419
|
+
Injectable15()
|
|
4461
5420
|
], GeneratedOwnershipService);
|
|
4462
5421
|
function bodyGuard(resourceType, bodyField, optional = false) {
|
|
4463
|
-
var
|
|
5422
|
+
var _a26;
|
|
4464
5423
|
let BodyAccessGuard = class BodyAccessGuard {
|
|
4465
5424
|
static {
|
|
4466
5425
|
__name(this, "BodyAccessGuard");
|
|
@@ -4473,19 +5432,19 @@ function configureOwnership(config) {
|
|
|
4473
5432
|
return this.ownership.canAccess(user, resourceType, id);
|
|
4474
5433
|
}
|
|
4475
5434
|
};
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
5435
|
+
__decorate30([
|
|
5436
|
+
Inject15(GeneratedOwnershipService),
|
|
5437
|
+
__metadata30("design:type", GeneratedOwnershipService)
|
|
4479
5438
|
], BodyAccessGuard.prototype, "ownership", void 0);
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
5439
|
+
__decorate30([
|
|
5440
|
+
__param11(0, User4()),
|
|
5441
|
+
__param11(1, Body5()),
|
|
5442
|
+
__metadata30("design:type", Function),
|
|
5443
|
+
__metadata30("design:paramtypes", [Object, Object]),
|
|
5444
|
+
__metadata30("design:returntype", typeof (_a26 = typeof Promise !== "undefined" && Promise) === "function" ? _a26 : Object)
|
|
4486
5445
|
], BodyAccessGuard.prototype, "canActivate", null);
|
|
4487
|
-
BodyAccessGuard =
|
|
4488
|
-
|
|
5446
|
+
BodyAccessGuard = __decorate30([
|
|
5447
|
+
Injectable15()
|
|
4489
5448
|
], BodyAccessGuard);
|
|
4490
5449
|
return createGuard5(BodyAccessGuard);
|
|
4491
5450
|
}
|
|
@@ -4599,19 +5558,19 @@ __name(Policy, "Policy");
|
|
|
4599
5558
|
|
|
4600
5559
|
// src/ownership/OwnedDecorator.ts
|
|
4601
5560
|
import "reflect-metadata";
|
|
4602
|
-
import { sql as sql5, and as
|
|
4603
|
-
import { Injectable as
|
|
5561
|
+
import { sql as sql5, and as and5 } from "drizzle-orm";
|
|
5562
|
+
import { Injectable as Injectable16, Inject as Inject16, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
|
|
4604
5563
|
import { USER as USER2 } from "najm-guard";
|
|
4605
|
-
var
|
|
5564
|
+
var __decorate31 = function(decorators, target, key, desc) {
|
|
4606
5565
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4607
5566
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4608
5567
|
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;
|
|
4609
5568
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
4610
5569
|
};
|
|
4611
|
-
var
|
|
5570
|
+
var __metadata31 = function(k, v) {
|
|
4612
5571
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4613
5572
|
};
|
|
4614
|
-
var
|
|
5573
|
+
var _a19;
|
|
4615
5574
|
var OWNED_META = Symbol.for("najm:owned");
|
|
4616
5575
|
var ScopeContext = class ScopeContext2 {
|
|
4617
5576
|
static {
|
|
@@ -4643,18 +5602,18 @@ var ScopeContext = class ScopeContext2 {
|
|
|
4643
5602
|
}
|
|
4644
5603
|
}
|
|
4645
5604
|
};
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
5605
|
+
__decorate31([
|
|
5606
|
+
DI3(),
|
|
5607
|
+
__metadata31("design:type", typeof (_a19 = typeof Container2 !== "undefined" && Container2) === "function" ? _a19 : Object)
|
|
4649
5608
|
], ScopeContext.prototype, "container", void 0);
|
|
4650
|
-
ScopeContext =
|
|
4651
|
-
|
|
5609
|
+
ScopeContext = __decorate31([
|
|
5610
|
+
Injectable16()
|
|
4652
5611
|
], ScopeContext);
|
|
4653
5612
|
function Owned(token) {
|
|
4654
5613
|
return function(target) {
|
|
4655
5614
|
Reflect.defineMetadata(OWNED_META, token, target);
|
|
4656
5615
|
const proto = target.prototype;
|
|
4657
|
-
|
|
5616
|
+
Inject16(ScopeContext)(proto, "_scopeCtx");
|
|
4658
5617
|
function getUser(self) {
|
|
4659
5618
|
return self._scopeCtx?.getUser() ?? null;
|
|
4660
5619
|
}
|
|
@@ -4669,7 +5628,7 @@ function Owned(token) {
|
|
|
4669
5628
|
return null;
|
|
4670
5629
|
if (filtered.length === 1)
|
|
4671
5630
|
return filtered[0];
|
|
4672
|
-
return
|
|
5631
|
+
return and5(...filtered);
|
|
4673
5632
|
}
|
|
4674
5633
|
__name(combineConditions, "combineConditions");
|
|
4675
5634
|
function applyQueryOptions(query, opts = {}, whereCondition) {
|
|
@@ -4762,7 +5721,15 @@ var en_default = {
|
|
|
4762
5721
|
oauthProviderAccountLinked: "This Google account is already linked.",
|
|
4763
5722
|
oauthSignupDisabled: "Registration with Google is disabled.",
|
|
4764
5723
|
oauthHostedDomainDenied: "This Google Workspace domain is not allowed.",
|
|
4765
|
-
oauthLinkSessionExpired: "Your session changed before Google could be linked. Please try again."
|
|
5724
|
+
oauthLinkSessionExpired: "Your session changed before Google could be linked. Please try again.",
|
|
5725
|
+
oauthCredentialSetupRequired: "Set a new password before signing in with Google.",
|
|
5726
|
+
credentialSetupRequired: "Set a new password before continuing.",
|
|
5727
|
+
credentialSetupSessionRequired: "Credential setup session is required.",
|
|
5728
|
+
credentialSetupSessionInvalid: "Credential setup session is invalid or expired.",
|
|
5729
|
+
credentialSetupAlreadyCompleted: "The password was already replaced. Please sign in again.",
|
|
5730
|
+
credentialSetupPasswordRejected: "Choose a different password.",
|
|
5731
|
+
credentialSetupTemporaryShape: "Choose a password that is not your temporary credential.",
|
|
5732
|
+
credentialSetupSamePassword: "Choose a password different from your current one."
|
|
4766
5733
|
},
|
|
4767
5734
|
success: {
|
|
4768
5735
|
login: "Login successful",
|
|
@@ -4775,7 +5742,10 @@ var en_default = {
|
|
|
4775
5742
|
tokenRefreshed: "Token refreshed successfully",
|
|
4776
5743
|
sessionRecovered: "Session recovered successfully",
|
|
4777
5744
|
oauthLogin: "Google sign-in successful",
|
|
4778
|
-
oauthLinked: "Google account linked successfully"
|
|
5745
|
+
oauthLinked: "Google account linked successfully",
|
|
5746
|
+
credentialSetupPending: "Password setup is required",
|
|
5747
|
+
credentialSetupPasswordReplaced: "Password set successfully",
|
|
5748
|
+
credentialSetupCancelled: "Password setup cancelled"
|
|
4779
5749
|
},
|
|
4780
5750
|
emails: {
|
|
4781
5751
|
passwordReset: {
|
|
@@ -4791,6 +5761,7 @@ var en_default = {
|
|
|
4791
5761
|
notFound: "User not found",
|
|
4792
5762
|
idExists: "User ID already exists",
|
|
4793
5763
|
emailRequired: "Email is required",
|
|
5764
|
+
phoneExists: "Phone number already registered",
|
|
4794
5765
|
passwordRequired: "Password is required",
|
|
4795
5766
|
invalidEmail: "Invalid email format",
|
|
4796
5767
|
weakPassword: "Password is too weak",
|
|
@@ -4852,7 +5823,7 @@ __name(getAuthLocale, "getAuthLocale");
|
|
|
4852
5823
|
var AUTH_SUPPORTED_LANGUAGES = Object.keys(AUTH_LOCALES);
|
|
4853
5824
|
|
|
4854
5825
|
// src/oauth/google/GoogleOAuthProvider.ts
|
|
4855
|
-
import { Inject as
|
|
5826
|
+
import { Inject as Inject18, Injectable as Injectable18 } from "najm-core";
|
|
4856
5827
|
|
|
4857
5828
|
// src/oauth/types.ts
|
|
4858
5829
|
var OAuthFlowError = class extends Error {
|
|
@@ -4870,15 +5841,15 @@ var OAuthFlowError = class extends Error {
|
|
|
4870
5841
|
};
|
|
4871
5842
|
|
|
4872
5843
|
// src/oauth/google/GoogleTokenVerifier.ts
|
|
4873
|
-
import { Inject as
|
|
5844
|
+
import { Inject as Inject17, Injectable as Injectable17 } from "najm-core";
|
|
4874
5845
|
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
4875
|
-
var
|
|
5846
|
+
var __decorate32 = function(decorators, target, key, desc) {
|
|
4876
5847
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4877
5848
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4878
5849
|
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;
|
|
4879
5850
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
4880
5851
|
};
|
|
4881
|
-
var
|
|
5852
|
+
var __metadata32 = function(k, v) {
|
|
4882
5853
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4883
5854
|
};
|
|
4884
5855
|
var GOOGLE_JWKS = createRemoteJWKSet(new URL("https://www.googleapis.com/oauth2/v3/certs"));
|
|
@@ -4930,25 +5901,25 @@ var GoogleTokenVerifier = class GoogleTokenVerifier2 {
|
|
|
4930
5901
|
return google;
|
|
4931
5902
|
}
|
|
4932
5903
|
};
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
5904
|
+
__decorate32([
|
|
5905
|
+
Inject17(AUTH_CONFIG),
|
|
5906
|
+
__metadata32("design:type", Object)
|
|
4936
5907
|
], GoogleTokenVerifier.prototype, "config", void 0);
|
|
4937
|
-
GoogleTokenVerifier =
|
|
4938
|
-
|
|
5908
|
+
GoogleTokenVerifier = __decorate32([
|
|
5909
|
+
Injectable17()
|
|
4939
5910
|
], GoogleTokenVerifier);
|
|
4940
5911
|
|
|
4941
5912
|
// src/oauth/google/GoogleOAuthProvider.ts
|
|
4942
|
-
var
|
|
5913
|
+
var __decorate33 = function(decorators, target, key, desc) {
|
|
4943
5914
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4944
5915
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4945
5916
|
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;
|
|
4946
5917
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
4947
5918
|
};
|
|
4948
|
-
var
|
|
5919
|
+
var __metadata33 = function(k, v) {
|
|
4949
5920
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4950
5921
|
};
|
|
4951
|
-
var
|
|
5922
|
+
var _a20;
|
|
4952
5923
|
var AUTHORIZATION_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
4953
5924
|
var TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token";
|
|
4954
5925
|
var GoogleOAuthProvider = class GoogleOAuthProvider2 {
|
|
@@ -5015,27 +5986,27 @@ var GoogleOAuthProvider = class GoogleOAuthProvider2 {
|
|
|
5015
5986
|
throw new OAuthFlowError("oauth_provider_disabled", 404);
|
|
5016
5987
|
return google;
|
|
5017
5988
|
}
|
|
5018
|
-
};
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5989
|
+
};
|
|
5990
|
+
__decorate33([
|
|
5991
|
+
Inject18(AUTH_CONFIG),
|
|
5992
|
+
__metadata33("design:type", Object)
|
|
5022
5993
|
], GoogleOAuthProvider.prototype, "config", void 0);
|
|
5023
|
-
GoogleOAuthProvider =
|
|
5024
|
-
|
|
5025
|
-
|
|
5994
|
+
GoogleOAuthProvider = __decorate33([
|
|
5995
|
+
Injectable18(),
|
|
5996
|
+
__metadata33("design:paramtypes", [typeof (_a20 = typeof GoogleTokenVerifier !== "undefined" && GoogleTokenVerifier) === "function" ? _a20 : Object])
|
|
5026
5997
|
], GoogleOAuthProvider);
|
|
5027
5998
|
|
|
5028
5999
|
// src/oauth/OAuthAccountRepository.ts
|
|
5029
|
-
import { and as
|
|
5030
|
-
import { Inject as
|
|
5031
|
-
import { DB as
|
|
5032
|
-
var
|
|
6000
|
+
import { and as and6, eq as eq9 } from "drizzle-orm";
|
|
6001
|
+
import { Inject as Inject19, Repository as Repository7 } from "najm-core";
|
|
6002
|
+
import { DB as DB7 } from "najm-database";
|
|
6003
|
+
var __decorate34 = function(decorators, target, key, desc) {
|
|
5033
6004
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5034
6005
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5035
6006
|
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;
|
|
5036
6007
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5037
6008
|
};
|
|
5038
|
-
var
|
|
6009
|
+
var __metadata34 = function(k, v) {
|
|
5039
6010
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5040
6011
|
};
|
|
5041
6012
|
var OAuthAccountRepository = class OAuthAccountRepository2 {
|
|
@@ -5051,11 +6022,11 @@ var OAuthAccountRepository = class OAuthAccountRepository2 {
|
|
|
5051
6022
|
return this.schema.oauthAccounts;
|
|
5052
6023
|
}
|
|
5053
6024
|
async getByProviderAccount(provider, providerAccountId) {
|
|
5054
|
-
const [account] = await this.db.select().from(this.accounts).where(
|
|
6025
|
+
const [account] = await this.db.select().from(this.accounts).where(and6(eq9(this.accounts.provider, provider), eq9(this.accounts.providerAccountId, providerAccountId))).limit(1);
|
|
5055
6026
|
return account;
|
|
5056
6027
|
}
|
|
5057
6028
|
async getByUserProvider(userId, provider) {
|
|
5058
|
-
const [account] = await this.db.select().from(this.accounts).where(
|
|
6029
|
+
const [account] = await this.db.select().from(this.accounts).where(and6(eq9(this.accounts.userId, userId), eq9(this.accounts.provider, provider))).limit(1);
|
|
5059
6030
|
return account;
|
|
5060
6031
|
}
|
|
5061
6032
|
async create(data) {
|
|
@@ -5063,35 +6034,35 @@ var OAuthAccountRepository = class OAuthAccountRepository2 {
|
|
|
5063
6034
|
return account;
|
|
5064
6035
|
}
|
|
5065
6036
|
};
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
6037
|
+
__decorate34([
|
|
6038
|
+
DB7(),
|
|
6039
|
+
__metadata34("design:type", Object)
|
|
5069
6040
|
], OAuthAccountRepository.prototype, "db", void 0);
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
6041
|
+
__decorate34([
|
|
6042
|
+
Inject19(AUTH_SCHEMA),
|
|
6043
|
+
__metadata34("design:type", Object)
|
|
5073
6044
|
], OAuthAccountRepository.prototype, "schema", void 0);
|
|
5074
|
-
OAuthAccountRepository =
|
|
5075
|
-
|
|
6045
|
+
OAuthAccountRepository = __decorate34([
|
|
6046
|
+
Repository7()
|
|
5076
6047
|
], OAuthAccountRepository);
|
|
5077
6048
|
|
|
5078
6049
|
// src/oauth/OAuthAccountService.ts
|
|
5079
|
-
import { randomBytes as
|
|
5080
|
-
import { Inject as
|
|
5081
|
-
import { Transaction as
|
|
5082
|
-
var
|
|
6050
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
6051
|
+
import { Inject as Inject20, Injectable as Injectable19 } from "najm-core";
|
|
6052
|
+
import { Transaction as Transaction5 } from "najm-database";
|
|
6053
|
+
var __decorate35 = function(decorators, target, key, desc) {
|
|
5083
6054
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5084
6055
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5085
6056
|
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;
|
|
5086
6057
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5087
6058
|
};
|
|
5088
|
-
var
|
|
6059
|
+
var __metadata35 = function(k, v) {
|
|
5089
6060
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5090
6061
|
};
|
|
5091
|
-
var
|
|
5092
|
-
var
|
|
5093
|
-
var
|
|
5094
|
-
var
|
|
6062
|
+
var _a21;
|
|
6063
|
+
var _b12;
|
|
6064
|
+
var _c9;
|
|
6065
|
+
var _d7;
|
|
5095
6066
|
var OAuthAccountService = class OAuthAccountService2 {
|
|
5096
6067
|
static {
|
|
5097
6068
|
__name(this, "OAuthAccountService");
|
|
@@ -5118,7 +6089,7 @@ var OAuthAccountService = class OAuthAccountService2 {
|
|
|
5118
6089
|
if (!this.googleConfig().allowSignup) {
|
|
5119
6090
|
throw new OAuthFlowError("oauth_signup_disabled", 403);
|
|
5120
6091
|
}
|
|
5121
|
-
const password = `${
|
|
6092
|
+
const password = `${randomBytes3(32).toString("base64url")}Aa1`;
|
|
5122
6093
|
const user = await this.users.create({
|
|
5123
6094
|
name: identity.name,
|
|
5124
6095
|
email: identity.email,
|
|
@@ -5167,50 +6138,50 @@ var OAuthAccountService = class OAuthAccountService2 {
|
|
|
5167
6138
|
return google;
|
|
5168
6139
|
}
|
|
5169
6140
|
};
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
6141
|
+
__decorate35([
|
|
6142
|
+
Inject20(AUTH_CONFIG),
|
|
6143
|
+
__metadata35("design:type", Object)
|
|
5173
6144
|
], OAuthAccountService.prototype, "config", void 0);
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
6145
|
+
__decorate35([
|
|
6146
|
+
Transaction5(),
|
|
6147
|
+
__metadata35("design:type", Function),
|
|
6148
|
+
__metadata35("design:paramtypes", [Object]),
|
|
6149
|
+
__metadata35("design:returntype", typeof (_c9 = typeof Promise !== "undefined" && Promise) === "function" ? _c9 : Object)
|
|
5179
6150
|
], OAuthAccountService.prototype, "resolveForLogin", null);
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
6151
|
+
__decorate35([
|
|
6152
|
+
Transaction5(),
|
|
6153
|
+
__metadata35("design:type", Function),
|
|
6154
|
+
__metadata35("design:paramtypes", [String, Object]),
|
|
6155
|
+
__metadata35("design:returntype", typeof (_d7 = typeof Promise !== "undefined" && Promise) === "function" ? _d7 : Object)
|
|
5185
6156
|
], OAuthAccountService.prototype, "linkUser", null);
|
|
5186
|
-
OAuthAccountService =
|
|
5187
|
-
|
|
5188
|
-
|
|
6157
|
+
OAuthAccountService = __decorate35([
|
|
6158
|
+
Injectable19(),
|
|
6159
|
+
__metadata35("design:paramtypes", [typeof (_a21 = typeof OAuthAccountRepository !== "undefined" && OAuthAccountRepository) === "function" ? _a21 : Object, typeof (_b12 = typeof UserService !== "undefined" && UserService) === "function" ? _b12 : Object])
|
|
5189
6160
|
], OAuthAccountService);
|
|
5190
6161
|
|
|
5191
6162
|
// src/oauth/OAuthController.ts
|
|
5192
|
-
import { createHash as
|
|
6163
|
+
import { createHash as createHash5 } from "crypto";
|
|
5193
6164
|
import { Controller as Controller5, Ctx as Ctx2, Get as Get5, Post as Post5, Query as Query2, User as User5 } from "najm-core";
|
|
5194
6165
|
import { RateLimit as RateLimit2 } from "najm-rate";
|
|
5195
6166
|
|
|
5196
6167
|
// src/oauth/OAuthService.ts
|
|
5197
|
-
import { Inject as
|
|
6168
|
+
import { Inject as Inject21, Injectable as Injectable21, Log as Log2 } from "najm-core";
|
|
5198
6169
|
|
|
5199
6170
|
// src/oauth/OAuthStateService.ts
|
|
5200
|
-
import { createHash as
|
|
5201
|
-
import { Injectable as
|
|
5202
|
-
import { CookieService as
|
|
5203
|
-
var
|
|
6171
|
+
import { createHash as createHash4, randomBytes as randomBytes4, timingSafeEqual } from "crypto";
|
|
6172
|
+
import { Injectable as Injectable20 } from "najm-core";
|
|
6173
|
+
import { CookieService as CookieService3 } from "najm-cookies";
|
|
6174
|
+
var __decorate36 = function(decorators, target, key, desc) {
|
|
5204
6175
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5205
6176
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5206
6177
|
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;
|
|
5207
6178
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5208
6179
|
};
|
|
5209
|
-
var
|
|
6180
|
+
var __metadata36 = function(k, v) {
|
|
5210
6181
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5211
6182
|
};
|
|
5212
|
-
var
|
|
5213
|
-
var
|
|
6183
|
+
var _a22;
|
|
6184
|
+
var _b13;
|
|
5214
6185
|
var ATTEMPT_TTL_MS = 10 * 60 * 1e3;
|
|
5215
6186
|
var COOKIE_PREFIX = "najm.oauth.google.";
|
|
5216
6187
|
var OAuthStateService = class OAuthStateService2 {
|
|
@@ -5224,13 +6195,13 @@ var OAuthStateService = class OAuthStateService2 {
|
|
|
5224
6195
|
this.encryption = encryption;
|
|
5225
6196
|
}
|
|
5226
6197
|
create(input) {
|
|
5227
|
-
const state =
|
|
5228
|
-
const codeVerifier =
|
|
6198
|
+
const state = randomBytes4(32).toString("base64url");
|
|
6199
|
+
const codeVerifier = randomBytes4(48).toString("base64url");
|
|
5229
6200
|
const attempt = {
|
|
5230
6201
|
provider: "google",
|
|
5231
6202
|
intent: input.intent,
|
|
5232
6203
|
state,
|
|
5233
|
-
nonce:
|
|
6204
|
+
nonce: randomBytes4(32).toString("base64url"),
|
|
5234
6205
|
codeVerifier,
|
|
5235
6206
|
returnTo: this.validateReturnTo(input.returnTo),
|
|
5236
6207
|
userId: input.userId,
|
|
@@ -5245,7 +6216,7 @@ var OAuthStateService = class OAuthStateService2 {
|
|
|
5245
6216
|
});
|
|
5246
6217
|
return {
|
|
5247
6218
|
attempt,
|
|
5248
|
-
codeChallenge:
|
|
6219
|
+
codeChallenge: createHash4("sha256").update(codeVerifier).digest("base64url")
|
|
5249
6220
|
};
|
|
5250
6221
|
}
|
|
5251
6222
|
consume(state) {
|
|
@@ -5299,27 +6270,28 @@ var OAuthStateService = class OAuthStateService2 {
|
|
|
5299
6270
|
return /^[A-Za-z0-9_-]{40,128}$/.test(state);
|
|
5300
6271
|
}
|
|
5301
6272
|
};
|
|
5302
|
-
OAuthStateService =
|
|
5303
|
-
|
|
5304
|
-
|
|
6273
|
+
OAuthStateService = __decorate36([
|
|
6274
|
+
Injectable20(),
|
|
6275
|
+
__metadata36("design:paramtypes", [typeof (_a22 = typeof CookieService3 !== "undefined" && CookieService3) === "function" ? _a22 : Object, typeof (_b13 = typeof EncryptionService !== "undefined" && EncryptionService) === "function" ? _b13 : Object])
|
|
5305
6276
|
], OAuthStateService);
|
|
5306
6277
|
|
|
5307
6278
|
// src/oauth/OAuthService.ts
|
|
5308
|
-
var
|
|
6279
|
+
var __decorate37 = function(decorators, target, key, desc) {
|
|
5309
6280
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5310
6281
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5311
6282
|
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;
|
|
5312
6283
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5313
6284
|
};
|
|
5314
|
-
var
|
|
6285
|
+
var __metadata37 = function(k, v) {
|
|
5315
6286
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5316
6287
|
};
|
|
5317
|
-
var
|
|
5318
|
-
var
|
|
5319
|
-
var
|
|
5320
|
-
var
|
|
5321
|
-
var
|
|
5322
|
-
var
|
|
6288
|
+
var _a23;
|
|
6289
|
+
var _b14;
|
|
6290
|
+
var _c10;
|
|
6291
|
+
var _d8;
|
|
6292
|
+
var _e5;
|
|
6293
|
+
var _f5;
|
|
6294
|
+
var _g4;
|
|
5323
6295
|
var OAuthService = class OAuthService2 {
|
|
5324
6296
|
static {
|
|
5325
6297
|
__name(this, "OAuthService");
|
|
@@ -5330,15 +6302,17 @@ var OAuthService = class OAuthService2 {
|
|
|
5330
6302
|
sessions;
|
|
5331
6303
|
tokens;
|
|
5332
6304
|
users;
|
|
6305
|
+
requirements;
|
|
5333
6306
|
config;
|
|
5334
6307
|
logger;
|
|
5335
|
-
constructor(state, google, accounts, sessions, tokens, users) {
|
|
6308
|
+
constructor(state, google, accounts, sessions, tokens, users, requirements) {
|
|
5336
6309
|
this.state = state;
|
|
5337
6310
|
this.google = google;
|
|
5338
6311
|
this.accounts = accounts;
|
|
5339
6312
|
this.sessions = sessions;
|
|
5340
6313
|
this.tokens = tokens;
|
|
5341
6314
|
this.users = users;
|
|
6315
|
+
this.requirements = requirements;
|
|
5342
6316
|
}
|
|
5343
6317
|
startGoogleLogin(returnTo) {
|
|
5344
6318
|
this.googleConfig();
|
|
@@ -5382,6 +6356,9 @@ var OAuthService = class OAuthService2 {
|
|
|
5382
6356
|
await this.accounts.linkUser(attempt.userId, identity);
|
|
5383
6357
|
} else {
|
|
5384
6358
|
const user = await this.accounts.resolveForLogin(identity);
|
|
6359
|
+
if (await this.requirements?.isRequired(user.id, PASSWORD_SETUP_PURPOSE)) {
|
|
6360
|
+
throw new OAuthFlowError(CREDENTIAL_SETUP_CODES.OAUTH_BLOCKED, 403);
|
|
6361
|
+
}
|
|
5385
6362
|
await this.sessions.establish(user);
|
|
5386
6363
|
}
|
|
5387
6364
|
return this.frontendSuccessUrl(attempt.returnTo, attempt.intent);
|
|
@@ -5419,39 +6396,39 @@ var OAuthService = class OAuthService2 {
|
|
|
5419
6396
|
return google;
|
|
5420
6397
|
}
|
|
5421
6398
|
};
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
6399
|
+
__decorate37([
|
|
6400
|
+
Inject21(AUTH_CONFIG),
|
|
6401
|
+
__metadata37("design:type", Object)
|
|
5425
6402
|
], OAuthService.prototype, "config", void 0);
|
|
5426
|
-
|
|
6403
|
+
__decorate37([
|
|
5427
6404
|
Log2(),
|
|
5428
|
-
|
|
6405
|
+
__metadata37("design:type", Object)
|
|
5429
6406
|
], OAuthService.prototype, "logger", void 0);
|
|
5430
|
-
OAuthService =
|
|
5431
|
-
|
|
5432
|
-
|
|
6407
|
+
OAuthService = __decorate37([
|
|
6408
|
+
Injectable21(),
|
|
6409
|
+
__metadata37("design:paramtypes", [typeof (_a23 = typeof OAuthStateService !== "undefined" && OAuthStateService) === "function" ? _a23 : Object, typeof (_b14 = typeof GoogleOAuthProvider !== "undefined" && GoogleOAuthProvider) === "function" ? _b14 : Object, typeof (_c10 = typeof OAuthAccountService !== "undefined" && OAuthAccountService) === "function" ? _c10 : Object, typeof (_d8 = typeof AuthSessionService !== "undefined" && AuthSessionService) === "function" ? _d8 : Object, typeof (_e5 = typeof TokenService !== "undefined" && TokenService) === "function" ? _e5 : Object, typeof (_f5 = typeof UserService !== "undefined" && UserService) === "function" ? _f5 : Object, typeof (_g4 = typeof CredentialSetupRequirementService !== "undefined" && CredentialSetupRequirementService) === "function" ? _g4 : Object])
|
|
5433
6410
|
], OAuthService);
|
|
5434
6411
|
|
|
5435
6412
|
// src/oauth/OAuthController.ts
|
|
5436
|
-
var
|
|
6413
|
+
var __decorate38 = function(decorators, target, key, desc) {
|
|
5437
6414
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5438
6415
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5439
6416
|
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;
|
|
5440
6417
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5441
6418
|
};
|
|
5442
|
-
var
|
|
6419
|
+
var __metadata38 = function(k, v) {
|
|
5443
6420
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5444
6421
|
};
|
|
5445
|
-
var
|
|
6422
|
+
var __param12 = function(paramIndex, decorator) {
|
|
5446
6423
|
return function(target, key) {
|
|
5447
6424
|
decorator(target, key, paramIndex);
|
|
5448
6425
|
};
|
|
5449
6426
|
};
|
|
5450
|
-
var
|
|
6427
|
+
var _a24;
|
|
5451
6428
|
var callbackKey = /* @__PURE__ */ __name((ctx) => {
|
|
5452
6429
|
const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
|
|
5453
6430
|
const state = ctx.req.query("state") ?? "none";
|
|
5454
|
-
const fingerprint =
|
|
6431
|
+
const fingerprint = createHash5("sha256").update(state).digest("base64url").slice(0, 24);
|
|
5455
6432
|
return `${ip}:${fingerprint}`;
|
|
5456
6433
|
}, "callbackKey");
|
|
5457
6434
|
var OAuthController = class OAuthController2 {
|
|
@@ -5473,39 +6450,39 @@ var OAuthController = class OAuthController2 {
|
|
|
5473
6450
|
return this.oauth.startGoogleLink(userId, returnTo);
|
|
5474
6451
|
}
|
|
5475
6452
|
};
|
|
5476
|
-
|
|
6453
|
+
__decorate38([
|
|
5477
6454
|
Get5("/start"),
|
|
5478
6455
|
RateLimit2({ limit: 20, window: "15m", key: "ip" }),
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
6456
|
+
__param12(0, Ctx2()),
|
|
6457
|
+
__param12(1, Query2("returnTo")),
|
|
6458
|
+
__metadata38("design:type", Function),
|
|
6459
|
+
__metadata38("design:paramtypes", [Object, String]),
|
|
6460
|
+
__metadata38("design:returntype", void 0)
|
|
5484
6461
|
], OAuthController.prototype, "start", null);
|
|
5485
|
-
|
|
6462
|
+
__decorate38([
|
|
5486
6463
|
Get5("/callback"),
|
|
5487
6464
|
RateLimit2({ limit: 20, window: "15m", key: callbackKey }),
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
6465
|
+
__param12(0, Ctx2()),
|
|
6466
|
+
__param12(1, Query2("code")),
|
|
6467
|
+
__param12(2, Query2("state")),
|
|
6468
|
+
__param12(3, Query2("error")),
|
|
6469
|
+
__metadata38("design:type", Function),
|
|
6470
|
+
__metadata38("design:paramtypes", [Object, String, String, String]),
|
|
6471
|
+
__metadata38("design:returntype", Promise)
|
|
5495
6472
|
], OAuthController.prototype, "callback", null);
|
|
5496
|
-
|
|
6473
|
+
__decorate38([
|
|
5497
6474
|
Post5("/link"),
|
|
5498
6475
|
isAuth(),
|
|
5499
6476
|
RateLimit2({ limit: 10, window: "15m", key: "user" }),
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
6477
|
+
__param12(0, User5("id")),
|
|
6478
|
+
__param12(1, Query2("returnTo")),
|
|
6479
|
+
__metadata38("design:type", Function),
|
|
6480
|
+
__metadata38("design:paramtypes", [String, String]),
|
|
6481
|
+
__metadata38("design:returntype", void 0)
|
|
5505
6482
|
], OAuthController.prototype, "link", null);
|
|
5506
|
-
OAuthController =
|
|
6483
|
+
OAuthController = __decorate38([
|
|
5507
6484
|
Controller5("/auth/oauth/google"),
|
|
5508
|
-
|
|
6485
|
+
__metadata38("design:paramtypes", [typeof (_a24 = typeof OAuthService !== "undefined" && OAuthService) === "function" ? _a24 : Object])
|
|
5509
6486
|
], OAuthController);
|
|
5510
6487
|
|
|
5511
6488
|
// src/oauth/index.ts
|
|
@@ -5519,250 +6496,91 @@ var OAUTH_MODULE = [
|
|
|
5519
6496
|
OAuthController
|
|
5520
6497
|
];
|
|
5521
6498
|
|
|
5522
|
-
// src/credentialSetup/
|
|
5523
|
-
import {
|
|
5524
|
-
import {
|
|
5525
|
-
import {
|
|
5526
|
-
var __decorate33 = function(decorators, target, key, desc) {
|
|
5527
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5528
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5529
|
-
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;
|
|
5530
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5531
|
-
};
|
|
5532
|
-
var __metadata33 = function(k, v) {
|
|
5533
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5534
|
-
};
|
|
5535
|
-
var CredentialSetupRepository = class CredentialSetupRepository2 {
|
|
5536
|
-
static {
|
|
5537
|
-
__name(this, "CredentialSetupRepository");
|
|
5538
|
-
}
|
|
5539
|
-
db;
|
|
5540
|
-
schema;
|
|
5541
|
-
get sessions() {
|
|
5542
|
-
const sessions = this.schema.credentialSetupSessions;
|
|
5543
|
-
if (!sessions) {
|
|
5544
|
-
Err11.invalidOperation("auth.schema.credentialSetupSessions is required to use CredentialSetupService");
|
|
5545
|
-
}
|
|
5546
|
-
return sessions;
|
|
5547
|
-
}
|
|
5548
|
-
async replaceActive(data) {
|
|
5549
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5550
|
-
await this.db.update(this.sessions).set({ revokedAt: now, updatedAt: now }).where(and5(eq8(this.sessions.userId, data.userId), eq8(this.sessions.purpose, data.purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt)));
|
|
5551
|
-
const [session] = await this.db.insert(this.sessions).values(data).returning({
|
|
5552
|
-
userId: this.sessions.userId,
|
|
5553
|
-
purpose: this.sessions.purpose,
|
|
5554
|
-
expiresAt: this.sessions.expiresAt
|
|
5555
|
-
});
|
|
5556
|
-
return session;
|
|
5557
|
-
}
|
|
5558
|
-
async findActive(tokenHash, purpose) {
|
|
5559
|
-
const [session] = await this.db.select({
|
|
5560
|
-
userId: this.sessions.userId,
|
|
5561
|
-
purpose: this.sessions.purpose,
|
|
5562
|
-
expiresAt: this.sessions.expiresAt
|
|
5563
|
-
}).from(this.sessions).where(and5(eq8(this.sessions.tokenHash, tokenHash), eq8(this.sessions.purpose, purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt), gt(this.sessions.expiresAt, (/* @__PURE__ */ new Date()).toISOString()))).limit(1);
|
|
5564
|
-
return session;
|
|
5565
|
-
}
|
|
5566
|
-
async consume(tokenHash, purpose) {
|
|
5567
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5568
|
-
const [session] = await this.db.update(this.sessions).set({ consumedAt: now, updatedAt: now }).where(and5(eq8(this.sessions.tokenHash, tokenHash), eq8(this.sessions.purpose, purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt), gt(this.sessions.expiresAt, now))).returning({
|
|
5569
|
-
userId: this.sessions.userId,
|
|
5570
|
-
purpose: this.sessions.purpose,
|
|
5571
|
-
expiresAt: this.sessions.expiresAt
|
|
5572
|
-
});
|
|
5573
|
-
return session;
|
|
5574
|
-
}
|
|
5575
|
-
async revoke(tokenHash, purpose) {
|
|
5576
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5577
|
-
const [session] = await this.db.update(this.sessions).set({ revokedAt: now, updatedAt: now }).where(and5(eq8(this.sessions.tokenHash, tokenHash), eq8(this.sessions.purpose, purpose), isNull2(this.sessions.consumedAt), isNull2(this.sessions.revokedAt))).returning({ userId: this.sessions.userId });
|
|
5578
|
-
return session;
|
|
5579
|
-
}
|
|
5580
|
-
async deleteExpired() {
|
|
5581
|
-
return this.db.delete(this.sessions).where(lt2(this.sessions.expiresAt, (/* @__PURE__ */ new Date()).toISOString())).returning({ userId: this.sessions.userId });
|
|
5582
|
-
}
|
|
5583
|
-
};
|
|
5584
|
-
__decorate33([
|
|
5585
|
-
DB6(),
|
|
5586
|
-
__metadata33("design:type", Object)
|
|
5587
|
-
], CredentialSetupRepository.prototype, "db", void 0);
|
|
5588
|
-
__decorate33([
|
|
5589
|
-
Inject18(AUTH_SCHEMA),
|
|
5590
|
-
__metadata33("design:type", Object)
|
|
5591
|
-
], CredentialSetupRepository.prototype, "schema", void 0);
|
|
5592
|
-
CredentialSetupRepository = __decorate33([
|
|
5593
|
-
Repository6()
|
|
5594
|
-
], CredentialSetupRepository);
|
|
6499
|
+
// src/credentialSetup/CredentialSetupController.ts
|
|
6500
|
+
import { Body as Body6, Controller as Controller6, Get as Get6, Post as Post6, ResMsg as ResMsg5 } from "najm-core";
|
|
6501
|
+
import { RateLimit as RateLimit3 } from "najm-rate";
|
|
6502
|
+
import { Validate as Validate5 } from "najm-validation";
|
|
5595
6503
|
|
|
5596
|
-
// src/credentialSetup/
|
|
5597
|
-
import {
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
6504
|
+
// src/credentialSetup/CredentialSetupDto.ts
|
|
6505
|
+
import { z as z5 } from "zod";
|
|
6506
|
+
var defaultCredentialSetupPasswordSchema = z5.string().min(8, "Password must be at least 8 characters").refine((v) => new TextEncoder().encode(v).length <= 72, "Password must be at most 72 bytes").regex(/[a-zA-Z]/, "Password must contain at least one letter").regex(/\d/, "Password must contain at least one number");
|
|
6507
|
+
var credentialSetupChangeDto = z5.object({
|
|
6508
|
+
newPassword: z5.string().min(1, "A new password is required").max(256)
|
|
6509
|
+
});
|
|
6510
|
+
|
|
6511
|
+
// src/credentialSetup/CredentialSetupController.ts
|
|
6512
|
+
var __decorate39 = function(decorators, target, key, desc) {
|
|
5602
6513
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5603
6514
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5604
6515
|
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;
|
|
5605
6516
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
5606
6517
|
};
|
|
5607
|
-
var
|
|
6518
|
+
var __metadata39 = function(k, v) {
|
|
5608
6519
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5609
6520
|
};
|
|
5610
|
-
var
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
var
|
|
5616
|
-
var
|
|
5617
|
-
var DEFAULT_COOKIE_NAME = "najm.credential-setup";
|
|
5618
|
-
var DEFAULT_TTL_MS = 10 * 60 * 1e3;
|
|
5619
|
-
var MAX_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
5620
|
-
var PURPOSE_PATTERN = /^[a-z0-9](?:[a-z0-9:_-]{0,62}[a-z0-9])?$/;
|
|
5621
|
-
var COOKIE_NAME_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
5622
|
-
var CredentialSetupService = class CredentialSetupService2 {
|
|
6521
|
+
var __param13 = function(paramIndex, decorator) {
|
|
6522
|
+
return function(target, key) {
|
|
6523
|
+
decorator(target, key, paramIndex);
|
|
6524
|
+
};
|
|
6525
|
+
};
|
|
6526
|
+
var _a25;
|
|
6527
|
+
var CredentialSetupController = class CredentialSetupController2 {
|
|
5623
6528
|
static {
|
|
5624
|
-
__name(this, "
|
|
5625
|
-
}
|
|
5626
|
-
repository;
|
|
5627
|
-
tokens;
|
|
5628
|
-
authCookies;
|
|
5629
|
-
cookies;
|
|
5630
|
-
constructor(repository, tokens, authCookies, cookies2) {
|
|
5631
|
-
this.repository = repository;
|
|
5632
|
-
this.tokens = tokens;
|
|
5633
|
-
this.authCookies = authCookies;
|
|
5634
|
-
this.cookies = cookies2;
|
|
5635
|
-
}
|
|
5636
|
-
/**
|
|
5637
|
-
* Revoke normal auth sessions and issue a single-purpose, short-lived,
|
|
5638
|
-
* browser-session cookie. No access or refresh token is minted.
|
|
5639
|
-
*/
|
|
5640
|
-
async begin(userId, options) {
|
|
5641
|
-
const resolved = this.resolveOptions(options);
|
|
5642
|
-
const token = randomBytes4(32).toString("base64url");
|
|
5643
|
-
const expiresAt = new Date(Date.now() + resolved.ttlMs).toISOString();
|
|
5644
|
-
await this.repository.deleteExpired();
|
|
5645
|
-
await this.repository.replaceActive({
|
|
5646
|
-
userId,
|
|
5647
|
-
purpose: resolved.purpose,
|
|
5648
|
-
tokenHash: this.hashToken(token),
|
|
5649
|
-
expiresAt
|
|
5650
|
-
});
|
|
5651
|
-
await this.tokens.invalidateUserAccessTokens(userId);
|
|
5652
|
-
await this.tokens.revokeAllForUser(userId);
|
|
5653
|
-
this.authCookies.clearRefreshToken();
|
|
5654
|
-
this.authCookies.clearSessionCookie();
|
|
5655
|
-
this.setCookie(token, resolved);
|
|
5656
|
-
return { purpose: resolved.purpose, expiresAt };
|
|
5657
|
-
}
|
|
5658
|
-
/** Validate and return the current active setup session without consuming it. */
|
|
5659
|
-
async require(options) {
|
|
5660
|
-
const resolved = this.resolveOptions(options);
|
|
5661
|
-
const token = this.cookies.get(resolved.cookieName);
|
|
5662
|
-
if (!token)
|
|
5663
|
-
Err12("Credential setup session is required", 401);
|
|
5664
|
-
const session = await this.repository.findActive(this.hashToken(token), resolved.purpose);
|
|
5665
|
-
if (!session) {
|
|
5666
|
-
this.clearCookie(resolved);
|
|
5667
|
-
Err12("Credential setup session is invalid or expired", 401);
|
|
5668
|
-
}
|
|
5669
|
-
return session;
|
|
5670
|
-
}
|
|
5671
|
-
/**
|
|
5672
|
-
* Atomically consume the setup session and execute the application-owned
|
|
5673
|
-
* credential mutation in the same database transaction. If the callback
|
|
5674
|
-
* fails, consumption rolls back and the browser may safely retry.
|
|
5675
|
-
*/
|
|
5676
|
-
async consume(options, complete) {
|
|
5677
|
-
const resolved = this.resolveOptions(options);
|
|
5678
|
-
const token = this.cookies.get(resolved.cookieName);
|
|
5679
|
-
if (!token)
|
|
5680
|
-
Err12("Credential setup session is required", 401);
|
|
5681
|
-
const session = await this.repository.consume(this.hashToken(token), resolved.purpose);
|
|
5682
|
-
if (!session) {
|
|
5683
|
-
this.clearCookie(resolved);
|
|
5684
|
-
Err12("Credential setup session is invalid or expired", 401);
|
|
5685
|
-
}
|
|
5686
|
-
const result = await complete(session);
|
|
5687
|
-
this.clearCookie(resolved);
|
|
5688
|
-
return result;
|
|
5689
|
-
}
|
|
5690
|
-
async cancel(options) {
|
|
5691
|
-
const resolved = this.resolveOptions(options);
|
|
5692
|
-
const token = this.cookies.get(resolved.cookieName);
|
|
5693
|
-
if (token) {
|
|
5694
|
-
await this.repository.revoke(this.hashToken(token), resolved.purpose);
|
|
5695
|
-
}
|
|
5696
|
-
this.clearCookie(resolved);
|
|
5697
|
-
return { cancelled: true };
|
|
5698
|
-
}
|
|
5699
|
-
async pruneExpired() {
|
|
5700
|
-
await this.repository.deleteExpired();
|
|
6529
|
+
__name(this, "CredentialSetupController");
|
|
5701
6530
|
}
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
5706
|
-
const cookiePath = options.cookiePath ?? "/";
|
|
5707
|
-
if (!purpose || !PURPOSE_PATTERN.test(purpose)) {
|
|
5708
|
-
Err12("Credential setup purpose must be 1-64 lowercase letters, numbers, colon, underscore, or hyphen", 500);
|
|
5709
|
-
}
|
|
5710
|
-
if (!COOKIE_NAME_PATTERN.test(cookieName) || cookieName.length > 128) {
|
|
5711
|
-
Err12("Credential setup cookie name is invalid", 500);
|
|
5712
|
-
}
|
|
5713
|
-
if (!Number.isInteger(ttlMs) || ttlMs < 1e3 || ttlMs > MAX_TTL_MS) {
|
|
5714
|
-
Err12("Credential setup ttlMs must be an integer between 1000 and 86400000", 500);
|
|
5715
|
-
}
|
|
5716
|
-
if (!cookiePath.startsWith("/") || cookiePath.includes(";") || cookiePath.includes("\\")) {
|
|
5717
|
-
Err12("Credential setup cookiePath must be a same-origin path", 500);
|
|
5718
|
-
}
|
|
5719
|
-
return { purpose, cookieName, ttlMs, cookiePath };
|
|
6531
|
+
passwords;
|
|
6532
|
+
constructor(passwords) {
|
|
6533
|
+
this.passwords = passwords;
|
|
5720
6534
|
}
|
|
5721
|
-
|
|
5722
|
-
return
|
|
6535
|
+
status() {
|
|
6536
|
+
return this.passwords.status();
|
|
5723
6537
|
}
|
|
5724
|
-
|
|
5725
|
-
this.
|
|
5726
|
-
httpOnly: true,
|
|
5727
|
-
path: options.cookiePath,
|
|
5728
|
-
sameSite: "Strict",
|
|
5729
|
-
secure: process.env.NODE_ENV === "production"
|
|
5730
|
-
});
|
|
6538
|
+
change(body) {
|
|
6539
|
+
return this.passwords.change(body.newPassword);
|
|
5731
6540
|
}
|
|
5732
|
-
|
|
5733
|
-
this.
|
|
5734
|
-
path: options.cookiePath,
|
|
5735
|
-
secure: process.env.NODE_ENV === "production"
|
|
5736
|
-
});
|
|
6541
|
+
cancel() {
|
|
6542
|
+
return this.passwords.cancel();
|
|
5737
6543
|
}
|
|
5738
6544
|
};
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
],
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
6545
|
+
__decorate39([
|
|
6546
|
+
Get6("/setup"),
|
|
6547
|
+
RateLimit3({ limit: 30, window: "15m", key: "ip" }),
|
|
6548
|
+
ResMsg5("auth.success.credentialSetupPending"),
|
|
6549
|
+
__metadata39("design:type", Function),
|
|
6550
|
+
__metadata39("design:paramtypes", []),
|
|
6551
|
+
__metadata39("design:returntype", void 0)
|
|
6552
|
+
], CredentialSetupController.prototype, "status", null);
|
|
6553
|
+
__decorate39([
|
|
6554
|
+
Post6("/change"),
|
|
6555
|
+
RateLimit3({ limit: 5, window: "15m", key: "ip" }),
|
|
6556
|
+
Validate5(credentialSetupChangeDto),
|
|
6557
|
+
ResMsg5("auth.success.credentialSetupPasswordReplaced"),
|
|
6558
|
+
__param13(0, Body6()),
|
|
6559
|
+
__metadata39("design:type", Function),
|
|
6560
|
+
__metadata39("design:paramtypes", [Object]),
|
|
6561
|
+
__metadata39("design:returntype", void 0)
|
|
6562
|
+
], CredentialSetupController.prototype, "change", null);
|
|
6563
|
+
__decorate39([
|
|
6564
|
+
Post6("/cancel"),
|
|
6565
|
+
RateLimit3({ limit: 10, window: "15m", key: "ip" }),
|
|
6566
|
+
ResMsg5("auth.success.credentialSetupCancelled"),
|
|
6567
|
+
__metadata39("design:type", Function),
|
|
6568
|
+
__metadata39("design:paramtypes", []),
|
|
6569
|
+
__metadata39("design:returntype", void 0)
|
|
6570
|
+
], CredentialSetupController.prototype, "cancel", null);
|
|
6571
|
+
CredentialSetupController = __decorate39([
|
|
6572
|
+
Controller6("/auth/credential-setup"),
|
|
6573
|
+
__metadata39("design:paramtypes", [typeof (_a25 = typeof PasswordSetupService !== "undefined" && PasswordSetupService) === "function" ? _a25 : Object])
|
|
6574
|
+
], CredentialSetupController);
|
|
5761
6575
|
|
|
5762
6576
|
// src/credentialSetup/index.ts
|
|
5763
6577
|
var CREDENTIAL_SETUP_MODULE = [
|
|
5764
6578
|
CredentialSetupRepository,
|
|
5765
|
-
|
|
6579
|
+
CredentialSetupRequirementRepository,
|
|
6580
|
+
CredentialSetupService,
|
|
6581
|
+
CredentialSetupRequirementService,
|
|
6582
|
+
PasswordSetupService,
|
|
6583
|
+
CredentialSetupController
|
|
5766
6584
|
];
|
|
5767
6585
|
|
|
5768
6586
|
// src/AuthPlugin.ts
|
|
@@ -5786,9 +6604,9 @@ var resolveGoogleConfig = /* @__PURE__ */ __name((config) => {
|
|
|
5786
6604
|
const clientId = google.clientId ?? process.env.GOOGLE_CLIENT_ID ?? "";
|
|
5787
6605
|
const clientSecret = google.clientSecret ?? process.env.GOOGLE_CLIENT_SECRET ?? "";
|
|
5788
6606
|
if (!clientId)
|
|
5789
|
-
throw
|
|
6607
|
+
throw Err15.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
|
|
5790
6608
|
if (!clientSecret)
|
|
5791
|
-
throw
|
|
6609
|
+
throw Err15.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
|
|
5792
6610
|
const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
|
|
5793
6611
|
const callbackUrl = google.callbackUrl ?? process.env.GOOGLE_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/google/callback`;
|
|
5794
6612
|
let callback;
|
|
@@ -5812,6 +6630,20 @@ var resolveGoogleConfig = /* @__PURE__ */ __name((config) => {
|
|
|
5812
6630
|
allowedHostedDomains: [...new Set((google.allowedHostedDomains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean))]
|
|
5813
6631
|
};
|
|
5814
6632
|
}, "resolveGoogleConfig");
|
|
6633
|
+
var resolveCredentialSetupConfig = /* @__PURE__ */ __name((config) => {
|
|
6634
|
+
const password = config?.credentialSetup?.password ?? {};
|
|
6635
|
+
const ttlMs = password.ttlMs ?? DEFAULT_CREDENTIAL_SETUP_TTL_MS;
|
|
6636
|
+
if (!Number.isInteger(ttlMs) || ttlMs < 1e3 || ttlMs > 24 * 60 * 60 * 1e3) {
|
|
6637
|
+
throw new Error("auth.credentialSetup.password.ttlMs must be an integer between 1000 and 86400000");
|
|
6638
|
+
}
|
|
6639
|
+
return {
|
|
6640
|
+
password: {
|
|
6641
|
+
ttlMs,
|
|
6642
|
+
cookieName: password.cookieName?.trim() || DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME,
|
|
6643
|
+
passwordSchema: password.passwordSchema ?? defaultCredentialSetupPasswordSchema
|
|
6644
|
+
}
|
|
6645
|
+
};
|
|
6646
|
+
}, "resolveCredentialSetupConfig");
|
|
5815
6647
|
var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
|
|
5816
6648
|
const bcryptRounds = config?.bcryptRounds ?? 10;
|
|
5817
6649
|
if (!Number.isInteger(bcryptRounds) || bcryptRounds < 4 || bcryptRounds > 31) {
|
|
@@ -5835,6 +6667,9 @@ var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
|
|
|
5835
6667
|
duration: config?.lockout?.duration ?? "15m"
|
|
5836
6668
|
},
|
|
5837
6669
|
bcryptRounds,
|
|
6670
|
+
identity: {
|
|
6671
|
+
resolve: createIdentityResolver(config?.identity)
|
|
6672
|
+
},
|
|
5838
6673
|
session: {
|
|
5839
6674
|
name: config?.session?.name ?? "najm.session",
|
|
5840
6675
|
maxAge: config?.session?.maxAge ?? 300,
|
|
@@ -5842,15 +6677,16 @@ var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
|
|
|
5842
6677
|
// CookieManager falls back to jwt.accessSecret when this is undefined.
|
|
5843
6678
|
secret: config?.session?.secret ?? process.env.NAJM_SESSION_SECRET
|
|
5844
6679
|
},
|
|
6680
|
+
credentialSetup: resolveCredentialSetupConfig(config),
|
|
5845
6681
|
oauth: {
|
|
5846
6682
|
google: resolveGoogleConfig(config)
|
|
5847
6683
|
}
|
|
5848
6684
|
};
|
|
5849
6685
|
if (!finalConfig.jwt.accessSecret) {
|
|
5850
|
-
throw
|
|
6686
|
+
throw Err15.configRequired("auth", "JWT_ACCESS_SECRET");
|
|
5851
6687
|
}
|
|
5852
6688
|
if (!finalConfig.jwt.refreshSecret) {
|
|
5853
|
-
throw
|
|
6689
|
+
throw Err15.configRequired("auth", "JWT_REFRESH_SECRET");
|
|
5854
6690
|
}
|
|
5855
6691
|
return finalConfig;
|
|
5856
6692
|
}, "resolveAuthConfig");
|
|
@@ -5859,6 +6695,12 @@ var selectAuthSchema = /* @__PURE__ */ __name((config) => {
|
|
|
5859
6695
|
if (config.oauth?.google && !config.schema.oauthAccounts) {
|
|
5860
6696
|
throw new Error("auth.schema.oauthAccounts is required when Google OAuth is enabled");
|
|
5861
6697
|
}
|
|
6698
|
+
if (!config.schema.credentialSetupSessions) {
|
|
6699
|
+
throw new Error("auth.schema.credentialSetupSessions is required \u2014 re-export it from najm-auth/pg or najm-auth/sqlite");
|
|
6700
|
+
}
|
|
6701
|
+
if (!config.schema.credentialSetupRequirements) {
|
|
6702
|
+
throw new Error("auth.schema.credentialSetupRequirements is required \u2014 re-export it from najm-auth/pg or najm-auth/sqlite");
|
|
6703
|
+
}
|
|
5862
6704
|
return config.schema;
|
|
5863
6705
|
}
|
|
5864
6706
|
const dialect = config?.dialect ?? "pg";
|
|
@@ -6017,6 +6859,7 @@ export {
|
|
|
6017
6859
|
AuthResolver,
|
|
6018
6860
|
AuthService,
|
|
6019
6861
|
AuthSessionService,
|
|
6862
|
+
CREDENTIAL_SETUP_CODES,
|
|
6020
6863
|
CREDENTIAL_SETUP_MODULE,
|
|
6021
6864
|
Can,
|
|
6022
6865
|
CanCreate,
|
|
@@ -6025,11 +6868,22 @@ export {
|
|
|
6025
6868
|
CanRead,
|
|
6026
6869
|
CanUpdate,
|
|
6027
6870
|
CookieManager,
|
|
6871
|
+
CredentialSetupController,
|
|
6028
6872
|
CredentialSetupRepository,
|
|
6873
|
+
CredentialSetupRequirementRepository,
|
|
6874
|
+
CredentialSetupRequirementService,
|
|
6029
6875
|
CredentialSetupService,
|
|
6876
|
+
DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME,
|
|
6877
|
+
DEFAULT_CREDENTIAL_SETUP_TTL_MS,
|
|
6878
|
+
DEFAULT_IDENTITY_PRESET,
|
|
6879
|
+
EXACT_TEMPORARY_CREDENTIAL_KIND,
|
|
6030
6880
|
EncryptionService,
|
|
6881
|
+
IDENTITY_PRESETS,
|
|
6882
|
+
MOROCCAN_CIN_TEMPORARY_CREDENTIAL_KIND,
|
|
6031
6883
|
Owned,
|
|
6032
6884
|
OwnershipToken,
|
|
6885
|
+
PASSWORD_SETUP_PURPOSE,
|
|
6886
|
+
PasswordSetupService,
|
|
6033
6887
|
PermissionController,
|
|
6034
6888
|
PermissionGuard,
|
|
6035
6889
|
PermissionRepository,
|
|
@@ -6068,13 +6922,19 @@ export {
|
|
|
6068
6922
|
changePasswordDto,
|
|
6069
6923
|
checkPermissionDto,
|
|
6070
6924
|
clean,
|
|
6925
|
+
compactPhone,
|
|
6071
6926
|
configureOwnership,
|
|
6072
6927
|
confirmResetPasswordDto,
|
|
6928
|
+
createIdentityResolver,
|
|
6073
6929
|
createPermissionDto,
|
|
6074
6930
|
createRoleDto,
|
|
6075
6931
|
createTokenDto,
|
|
6076
6932
|
createUserDto,
|
|
6933
|
+
credentialSetupChangeDto,
|
|
6934
|
+
credentialSetupError,
|
|
6935
|
+
credentialSetupRequirementsTable,
|
|
6077
6936
|
credentialSetupSessionsTable,
|
|
6937
|
+
defaultCredentialSetupPasswordSchema,
|
|
6078
6938
|
defineRoles,
|
|
6079
6939
|
emailParam,
|
|
6080
6940
|
formatDate,
|
|
@@ -6087,11 +6947,19 @@ export {
|
|
|
6087
6947
|
isEmailIdentifier,
|
|
6088
6948
|
isEmpty,
|
|
6089
6949
|
isFile,
|
|
6950
|
+
isMoroccanCin,
|
|
6090
6951
|
isPath,
|
|
6952
|
+
isTemporaryCredentialKind,
|
|
6091
6953
|
join2 as join,
|
|
6092
6954
|
languageParam,
|
|
6093
6955
|
loginDto,
|
|
6956
|
+
moroccanCinTemporaryCredential,
|
|
6957
|
+
moroccoIdentityPreset,
|
|
6094
6958
|
normalizeAuthIdentifier,
|
|
6959
|
+
normalizeMoroccanCin,
|
|
6960
|
+
normalizeMoroccanPhone,
|
|
6961
|
+
normalizeSetupPurpose,
|
|
6962
|
+
normalizeTunisianPhone,
|
|
6095
6963
|
oauthAccountsTable,
|
|
6096
6964
|
own,
|
|
6097
6965
|
parseSchema,
|
|
@@ -6101,16 +6969,19 @@ export {
|
|
|
6101
6969
|
refreshTokenDto,
|
|
6102
6970
|
registerDto,
|
|
6103
6971
|
resetPasswordDto,
|
|
6972
|
+
resolveTemporaryCredentialKind,
|
|
6104
6973
|
revokeTokenDto,
|
|
6105
6974
|
roleIdParam,
|
|
6106
6975
|
rolePermissionsTable,
|
|
6107
6976
|
rolesTable,
|
|
6108
6977
|
runAsUser,
|
|
6109
6978
|
seedAuthData,
|
|
6979
|
+
toTemporaryCredential,
|
|
6110
6980
|
tokenIdParam,
|
|
6111
6981
|
tokenStatusEnum,
|
|
6112
6982
|
tokenTypeEnum,
|
|
6113
6983
|
tokensTable,
|
|
6984
|
+
tunisiaIdentityPreset,
|
|
6114
6985
|
updatePermissionDto,
|
|
6115
6986
|
updateRoleDto,
|
|
6116
6987
|
updateTokenDto,
|