najm-auth 1.1.44 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -8
- package/dist/client/index.js +1 -1
- package/dist/index.d.ts +75 -9
- package/dist/index.js +435 -369
- package/package.json +10 -10
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 Err9, plugin } from "najm-core";
|
|
10
10
|
import { cache } from "najm-cache";
|
|
11
11
|
|
|
12
12
|
// src/auth.tokens.ts
|
|
@@ -290,6 +290,9 @@ var CookieManager = class CookieManager2 {
|
|
|
290
290
|
get cookieName() {
|
|
291
291
|
return this.config.refreshCookieName || "refreshToken";
|
|
292
292
|
}
|
|
293
|
+
get refreshCookiePath() {
|
|
294
|
+
return this.config.refreshCookiePath || "/";
|
|
295
|
+
}
|
|
293
296
|
get sessionCookieName() {
|
|
294
297
|
return this.config.session.name;
|
|
295
298
|
}
|
|
@@ -304,10 +307,10 @@ var CookieManager = class CookieManager2 {
|
|
|
304
307
|
// =========================================================================
|
|
305
308
|
setRefreshToken(refreshToken) {
|
|
306
309
|
const maxAge = timestring(this.config.jwt.refreshExpiresIn, "s");
|
|
307
|
-
this.cookieService.set(this.cookieName, refreshToken, { maxAge });
|
|
310
|
+
this.cookieService.set(this.cookieName, refreshToken, { maxAge, path: this.refreshCookiePath });
|
|
308
311
|
}
|
|
309
312
|
clearRefreshToken() {
|
|
310
|
-
this.cookieService.delete(this.cookieName);
|
|
313
|
+
this.cookieService.delete(this.cookieName, { path: this.refreshCookiePath });
|
|
311
314
|
}
|
|
312
315
|
getRefreshToken() {
|
|
313
316
|
return this.cookieService.get(this.cookieName);
|
|
@@ -373,14 +376,14 @@ CookieManager = __decorate2([
|
|
|
373
376
|
], CookieManager);
|
|
374
377
|
|
|
375
378
|
// src/auth/AuthController.ts
|
|
376
|
-
import { Controller
|
|
377
|
-
import { Get
|
|
378
|
-
import { Body
|
|
379
|
+
import { Controller } from "najm-core";
|
|
380
|
+
import { Get, Post, ResMsg } from "najm-core";
|
|
381
|
+
import { Body, User as User3, Headers } from "najm-core";
|
|
379
382
|
|
|
380
383
|
// src/auth/AuthService.ts
|
|
381
384
|
import { Injectable as Injectable7, Inject as Inject8 } from "najm-core";
|
|
382
|
-
import { Err as
|
|
383
|
-
import { I18n as
|
|
385
|
+
import { Err as Err7, Log } from "najm-core";
|
|
386
|
+
import { I18n as I18n6, I18nService as I18nService2 } from "najm-i18n";
|
|
384
387
|
import { EmailService, passwordResetTemplate, accountInviteTemplate } from "najm-email";
|
|
385
388
|
import { nanoid as nanoid5 } from "nanoid";
|
|
386
389
|
|
|
@@ -388,7 +391,7 @@ import { nanoid as nanoid5 } from "nanoid";
|
|
|
388
391
|
import { Injectable as Injectable5, Inject as Inject5 } from "najm-core";
|
|
389
392
|
import { Transaction } from "najm-database";
|
|
390
393
|
import { I18nService } from "najm-i18n";
|
|
391
|
-
import { I18n as
|
|
394
|
+
import { I18n as I18n4 } from "najm-i18n";
|
|
392
395
|
|
|
393
396
|
// src/users/UserRepository.ts
|
|
394
397
|
import { eq as eq2, ne, sql as sql3 } from "drizzle-orm";
|
|
@@ -758,7 +761,8 @@ UserValidator = __decorate4([
|
|
|
758
761
|
], UserValidator);
|
|
759
762
|
|
|
760
763
|
// src/roles/RoleService.ts
|
|
761
|
-
import { Injectable as Injectable4 } from "najm-core";
|
|
764
|
+
import { Injectable as Injectable4, Err as Err3 } from "najm-core";
|
|
765
|
+
import { I18n as I18n3 } from "najm-i18n";
|
|
762
766
|
|
|
763
767
|
// src/roles/RoleRepository.ts
|
|
764
768
|
import { eq as eq3 } from "drizzle-orm";
|
|
@@ -782,6 +786,14 @@ var RoleRepository = class RoleRepository2 {
|
|
|
782
786
|
get roles() {
|
|
783
787
|
return this.schema.roles;
|
|
784
788
|
}
|
|
789
|
+
get users() {
|
|
790
|
+
return this.schema.users;
|
|
791
|
+
}
|
|
792
|
+
/** True if any user currently references this role (blocks deletion). */
|
|
793
|
+
async hasUsers(roleId) {
|
|
794
|
+
const rows = await this.db.select({ id: this.users.id }).from(this.users).where(eq3(this.users.roleId, roleId)).limit(1);
|
|
795
|
+
return rows.length > 0;
|
|
796
|
+
}
|
|
785
797
|
async getAll() {
|
|
786
798
|
return await this.db.select().from(this.roles);
|
|
787
799
|
}
|
|
@@ -917,6 +929,7 @@ var RoleService = class RoleService2 {
|
|
|
917
929
|
}
|
|
918
930
|
roleRepository;
|
|
919
931
|
roleValidator;
|
|
932
|
+
t;
|
|
920
933
|
constructor(roleRepository, roleValidator) {
|
|
921
934
|
this.roleRepository = roleRepository;
|
|
922
935
|
this.roleValidator = roleValidator;
|
|
@@ -936,12 +949,21 @@ var RoleService = class RoleService2 {
|
|
|
936
949
|
return await this.roleRepository.create(data);
|
|
937
950
|
}
|
|
938
951
|
async update(id, data) {
|
|
939
|
-
await this.roleValidator.checkRoleExists(id);
|
|
952
|
+
const role = await this.roleValidator.checkRoleExists(id);
|
|
953
|
+
if (role.name === ROLES.ADMIN && data.name && data.name !== ROLES.ADMIN) {
|
|
954
|
+
Err3(this.t("errors.cannotRenameSystem"), 403);
|
|
955
|
+
}
|
|
940
956
|
await this.roleValidator.checkNameUnique(data.name, id);
|
|
941
957
|
return await this.roleRepository.update(id, data);
|
|
942
958
|
}
|
|
943
959
|
async delete(id) {
|
|
944
|
-
await this.roleValidator.checkRoleExists(id);
|
|
960
|
+
const role = await this.roleValidator.checkRoleExists(id);
|
|
961
|
+
if (role.name === ROLES.ADMIN) {
|
|
962
|
+
Err3(this.t("errors.cannotDeleteSystem"), 403);
|
|
963
|
+
}
|
|
964
|
+
if (await this.roleRepository.hasUsers(id)) {
|
|
965
|
+
Err3(this.t("errors.roleInUse"), 409);
|
|
966
|
+
}
|
|
945
967
|
return await this.roleRepository.delete(id);
|
|
946
968
|
}
|
|
947
969
|
async seedDefaultRoles(defaultRoles) {
|
|
@@ -960,6 +982,10 @@ var RoleService = class RoleService2 {
|
|
|
960
982
|
return role?.id;
|
|
961
983
|
}
|
|
962
984
|
};
|
|
985
|
+
__decorate7([
|
|
986
|
+
I18n3("roles"),
|
|
987
|
+
__metadata7("design:type", Object)
|
|
988
|
+
], RoleService.prototype, "t", void 0);
|
|
963
989
|
RoleService = __decorate7([
|
|
964
990
|
Injectable4(),
|
|
965
991
|
__metadata7("design:paramtypes", [typeof (_a4 = typeof RoleRepository !== "undefined" && RoleRepository) === "function" ? _a4 : Object, typeof (_b2 = typeof RoleValidator !== "undefined" && RoleValidator) === "function" ? _b2 : Object])
|
|
@@ -972,7 +998,7 @@ import { nanoid as nanoid3 } from "nanoid";
|
|
|
972
998
|
import * as fs from "fs/promises";
|
|
973
999
|
import * as path from "path";
|
|
974
1000
|
import _isEmpty from "lodash.isempty";
|
|
975
|
-
import { Err as
|
|
1001
|
+
import { Err as Err4 } from "najm-core";
|
|
976
1002
|
var avatarsPath = path.join(process.cwd(), "avatars");
|
|
977
1003
|
var parseSchema = /* @__PURE__ */ __name(async (schema, data) => {
|
|
978
1004
|
try {
|
|
@@ -980,7 +1006,7 @@ var parseSchema = /* @__PURE__ */ __name(async (schema, data) => {
|
|
|
980
1006
|
} catch (error) {
|
|
981
1007
|
const errors = error.issues || error.errors || [];
|
|
982
1008
|
const errorMessage = errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
|
|
983
|
-
|
|
1009
|
+
Err4(errorMessage);
|
|
984
1010
|
}
|
|
985
1011
|
}, "parseSchema");
|
|
986
1012
|
var clean = /* @__PURE__ */ __name((obj) => {
|
|
@@ -1066,7 +1092,7 @@ var isPath = /* @__PURE__ */ __name((img) => typeof img === "string" && img.trim
|
|
|
1066
1092
|
var isFile = /* @__PURE__ */ __name((img) => !!img && typeof img !== "string" && img instanceof File, "isFile");
|
|
1067
1093
|
|
|
1068
1094
|
// src/users/UserService.ts
|
|
1069
|
-
import { Err as
|
|
1095
|
+
import { Err as Err5 } from "najm-core";
|
|
1070
1096
|
var __decorate8 = function(decorators, target, key, desc) {
|
|
1071
1097
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1072
1098
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1121,7 +1147,7 @@ var UserService = class UserService2 {
|
|
|
1121
1147
|
}
|
|
1122
1148
|
requireUser(user) {
|
|
1123
1149
|
if (!user) {
|
|
1124
|
-
|
|
1150
|
+
Err5(this.t("errors.notFound"), 404);
|
|
1125
1151
|
}
|
|
1126
1152
|
return user;
|
|
1127
1153
|
}
|
|
@@ -1135,12 +1161,12 @@ var UserService = class UserService2 {
|
|
|
1135
1161
|
if (roleByName) {
|
|
1136
1162
|
return roleByName.id;
|
|
1137
1163
|
}
|
|
1138
|
-
|
|
1164
|
+
Err5(`Role '${roleName}' not found`);
|
|
1139
1165
|
}
|
|
1140
1166
|
if (this.authConfig.defaultRole) {
|
|
1141
1167
|
const defaultRole = await this.roleService.getByName(this.authConfig.defaultRole);
|
|
1142
1168
|
if (!defaultRole) {
|
|
1143
|
-
|
|
1169
|
+
Err5(`Default role '${this.authConfig.defaultRole}' not found. Create it first or set defaultRole to null in auth config.`);
|
|
1144
1170
|
}
|
|
1145
1171
|
return defaultRole.id;
|
|
1146
1172
|
}
|
|
@@ -1173,7 +1199,7 @@ var UserService = class UserService2 {
|
|
|
1173
1199
|
async create(data) {
|
|
1174
1200
|
const { id, email: email2, name, image, emailVerified, password, roleId, role } = data;
|
|
1175
1201
|
if (!password || typeof password !== "string" || password.trim().length === 0) {
|
|
1176
|
-
|
|
1202
|
+
Err5("Password is required");
|
|
1177
1203
|
}
|
|
1178
1204
|
this.userValidator.validatePasswordStrength(password);
|
|
1179
1205
|
let userId = id || nanoid3(10);
|
|
@@ -1247,10 +1273,10 @@ var UserService = class UserService2 {
|
|
|
1247
1273
|
}
|
|
1248
1274
|
async seedAdminUser(config) {
|
|
1249
1275
|
if (!config?.email || !config?.password) {
|
|
1250
|
-
|
|
1276
|
+
Err5("Admin email and password must be provided via config parameter");
|
|
1251
1277
|
}
|
|
1252
1278
|
if (config.password.length < 12) {
|
|
1253
|
-
|
|
1279
|
+
Err5("Admin password must be at least 12 characters");
|
|
1254
1280
|
}
|
|
1255
1281
|
const adminRole = await this.roleValidator.checkAdminRoleExists();
|
|
1256
1282
|
const existingUser = await this.userRepository.getByEmail(config.email);
|
|
@@ -1279,7 +1305,7 @@ var UserService = class UserService2 {
|
|
|
1279
1305
|
}
|
|
1280
1306
|
};
|
|
1281
1307
|
__decorate8([
|
|
1282
|
-
|
|
1308
|
+
I18n4("users"),
|
|
1283
1309
|
__metadata8("design:type", Object)
|
|
1284
1310
|
], UserService.prototype, "t", void 0);
|
|
1285
1311
|
__decorate8([
|
|
@@ -1296,7 +1322,7 @@ UserService = __decorate8([
|
|
|
1296
1322
|
|
|
1297
1323
|
// src/tokens/TokenService.ts
|
|
1298
1324
|
import { Injectable as Injectable6, Inject as Inject7 } from "najm-core";
|
|
1299
|
-
import { I18n as
|
|
1325
|
+
import { I18n as I18n5 } from "najm-i18n";
|
|
1300
1326
|
import { CacheService } from "najm-cache";
|
|
1301
1327
|
import { createHash } from "crypto";
|
|
1302
1328
|
import jwt from "jsonwebtoken";
|
|
@@ -1413,7 +1439,7 @@ TokenRepository = __decorate9([
|
|
|
1413
1439
|
|
|
1414
1440
|
// src/tokens/TokenService.ts
|
|
1415
1441
|
import timestring2 from "timestring";
|
|
1416
|
-
import { Err as
|
|
1442
|
+
import { Err as Err6 } from "najm-core";
|
|
1417
1443
|
var __decorate10 = function(decorators, target, key, desc) {
|
|
1418
1444
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1419
1445
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1482,7 +1508,7 @@ var TokenService = class TokenService2 {
|
|
|
1482
1508
|
if (authorization?.startsWith("Bearer ")) {
|
|
1483
1509
|
return authorization.split(" ")[1];
|
|
1484
1510
|
}
|
|
1485
|
-
|
|
1511
|
+
Err6(this.t("errors.tokenMissing"));
|
|
1486
1512
|
}
|
|
1487
1513
|
/**
|
|
1488
1514
|
* Verify access token and check blacklist
|
|
@@ -1493,7 +1519,7 @@ var TokenService = class TokenService2 {
|
|
|
1493
1519
|
try {
|
|
1494
1520
|
payload = jwt.verify(token, this.config.jwt.accessSecret);
|
|
1495
1521
|
} catch {
|
|
1496
|
-
|
|
1522
|
+
Err6(this.t("errors.tokenVerificationFailed"));
|
|
1497
1523
|
}
|
|
1498
1524
|
const sessionKey = this.sessionVersionKey(payload.userId);
|
|
1499
1525
|
const blacklistKey = payload.jti ? `${this.blacklistPrefix}${payload.jti}` : null;
|
|
@@ -1506,15 +1532,15 @@ var TokenService = class TokenService2 {
|
|
|
1506
1532
|
const values = await this.getCacheValues(keys);
|
|
1507
1533
|
const valueByKey = new Map(keys.map((key, i) => [key, values[i]]));
|
|
1508
1534
|
if (blacklistKey && valueByKey.get(blacklistKey) != null) {
|
|
1509
|
-
|
|
1535
|
+
Err6(this.t("errors.tokenRevoked"));
|
|
1510
1536
|
}
|
|
1511
1537
|
if (familyKey && valueByKey.get(familyKey) != null) {
|
|
1512
|
-
|
|
1538
|
+
Err6(this.t("errors.tokenRevoked"));
|
|
1513
1539
|
}
|
|
1514
1540
|
const activeSessionVersion = this.parseSessionVersion(valueByKey.get(sessionKey) ?? null);
|
|
1515
1541
|
const tokenSessionVersion = payload.sessionVersion ?? 0;
|
|
1516
1542
|
if (tokenSessionVersion !== activeSessionVersion) {
|
|
1517
|
-
|
|
1543
|
+
Err6(this.t("errors.tokenRevoked"));
|
|
1518
1544
|
}
|
|
1519
1545
|
return payload;
|
|
1520
1546
|
}
|
|
@@ -1523,13 +1549,13 @@ var TokenService = class TokenService2 {
|
|
|
1523
1549
|
try {
|
|
1524
1550
|
decoded = jwt.verify(token, this.config.jwt.refreshSecret);
|
|
1525
1551
|
} catch {
|
|
1526
|
-
|
|
1552
|
+
Err6(this.t("errors.tokenVerificationFailed"));
|
|
1527
1553
|
}
|
|
1528
1554
|
if (decoded.type && decoded.type !== "refresh") {
|
|
1529
|
-
|
|
1555
|
+
Err6(this.t("errors.tokenVerificationFailed"));
|
|
1530
1556
|
}
|
|
1531
1557
|
if (!decoded.tokenFamily) {
|
|
1532
|
-
|
|
1558
|
+
Err6(this.t("errors.tokenVerificationFailed"));
|
|
1533
1559
|
}
|
|
1534
1560
|
return { userId: decoded.userId, tokenFamily: decoded.tokenFamily };
|
|
1535
1561
|
}
|
|
@@ -1548,12 +1574,12 @@ var TokenService = class TokenService2 {
|
|
|
1548
1574
|
async resolveUserFromCookie() {
|
|
1549
1575
|
const refreshToken = this.cookieManager.getRefreshToken();
|
|
1550
1576
|
if (!refreshToken) {
|
|
1551
|
-
|
|
1577
|
+
Err6(this.t("errors.refreshTokenMissing"));
|
|
1552
1578
|
}
|
|
1553
1579
|
const { userId, tokenFamily } = this.verifyRefreshToken(refreshToken);
|
|
1554
1580
|
const stored = await this.tokenRepository.getByFamily(tokenFamily);
|
|
1555
1581
|
if (!stored || stored.userId !== userId) {
|
|
1556
|
-
|
|
1582
|
+
Err6(this.t("errors.refreshTokenInvalid"));
|
|
1557
1583
|
}
|
|
1558
1584
|
const presentedHash = this.hashToken(refreshToken);
|
|
1559
1585
|
if (presentedHash === stored.token) {
|
|
@@ -1563,7 +1589,7 @@ var TokenService = class TokenService2 {
|
|
|
1563
1589
|
if (canRecover) {
|
|
1564
1590
|
return userId;
|
|
1565
1591
|
}
|
|
1566
|
-
|
|
1592
|
+
Err6(this.t("errors.refreshTokenInvalid"));
|
|
1567
1593
|
}
|
|
1568
1594
|
// ============ USER RETRIEVAL (MAIN METHOD) ============
|
|
1569
1595
|
async getUser(auth2) {
|
|
@@ -1604,7 +1630,15 @@ var TokenService = class TokenService2 {
|
|
|
1604
1630
|
await this.cache.set(this.sessionVersionKey(data.userId), String(sessionVersion), this.accessTokenTtlMs());
|
|
1605
1631
|
}
|
|
1606
1632
|
const token = jwt.sign({ ...data, jti, sessionVersion, exp: expiresAt }, this.config.jwt.accessSecret);
|
|
1607
|
-
return { token, expiresAt };
|
|
1633
|
+
return { token, expiresAt, sessionVersion };
|
|
1634
|
+
}
|
|
1635
|
+
/**
|
|
1636
|
+
* Current per-user session version (0 when never invalidated). The signed
|
|
1637
|
+
* session cookie stamps this so a fast-path reader can reject a cookie whose
|
|
1638
|
+
* session was invalidated after it was written.
|
|
1639
|
+
*/
|
|
1640
|
+
async getSessionVersion(userId) {
|
|
1641
|
+
return this.getUserSessionVersion(userId);
|
|
1608
1642
|
}
|
|
1609
1643
|
/**
|
|
1610
1644
|
* Generate access token with unique jti for blacklist support.
|
|
@@ -1643,6 +1677,7 @@ var TokenService = class TokenService2 {
|
|
|
1643
1677
|
tokenFamily: family,
|
|
1644
1678
|
roles: accessTokenData.roles,
|
|
1645
1679
|
permissions: accessTokenData.permissions,
|
|
1680
|
+
sessionVersion: access.sessionVersion,
|
|
1646
1681
|
accessToken: access.token,
|
|
1647
1682
|
refreshToken: refresh.token,
|
|
1648
1683
|
accessTokenExpiresAt: access.expiresAt,
|
|
@@ -1710,12 +1745,12 @@ var TokenService = class TokenService2 {
|
|
|
1710
1745
|
async refreshTokens() {
|
|
1711
1746
|
const refreshToken = this.cookieManager.getRefreshToken();
|
|
1712
1747
|
if (!refreshToken) {
|
|
1713
|
-
|
|
1748
|
+
Err6(this.t("errors.refreshTokenMissing"));
|
|
1714
1749
|
}
|
|
1715
1750
|
const { userId, tokenFamily } = this.verifyRefreshToken(refreshToken);
|
|
1716
1751
|
const stored = await this.tokenRepository.getByFamily(tokenFamily);
|
|
1717
1752
|
if (!stored || stored.userId !== userId) {
|
|
1718
|
-
|
|
1753
|
+
Err6(this.t("errors.refreshTokenInvalid"));
|
|
1719
1754
|
}
|
|
1720
1755
|
const presentedHash = this.hashToken(refreshToken);
|
|
1721
1756
|
if (presentedHash === stored.token) {
|
|
@@ -1725,12 +1760,12 @@ var TokenService = class TokenService2 {
|
|
|
1725
1760
|
if (canRecover) {
|
|
1726
1761
|
const claimed = await this.tokenRepository.markPreviousUsed(tokenFamily, presentedHash);
|
|
1727
1762
|
if (!claimed?.length) {
|
|
1728
|
-
|
|
1763
|
+
Err6(this.t("errors.refreshTokenInvalid"));
|
|
1729
1764
|
}
|
|
1730
1765
|
return this.generateTokens(userId, tokenFamily);
|
|
1731
1766
|
}
|
|
1732
1767
|
await this.revokeSuspectRefreshFamily(userId, tokenFamily);
|
|
1733
|
-
|
|
1768
|
+
Err6(this.t("errors.refreshTokenInvalid"));
|
|
1734
1769
|
}
|
|
1735
1770
|
/** Revoke every refresh session for a user (password change/reset, logout-all). */
|
|
1736
1771
|
async revokeAllForUser(userId) {
|
|
@@ -1762,7 +1797,7 @@ var TokenService = class TokenService2 {
|
|
|
1762
1797
|
const userId = await this.resolveUserFromCookie();
|
|
1763
1798
|
const user = await this.getUserById(userId);
|
|
1764
1799
|
if (!user) {
|
|
1765
|
-
|
|
1800
|
+
Err6(this.t("errors.refreshTokenInvalid"));
|
|
1766
1801
|
}
|
|
1767
1802
|
return user;
|
|
1768
1803
|
}
|
|
@@ -1904,15 +1939,15 @@ var TokenService = class TokenService2 {
|
|
|
1904
1939
|
try {
|
|
1905
1940
|
decoded = jwt.verify(token, this.config.jwt.refreshSecret);
|
|
1906
1941
|
} catch {
|
|
1907
|
-
|
|
1942
|
+
Err6(this.t("errors.resetTokenExpired"));
|
|
1908
1943
|
}
|
|
1909
1944
|
if (decoded.type !== "reset" && decoded.type !== "invite" || !decoded.jti) {
|
|
1910
|
-
|
|
1945
|
+
Err6(this.t("errors.invalidResetToken"));
|
|
1911
1946
|
}
|
|
1912
1947
|
const key = `${this.resetTokenPrefix}${decoded.userId}`;
|
|
1913
1948
|
const storedJti = await this.cache.get(key);
|
|
1914
1949
|
if (!storedJti || storedJti !== decoded.jti) {
|
|
1915
|
-
|
|
1950
|
+
Err6(this.t("errors.invalidResetToken"));
|
|
1916
1951
|
}
|
|
1917
1952
|
await this.cache.del(key);
|
|
1918
1953
|
return decoded.userId;
|
|
@@ -1926,7 +1961,7 @@ __decorate10([
|
|
|
1926
1961
|
__metadata10("design:type", Object)
|
|
1927
1962
|
], TokenService.prototype, "config", void 0);
|
|
1928
1963
|
__decorate10([
|
|
1929
|
-
|
|
1964
|
+
I18n5("auth"),
|
|
1930
1965
|
__metadata10("design:type", Object)
|
|
1931
1966
|
], TokenService.prototype, "t", void 0);
|
|
1932
1967
|
TokenService = TokenService_1 = __decorate10([
|
|
@@ -1993,7 +2028,13 @@ var AuthService = class AuthService2 {
|
|
|
1993
2028
|
await this.getDummyHash();
|
|
1994
2029
|
}
|
|
1995
2030
|
async registerUser(body) {
|
|
1996
|
-
return await this.userService.create(
|
|
2031
|
+
return await this.userService.create({
|
|
2032
|
+
name: body.name,
|
|
2033
|
+
email: body.email,
|
|
2034
|
+
password: body.password,
|
|
2035
|
+
image: body.image,
|
|
2036
|
+
emailVerified: false
|
|
2037
|
+
});
|
|
1997
2038
|
}
|
|
1998
2039
|
/**
|
|
1999
2040
|
* Admin-initiated account creation. The user is created with a random,
|
|
@@ -2019,15 +2060,17 @@ var AuthService = class AuthService2 {
|
|
|
2019
2060
|
});
|
|
2020
2061
|
const { token } = await this.tokenService.generateInviteToken(user.id);
|
|
2021
2062
|
const inviteLink = `${this.config.frontendUrl}/reset-password?token=${token}`;
|
|
2063
|
+
let emailSent = false;
|
|
2022
2064
|
try {
|
|
2023
2065
|
await this.emailService.sendHtml(body.email, this.t("emails.accountInvite.subject"), accountInviteTemplate({
|
|
2024
2066
|
inviteLink,
|
|
2025
2067
|
userName: user.name || body.email
|
|
2026
2068
|
}));
|
|
2069
|
+
emailSent = true;
|
|
2027
2070
|
} catch (error) {
|
|
2028
2071
|
this.logger.warn("Account invite email failed", { email: body.email, error });
|
|
2029
2072
|
}
|
|
2030
|
-
return user;
|
|
2073
|
+
return { ...user, emailSent };
|
|
2031
2074
|
}
|
|
2032
2075
|
/**
|
|
2033
2076
|
* Create a login for a person record. The branch is intentional and is the
|
|
@@ -2062,7 +2105,7 @@ var AuthService = class AuthService2 {
|
|
|
2062
2105
|
user.lockoutUntil = null;
|
|
2063
2106
|
}
|
|
2064
2107
|
if (user && this.isLockoutActive(user.lockoutUntil)) {
|
|
2065
|
-
|
|
2108
|
+
Err7(this.t("errors.accountLocked"), 423);
|
|
2066
2109
|
}
|
|
2067
2110
|
const storedHash = user?.password ?? await this.getDummyHash();
|
|
2068
2111
|
const isValid = await this.userValidator.comparePassword(password, storedHash);
|
|
@@ -2071,13 +2114,16 @@ var AuthService = class AuthService2 {
|
|
|
2071
2114
|
const attempts = await this.userService.incrementFailedAttempts(user.id);
|
|
2072
2115
|
if (attempts >= this.config.lockout.maxAttempts) {
|
|
2073
2116
|
await this.userService.setLockout(user.id, this.nextLockoutUntil());
|
|
2074
|
-
|
|
2117
|
+
Err7(this.t("errors.accountLocked"), 423);
|
|
2075
2118
|
}
|
|
2076
2119
|
}
|
|
2077
|
-
|
|
2120
|
+
Err7(this.t("errors.invalidCredentials"));
|
|
2078
2121
|
}
|
|
2079
2122
|
if (user.status !== "active") {
|
|
2080
|
-
|
|
2123
|
+
Err7(this.t("errors.accountInactive"));
|
|
2124
|
+
}
|
|
2125
|
+
if (this.config.requireVerifiedEmail && !user.emailVerified) {
|
|
2126
|
+
Err7(this.t("errors.emailNotVerified"), 403);
|
|
2081
2127
|
}
|
|
2082
2128
|
if ((user.failedLoginAttempts ?? 0) > 0 || user.lockoutUntil) {
|
|
2083
2129
|
await this.userService.resetFailedAttempts(user.id);
|
|
@@ -2087,13 +2133,14 @@ var AuthService = class AuthService2 {
|
|
|
2087
2133
|
this.cookieManager.setRefreshToken(generated.refreshToken);
|
|
2088
2134
|
await this.userService.updateLastLogin(user.id);
|
|
2089
2135
|
const { password: _, failedLoginAttempts: __, lockoutUntil: ___, ...sanitized } = user;
|
|
2090
|
-
const { roles, permissions } = generated;
|
|
2136
|
+
const { roles, permissions, sessionVersion } = generated;
|
|
2091
2137
|
this.cookieManager.setSessionCookie({
|
|
2092
2138
|
user: { id: sanitized.id, email: sanitized.email, name: sanitized.name, role: sanitized.role, status: sanitized.status ?? void 0 },
|
|
2093
2139
|
roles,
|
|
2094
|
-
permissions
|
|
2140
|
+
permissions,
|
|
2141
|
+
sessionVersion
|
|
2095
2142
|
});
|
|
2096
|
-
const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, ...tokens } = generated;
|
|
2143
|
+
const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sv, ...tokens } = generated;
|
|
2097
2144
|
return { ...tokens, user: sanitized };
|
|
2098
2145
|
}
|
|
2099
2146
|
async refreshTokens() {
|
|
@@ -2104,10 +2151,11 @@ var AuthService = class AuthService2 {
|
|
|
2104
2151
|
this.cookieManager.setSessionCookie({
|
|
2105
2152
|
user: { id: user.id, email: user.email, name: user.name, role: user.role, status: user.status ?? void 0 },
|
|
2106
2153
|
roles: generated.roles,
|
|
2107
|
-
permissions: generated.permissions
|
|
2154
|
+
permissions: generated.permissions,
|
|
2155
|
+
sessionVersion: generated.sessionVersion
|
|
2108
2156
|
});
|
|
2109
2157
|
}
|
|
2110
|
-
const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, ...tokens } = generated;
|
|
2158
|
+
const { userId: _userId, tokenFamily: _tokenFamily, roles: _roles, permissions: _permissions, sessionVersion: _sv, ...tokens } = generated;
|
|
2111
2159
|
return tokens;
|
|
2112
2160
|
}
|
|
2113
2161
|
async logoutUser(userId, authorization) {
|
|
@@ -2153,7 +2201,7 @@ var AuthService = class AuthService2 {
|
|
|
2153
2201
|
const lang = this.i18nService.getCurrentLanguage();
|
|
2154
2202
|
result = { ...user, language: lang };
|
|
2155
2203
|
const token = this.tokenService.decodeAccessToken(authorization.replace(/^Bearer\s+/i, ""));
|
|
2156
|
-
cachePayload = { roles: token?.roles ?? [], permissions: token?.permissions ?? [] };
|
|
2204
|
+
cachePayload = { roles: token?.roles ?? [], permissions: token?.permissions ?? [], sessionVersion: token?.sessionVersion ?? 0 };
|
|
2157
2205
|
} else {
|
|
2158
2206
|
result = await this.getUserFromCookie();
|
|
2159
2207
|
}
|
|
@@ -2164,7 +2212,8 @@ var AuthService = class AuthService2 {
|
|
|
2164
2212
|
this.cookieManager.setSessionCookie({
|
|
2165
2213
|
user: { id: result.id, email: result.email, name: result.name, role: result.role, status: result.status ?? void 0 },
|
|
2166
2214
|
roles: cachePayload.roles,
|
|
2167
|
-
permissions: cachePayload.permissions
|
|
2215
|
+
permissions: cachePayload.permissions,
|
|
2216
|
+
sessionVersion: cachePayload.sessionVersion
|
|
2168
2217
|
});
|
|
2169
2218
|
}
|
|
2170
2219
|
return result;
|
|
@@ -2188,11 +2237,11 @@ var AuthService = class AuthService2 {
|
|
|
2188
2237
|
async changePassword(userId, currentPassword, newPassword) {
|
|
2189
2238
|
const user = await this.userService.getAuthRecordById(userId);
|
|
2190
2239
|
if (!user?.password) {
|
|
2191
|
-
|
|
2240
|
+
Err7(this.t("errors.invalidCredentials"));
|
|
2192
2241
|
}
|
|
2193
2242
|
const isValid = await this.userValidator.comparePassword(currentPassword, user.password);
|
|
2194
2243
|
if (!isValid) {
|
|
2195
|
-
|
|
2244
|
+
Err7(this.t("errors.invalidCredentials"));
|
|
2196
2245
|
}
|
|
2197
2246
|
this.userValidator.validatePasswordStrength(newPassword);
|
|
2198
2247
|
await this.userService.update(userId, { password: newPassword });
|
|
@@ -2218,7 +2267,7 @@ __decorate11([
|
|
|
2218
2267
|
__metadata11("design:type", Object)
|
|
2219
2268
|
], AuthService.prototype, "config", void 0);
|
|
2220
2269
|
__decorate11([
|
|
2221
|
-
|
|
2270
|
+
I18n6("auth"),
|
|
2222
2271
|
__metadata11("design:type", Object)
|
|
2223
2272
|
], AuthService.prototype, "t", void 0);
|
|
2224
2273
|
__decorate11([
|
|
@@ -2266,29 +2315,6 @@ AuthGuard = __decorate12([
|
|
|
2266
2315
|
], AuthGuard);
|
|
2267
2316
|
var isAuth = createGuard(AuthGuard);
|
|
2268
2317
|
|
|
2269
|
-
// src/roles/index.ts
|
|
2270
|
-
var roles_exports = {};
|
|
2271
|
-
__export(roles_exports, {
|
|
2272
|
-
ROLES: () => ROLES,
|
|
2273
|
-
ROLE_GROUPS: () => ROLE_GROUPS,
|
|
2274
|
-
Role: () => Role,
|
|
2275
|
-
RoleController: () => RoleController,
|
|
2276
|
-
RoleGuard: () => RoleGuard,
|
|
2277
|
-
RoleRepository: () => RoleRepository,
|
|
2278
|
-
RoleService: () => RoleService,
|
|
2279
|
-
RoleValidator: () => RoleValidator,
|
|
2280
|
-
assignRoleDto: () => assignRoleDto,
|
|
2281
|
-
createRoleDto: () => createRoleDto,
|
|
2282
|
-
defineRoles: () => defineRoles,
|
|
2283
|
-
isAdmin: () => isAdmin,
|
|
2284
|
-
isAdministrator: () => isAdministrator,
|
|
2285
|
-
roleIdParam: () => roleIdParam,
|
|
2286
|
-
updateRoleDto: () => updateRoleDto
|
|
2287
|
-
});
|
|
2288
|
-
|
|
2289
|
-
// src/roles/defineRoles.ts
|
|
2290
|
-
import { composeGuards as composeGuards2, createGuard as createGuard3 } from "najm-guard";
|
|
2291
|
-
|
|
2292
2318
|
// src/roles/RoleGuards.ts
|
|
2293
2319
|
import { Service as Service3 } from "najm-core";
|
|
2294
2320
|
import { GuardParams, User as User2 } from "najm-core";
|
|
@@ -2336,239 +2362,90 @@ var Role = createGuard2(RoleGuard);
|
|
|
2336
2362
|
var isAdmin = composeGuards(isAuth(), Role(ROLES.ADMIN));
|
|
2337
2363
|
var isAdministrator = composeGuards(isAuth(), Role(ROLE_GROUPS.ADMINISTRATORS));
|
|
2338
2364
|
|
|
2339
|
-
// src/roles/defineRoles.ts
|
|
2340
|
-
var Role2 = createGuard3(RoleGuard);
|
|
2341
|
-
function defineRoles(roles, options) {
|
|
2342
|
-
const ROLES2 = roles;
|
|
2343
|
-
const superRoleKeys = options?.superRoles ?? [];
|
|
2344
|
-
function resolveRoleValues(keys) {
|
|
2345
|
-
return Array.from(new Set([...keys, ...superRoleKeys].map((key) => roles[key])));
|
|
2346
|
-
}
|
|
2347
|
-
__name(resolveRoleValues, "resolveRoleValues");
|
|
2348
|
-
const guards2 = {};
|
|
2349
|
-
for (const [key, value] of Object.entries(roles)) {
|
|
2350
|
-
const name = `is${key.charAt(0).toUpperCase()}${key.slice(1).toLowerCase()}`;
|
|
2351
|
-
const allowedValues = resolveRoleValues([key]);
|
|
2352
|
-
guards2[name] = composeGuards2(isAuth(), Role2(allowedValues.length === 1 ? value : allowedValues));
|
|
2353
|
-
}
|
|
2354
|
-
function createGroupGuard(keys) {
|
|
2355
|
-
const values = resolveRoleValues(keys);
|
|
2356
|
-
return composeGuards2(isAuth(), Role2(values));
|
|
2357
|
-
}
|
|
2358
|
-
__name(createGroupGuard, "createGroupGuard");
|
|
2359
|
-
function hasRole(userRole, ...keys) {
|
|
2360
|
-
if (!userRole)
|
|
2361
|
-
return false;
|
|
2362
|
-
const normalized = userRole.toLowerCase();
|
|
2363
|
-
return resolveRoleValues(keys).some((role) => role === normalized);
|
|
2364
|
-
}
|
|
2365
|
-
__name(hasRole, "hasRole");
|
|
2366
|
-
function isInGroup(userRole, keys) {
|
|
2367
|
-
return hasRole(userRole, ...keys);
|
|
2368
|
-
}
|
|
2369
|
-
__name(isInGroup, "isInGroup");
|
|
2370
|
-
return { ROLES: ROLES2, createGroupGuard, hasRole, isInGroup, ...guards2 };
|
|
2371
|
-
}
|
|
2372
|
-
__name(defineRoles, "defineRoles");
|
|
2373
|
-
|
|
2374
|
-
// src/roles/RoleController.ts
|
|
2375
|
-
import { Controller } from "najm-core";
|
|
2376
|
-
import { Get, Post, Put, Delete, ResMsg } from "najm-core";
|
|
2377
|
-
import { Params, Body } from "najm-core";
|
|
2378
|
-
import { Validate } from "najm-validation";
|
|
2379
|
-
|
|
2380
|
-
// src/roles/RoleDto.ts
|
|
2381
|
-
import { z } from "zod";
|
|
2382
|
-
var nameField = z.string().min(2, "Name must be at least 2 characters").max(50, "Name too long");
|
|
2383
|
-
var descriptionField = z.string().max(255, "Description too long").optional();
|
|
2384
|
-
var createRoleDto = z.object({
|
|
2385
|
-
name: nameField,
|
|
2386
|
-
description: descriptionField
|
|
2387
|
-
});
|
|
2388
|
-
var updateRoleDto = createRoleDto.partial();
|
|
2389
|
-
var roleIdParam = z.object({
|
|
2390
|
-
id: z.string().length(5, "Role ID must be 5 characters")
|
|
2391
|
-
});
|
|
2392
|
-
var assignRoleDto = z.object({
|
|
2393
|
-
userId: z.string().length(8, "User ID must be 8 characters"),
|
|
2394
|
-
roleId: z.string().length(5, "Role ID must be 5 characters")
|
|
2395
|
-
});
|
|
2396
|
-
|
|
2397
|
-
// src/roles/RoleController.ts
|
|
2398
|
-
var __decorate14 = function(decorators, target, key, desc) {
|
|
2399
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2400
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2401
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2402
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2403
|
-
};
|
|
2404
|
-
var __metadata14 = function(k, v) {
|
|
2405
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2406
|
-
};
|
|
2407
|
-
var __param5 = function(paramIndex, decorator) {
|
|
2408
|
-
return function(target, key) {
|
|
2409
|
-
decorator(target, key, paramIndex);
|
|
2410
|
-
};
|
|
2411
|
-
};
|
|
2412
|
-
var _a8;
|
|
2413
|
-
var RoleController = class RoleController2 {
|
|
2414
|
-
static {
|
|
2415
|
-
__name(this, "RoleController");
|
|
2416
|
-
}
|
|
2417
|
-
roleService;
|
|
2418
|
-
constructor(roleService) {
|
|
2419
|
-
this.roleService = roleService;
|
|
2420
|
-
}
|
|
2421
|
-
async getRoles() {
|
|
2422
|
-
return this.roleService.getAll();
|
|
2423
|
-
}
|
|
2424
|
-
async getRole(params) {
|
|
2425
|
-
return this.roleService.getById(params.id);
|
|
2426
|
-
}
|
|
2427
|
-
async createRole(body) {
|
|
2428
|
-
return this.roleService.create(body);
|
|
2429
|
-
}
|
|
2430
|
-
async updateRole(params, body) {
|
|
2431
|
-
return this.roleService.update(params.id, body);
|
|
2432
|
-
}
|
|
2433
|
-
async deleteRole(params) {
|
|
2434
|
-
return this.roleService.delete(params.id);
|
|
2435
|
-
}
|
|
2436
|
-
};
|
|
2437
|
-
__decorate14([
|
|
2438
|
-
Get(),
|
|
2439
|
-
isAdmin(),
|
|
2440
|
-
ResMsg("roles.success.retrieved"),
|
|
2441
|
-
__metadata14("design:type", Function),
|
|
2442
|
-
__metadata14("design:paramtypes", []),
|
|
2443
|
-
__metadata14("design:returntype", Promise)
|
|
2444
|
-
], RoleController.prototype, "getRoles", null);
|
|
2445
|
-
__decorate14([
|
|
2446
|
-
Get("/:id"),
|
|
2447
|
-
isAdmin(),
|
|
2448
|
-
Validate({ params: roleIdParam }),
|
|
2449
|
-
ResMsg("roles.success.retrieved"),
|
|
2450
|
-
__param5(0, Params()),
|
|
2451
|
-
__metadata14("design:type", Function),
|
|
2452
|
-
__metadata14("design:paramtypes", [Object]),
|
|
2453
|
-
__metadata14("design:returntype", Promise)
|
|
2454
|
-
], RoleController.prototype, "getRole", null);
|
|
2455
|
-
__decorate14([
|
|
2456
|
-
Post(),
|
|
2457
|
-
isAdmin(),
|
|
2458
|
-
Validate(createRoleDto),
|
|
2459
|
-
ResMsg("roles.success.created"),
|
|
2460
|
-
__param5(0, Body()),
|
|
2461
|
-
__metadata14("design:type", Function),
|
|
2462
|
-
__metadata14("design:paramtypes", [Object]),
|
|
2463
|
-
__metadata14("design:returntype", Promise)
|
|
2464
|
-
], RoleController.prototype, "createRole", null);
|
|
2465
|
-
__decorate14([
|
|
2466
|
-
Put("/:id"),
|
|
2467
|
-
isAdmin(),
|
|
2468
|
-
Validate({
|
|
2469
|
-
params: roleIdParam,
|
|
2470
|
-
body: updateRoleDto
|
|
2471
|
-
}),
|
|
2472
|
-
ResMsg("roles.success.updated"),
|
|
2473
|
-
__param5(0, Params()),
|
|
2474
|
-
__param5(1, Body()),
|
|
2475
|
-
__metadata14("design:type", Function),
|
|
2476
|
-
__metadata14("design:paramtypes", [Object, Object]),
|
|
2477
|
-
__metadata14("design:returntype", Promise)
|
|
2478
|
-
], RoleController.prototype, "updateRole", null);
|
|
2479
|
-
__decorate14([
|
|
2480
|
-
Delete("/:id"),
|
|
2481
|
-
isAdmin(),
|
|
2482
|
-
Validate({ params: roleIdParam }),
|
|
2483
|
-
ResMsg("roles.success.deleted"),
|
|
2484
|
-
__param5(0, Params()),
|
|
2485
|
-
__metadata14("design:type", Function),
|
|
2486
|
-
__metadata14("design:paramtypes", [Object]),
|
|
2487
|
-
__metadata14("design:returntype", Promise)
|
|
2488
|
-
], RoleController.prototype, "deleteRole", null);
|
|
2489
|
-
RoleController = __decorate14([
|
|
2490
|
-
Controller("/roles"),
|
|
2491
|
-
__metadata14("design:paramtypes", [typeof (_a8 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a8 : Object])
|
|
2492
|
-
], RoleController);
|
|
2493
|
-
|
|
2494
2365
|
// src/auth/AuthController.ts
|
|
2495
|
-
import { Validate
|
|
2366
|
+
import { Validate } from "najm-validation";
|
|
2496
2367
|
import { RateLimit } from "najm-rate";
|
|
2497
2368
|
import { createHash as createHash2 } from "crypto";
|
|
2498
2369
|
|
|
2499
2370
|
// src/users/UserDto.ts
|
|
2500
|
-
import { z
|
|
2501
|
-
var emailField =
|
|
2502
|
-
var passwordField =
|
|
2503
|
-
var optionalDateField =
|
|
2504
|
-
var createUserDto =
|
|
2505
|
-
name:
|
|
2371
|
+
import { z } from "zod";
|
|
2372
|
+
var emailField = z.string().email("Invalid email format");
|
|
2373
|
+
var passwordField = z.string().min(8, "Password must be at least 8 characters").refine((v) => new TextEncoder().encode(v).length <= 72, "Password must be at most 72 bytes").regex(/[A-Z]/, "Password must contain at least one uppercase letter").regex(/[a-z]/, "Password must contain at least one lowercase letter").regex(/\d/, "Password must contain at least one number");
|
|
2374
|
+
var optionalDateField = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").nullable().optional();
|
|
2375
|
+
var createUserDto = z.object({
|
|
2376
|
+
name: z.string().max(100).optional(),
|
|
2506
2377
|
email: emailField,
|
|
2507
2378
|
password: passwordField,
|
|
2508
|
-
roleId:
|
|
2509
|
-
image:
|
|
2510
|
-
emailVerified:
|
|
2511
|
-
status:
|
|
2379
|
+
roleId: z.string().min(1).optional(),
|
|
2380
|
+
image: z.string().nullish(),
|
|
2381
|
+
emailVerified: z.boolean().default(false),
|
|
2382
|
+
status: z.enum(["active", "inactive", "pending"]).optional()
|
|
2512
2383
|
});
|
|
2513
2384
|
var updateUserDto = createUserDto.partial();
|
|
2514
|
-
var
|
|
2515
|
-
name:
|
|
2385
|
+
var registerDto = z.object({
|
|
2386
|
+
name: z.string().max(100).optional(),
|
|
2516
2387
|
email: emailField,
|
|
2517
|
-
|
|
2518
|
-
image:
|
|
2388
|
+
password: passwordField,
|
|
2389
|
+
image: z.string().nullish()
|
|
2519
2390
|
});
|
|
2520
|
-
var
|
|
2521
|
-
|
|
2391
|
+
var inviteUserDto = z.object({
|
|
2392
|
+
name: z.string().max(100).optional(),
|
|
2393
|
+
email: emailField,
|
|
2394
|
+
roleId: z.string().min(1).optional(),
|
|
2395
|
+
image: z.string().nullish()
|
|
2522
2396
|
});
|
|
2523
|
-
var
|
|
2397
|
+
var userIdParam = z.object({
|
|
2398
|
+
id: z.string().min(1, "User ID is required")
|
|
2399
|
+
});
|
|
2400
|
+
var loginDto = z.object({
|
|
2524
2401
|
email: emailField,
|
|
2525
2402
|
password: passwordField
|
|
2526
2403
|
});
|
|
2527
|
-
var changePasswordDto =
|
|
2404
|
+
var changePasswordDto = z.object({
|
|
2528
2405
|
currentPassword: passwordField,
|
|
2529
2406
|
newPassword: passwordField
|
|
2530
2407
|
});
|
|
2531
|
-
var resetPasswordDto =
|
|
2408
|
+
var resetPasswordDto = z.object({
|
|
2532
2409
|
email: emailField
|
|
2533
2410
|
});
|
|
2534
|
-
var confirmResetPasswordDto =
|
|
2535
|
-
token:
|
|
2411
|
+
var confirmResetPasswordDto = z.object({
|
|
2412
|
+
token: z.string().min(10, "Invalid reset token"),
|
|
2536
2413
|
newPassword: passwordField
|
|
2537
2414
|
});
|
|
2538
|
-
var languageParam =
|
|
2539
|
-
language:
|
|
2415
|
+
var languageParam = z.object({
|
|
2416
|
+
language: z.string().min(2)
|
|
2540
2417
|
});
|
|
2541
|
-
var emailParam =
|
|
2418
|
+
var emailParam = z.object({
|
|
2542
2419
|
email: emailField
|
|
2543
2420
|
});
|
|
2544
|
-
var userIdInParam =
|
|
2545
|
-
userId:
|
|
2421
|
+
var userIdInParam = z.object({
|
|
2422
|
+
userId: z.string().min(1, "User ID is required")
|
|
2546
2423
|
});
|
|
2547
|
-
var assignRoleParams =
|
|
2548
|
-
userId:
|
|
2549
|
-
roleId:
|
|
2424
|
+
var assignRoleParams = z.object({
|
|
2425
|
+
userId: z.string().min(1, "User ID is required"),
|
|
2426
|
+
roleId: z.string().min(1)
|
|
2550
2427
|
});
|
|
2551
|
-
var userListQuery =
|
|
2552
|
-
limit:
|
|
2553
|
-
offset:
|
|
2428
|
+
var userListQuery = z.object({
|
|
2429
|
+
limit: z.coerce.number().int().min(1).max(100).default(50),
|
|
2430
|
+
offset: z.coerce.number().int().min(0).default(0)
|
|
2554
2431
|
});
|
|
2555
2432
|
|
|
2556
2433
|
// src/auth/AuthController.ts
|
|
2557
|
-
var
|
|
2434
|
+
var __decorate14 = function(decorators, target, key, desc) {
|
|
2558
2435
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2559
2436
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2560
2437
|
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
2438
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2562
2439
|
};
|
|
2563
|
-
var
|
|
2440
|
+
var __metadata14 = function(k, v) {
|
|
2564
2441
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2565
2442
|
};
|
|
2566
|
-
var
|
|
2443
|
+
var __param5 = function(paramIndex, decorator) {
|
|
2567
2444
|
return function(target, key) {
|
|
2568
2445
|
decorator(target, key, paramIndex);
|
|
2569
2446
|
};
|
|
2570
2447
|
};
|
|
2571
|
-
var
|
|
2448
|
+
var _a8;
|
|
2572
2449
|
var hashKeyPart = /* @__PURE__ */ __name((value) => createHash2("sha256").update(value).digest("base64url").slice(0, 32), "hashKeyPart");
|
|
2573
2450
|
var cookieFingerprint = /* @__PURE__ */ __name(() => (ctx) => {
|
|
2574
2451
|
const ip = ctx.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? ctx.req.header("x-real-ip") ?? "unknown";
|
|
@@ -2625,113 +2502,113 @@ var AuthController = class AuthController2 {
|
|
|
2625
2502
|
return this.authService.resetPassword(body.token, body.newPassword);
|
|
2626
2503
|
}
|
|
2627
2504
|
};
|
|
2628
|
-
|
|
2629
|
-
|
|
2505
|
+
__decorate14([
|
|
2506
|
+
Post("/register"),
|
|
2630
2507
|
RateLimit({ limit: 5, window: "15m", key: ipAndEmail }),
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2508
|
+
Validate(registerDto),
|
|
2509
|
+
ResMsg("auth.success.register"),
|
|
2510
|
+
__param5(0, Body()),
|
|
2511
|
+
__metadata14("design:type", Function),
|
|
2512
|
+
__metadata14("design:paramtypes", [Object]),
|
|
2513
|
+
__metadata14("design:returntype", Promise)
|
|
2637
2514
|
], AuthController.prototype, "registerUser", null);
|
|
2638
|
-
|
|
2639
|
-
|
|
2515
|
+
__decorate14([
|
|
2516
|
+
Post("/login"),
|
|
2640
2517
|
RateLimit({ limit: 5, window: "15m", key: ipAndEmail, message: "Too many login attempts. Please try again later." }),
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2518
|
+
Validate(loginDto),
|
|
2519
|
+
ResMsg("auth.success.login"),
|
|
2520
|
+
__param5(0, Body()),
|
|
2521
|
+
__metadata14("design:type", Function),
|
|
2522
|
+
__metadata14("design:paramtypes", [Object]),
|
|
2523
|
+
__metadata14("design:returntype", Promise)
|
|
2647
2524
|
], AuthController.prototype, "loginUser", null);
|
|
2648
|
-
|
|
2649
|
-
|
|
2525
|
+
__decorate14([
|
|
2526
|
+
Post("/invite"),
|
|
2650
2527
|
isAdmin(),
|
|
2651
2528
|
RateLimit({ limit: 20, window: "15m", key: "user" }),
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2529
|
+
Validate(inviteUserDto),
|
|
2530
|
+
ResMsg("auth.success.accountInviteSent"),
|
|
2531
|
+
__param5(0, Body()),
|
|
2532
|
+
__metadata14("design:type", Function),
|
|
2533
|
+
__metadata14("design:paramtypes", [Object]),
|
|
2534
|
+
__metadata14("design:returntype", Promise)
|
|
2658
2535
|
], AuthController.prototype, "inviteUser", null);
|
|
2659
|
-
|
|
2660
|
-
|
|
2536
|
+
__decorate14([
|
|
2537
|
+
Post("/refresh"),
|
|
2661
2538
|
RateLimit({ limit: 15, window: "15m", key: cookieFingerprint() }),
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2539
|
+
ResMsg("auth.success.tokenRefreshed"),
|
|
2540
|
+
__metadata14("design:type", Function),
|
|
2541
|
+
__metadata14("design:paramtypes", []),
|
|
2542
|
+
__metadata14("design:returntype", Promise)
|
|
2666
2543
|
], AuthController.prototype, "refreshTokens", null);
|
|
2667
|
-
|
|
2668
|
-
|
|
2544
|
+
__decorate14([
|
|
2545
|
+
Post("/logout"),
|
|
2669
2546
|
isAuth(),
|
|
2670
2547
|
RateLimit({ limit: 10, window: "15m", key: "user" }),
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2548
|
+
__param5(0, User3("id")),
|
|
2549
|
+
__param5(1, Headers("authorization")),
|
|
2550
|
+
__metadata14("design:type", Function),
|
|
2551
|
+
__metadata14("design:paramtypes", [String, String]),
|
|
2552
|
+
__metadata14("design:returntype", Promise)
|
|
2676
2553
|
], AuthController.prototype, "logoutUser", null);
|
|
2677
|
-
|
|
2678
|
-
|
|
2554
|
+
__decorate14([
|
|
2555
|
+
Post("/change-password"),
|
|
2679
2556
|
isAuth(),
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2557
|
+
Validate(changePasswordDto),
|
|
2558
|
+
ResMsg("auth.success.passwordChanged"),
|
|
2559
|
+
__param5(0, User3("id")),
|
|
2560
|
+
__param5(1, Body()),
|
|
2561
|
+
__metadata14("design:type", Function),
|
|
2562
|
+
__metadata14("design:paramtypes", [String, Object]),
|
|
2563
|
+
__metadata14("design:returntype", Promise)
|
|
2687
2564
|
], AuthController.prototype, "changePassword", null);
|
|
2688
|
-
|
|
2689
|
-
|
|
2565
|
+
__decorate14([
|
|
2566
|
+
Get("/me"),
|
|
2690
2567
|
RateLimit({ limit: 30, window: "1m", key: cookieFingerprint() }),
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2568
|
+
ResMsg("auth.users.success.retrieved"),
|
|
2569
|
+
__param5(0, Headers("authorization")),
|
|
2570
|
+
__metadata14("design:type", Function),
|
|
2571
|
+
__metadata14("design:paramtypes", [String]),
|
|
2572
|
+
__metadata14("design:returntype", Promise)
|
|
2696
2573
|
], AuthController.prototype, "userProfile", null);
|
|
2697
|
-
|
|
2698
|
-
|
|
2574
|
+
__decorate14([
|
|
2575
|
+
Post("/forgot-password"),
|
|
2699
2576
|
RateLimit({ limit: 3, window: "15m", key: ipAndEmail, message: "Too many password reset requests. Please try again later." }),
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2577
|
+
Validate(resetPasswordDto),
|
|
2578
|
+
ResMsg("auth.success.passwordResetSent"),
|
|
2579
|
+
__param5(0, Body()),
|
|
2580
|
+
__metadata14("design:type", Function),
|
|
2581
|
+
__metadata14("design:paramtypes", [Object]),
|
|
2582
|
+
__metadata14("design:returntype", Promise)
|
|
2706
2583
|
], AuthController.prototype, "forgotPassword", null);
|
|
2707
|
-
|
|
2708
|
-
|
|
2584
|
+
__decorate14([
|
|
2585
|
+
Post("/reset-password"),
|
|
2709
2586
|
RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many password reset attempts. Please try again later." }),
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2587
|
+
Validate(confirmResetPasswordDto),
|
|
2588
|
+
ResMsg("auth.success.passwordReset"),
|
|
2589
|
+
__param5(0, Body()),
|
|
2590
|
+
__metadata14("design:type", Function),
|
|
2591
|
+
__metadata14("design:paramtypes", [Object]),
|
|
2592
|
+
__metadata14("design:returntype", Promise)
|
|
2716
2593
|
], AuthController.prototype, "resetPassword", null);
|
|
2717
|
-
AuthController =
|
|
2718
|
-
|
|
2719
|
-
|
|
2594
|
+
AuthController = __decorate14([
|
|
2595
|
+
Controller("/auth"),
|
|
2596
|
+
__metadata14("design:paramtypes", [typeof (_a8 = typeof AuthService !== "undefined" && AuthService) === "function" ? _a8 : Object])
|
|
2720
2597
|
], AuthController);
|
|
2721
2598
|
|
|
2722
2599
|
// src/auth/AuthResolver.ts
|
|
2723
2600
|
import { APP, Container, DI, Inject as Inject9, LOGGER, Meta, Service as Service4 } from "najm-core";
|
|
2724
2601
|
import { USER, ROLE, PERMISSIONS } from "najm-guard";
|
|
2725
|
-
var
|
|
2602
|
+
var __decorate15 = function(decorators, target, key, desc) {
|
|
2726
2603
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2727
2604
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2728
2605
|
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;
|
|
2729
2606
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2730
2607
|
};
|
|
2731
|
-
var
|
|
2608
|
+
var __metadata15 = function(k, v) {
|
|
2732
2609
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2733
2610
|
};
|
|
2734
|
-
var
|
|
2611
|
+
var _a9;
|
|
2735
2612
|
var AuthResolver = class AuthResolver2 {
|
|
2736
2613
|
static {
|
|
2737
2614
|
__name(this, "AuthResolver");
|
|
@@ -2778,6 +2655,10 @@ var AuthResolver = class AuthResolver2 {
|
|
|
2778
2655
|
const session = cookieManager.getSessionCookie();
|
|
2779
2656
|
if (!session)
|
|
2780
2657
|
return false;
|
|
2658
|
+
const tokenService = await this.container.resolve(TokenService);
|
|
2659
|
+
const currentVersion = await tokenService.getSessionVersion(session.user.id);
|
|
2660
|
+
if ((session.sessionVersion ?? 0) !== currentVersion)
|
|
2661
|
+
return false;
|
|
2781
2662
|
return {
|
|
2782
2663
|
user: { ...session.user, permissions: session.permissions },
|
|
2783
2664
|
role: session.user.role ?? session.roles[0],
|
|
@@ -2843,19 +2724,19 @@ var AuthResolver = class AuthResolver2 {
|
|
|
2843
2724
|
await authService.warmupPasswordHash();
|
|
2844
2725
|
}
|
|
2845
2726
|
};
|
|
2846
|
-
|
|
2727
|
+
__decorate15([
|
|
2847
2728
|
DI(),
|
|
2848
|
-
|
|
2729
|
+
__metadata15("design:type", typeof (_a9 = typeof Container !== "undefined" && Container) === "function" ? _a9 : Object)
|
|
2849
2730
|
], AuthResolver.prototype, "container", void 0);
|
|
2850
|
-
|
|
2731
|
+
__decorate15([
|
|
2851
2732
|
Inject9(APP),
|
|
2852
|
-
|
|
2733
|
+
__metadata15("design:type", Object)
|
|
2853
2734
|
], AuthResolver.prototype, "app", void 0);
|
|
2854
|
-
|
|
2735
|
+
__decorate15([
|
|
2855
2736
|
Inject9(LOGGER),
|
|
2856
|
-
|
|
2737
|
+
__metadata15("design:type", Object)
|
|
2857
2738
|
], AuthResolver.prototype, "log", void 0);
|
|
2858
|
-
AuthResolver =
|
|
2739
|
+
AuthResolver = __decorate15([
|
|
2859
2740
|
Service4(),
|
|
2860
2741
|
Meta({ layer: "plugin", order: 30 })
|
|
2861
2742
|
], AuthResolver);
|
|
@@ -2908,6 +2789,7 @@ __export(users_exports, {
|
|
|
2908
2789
|
inviteUserDto: () => inviteUserDto,
|
|
2909
2790
|
languageParam: () => languageParam,
|
|
2910
2791
|
loginDto: () => loginDto,
|
|
2792
|
+
registerDto: () => registerDto,
|
|
2911
2793
|
resetPasswordDto: () => resetPasswordDto,
|
|
2912
2794
|
updateUserDto: () => updateUserDto,
|
|
2913
2795
|
userIdInParam: () => userIdInParam,
|
|
@@ -2919,6 +2801,184 @@ __export(users_exports, {
|
|
|
2919
2801
|
import { Controller as Controller3 } from "najm-core";
|
|
2920
2802
|
import { Get as Get3, Post as Post3, Put as Put2, Delete as Delete2, ResMsg as ResMsg3 } from "najm-core";
|
|
2921
2803
|
import { Params as Params2, Body as Body3, Query } from "najm-core";
|
|
2804
|
+
|
|
2805
|
+
// src/roles/index.ts
|
|
2806
|
+
var roles_exports = {};
|
|
2807
|
+
__export(roles_exports, {
|
|
2808
|
+
ROLES: () => ROLES,
|
|
2809
|
+
ROLE_GROUPS: () => ROLE_GROUPS,
|
|
2810
|
+
Role: () => Role,
|
|
2811
|
+
RoleController: () => RoleController,
|
|
2812
|
+
RoleGuard: () => RoleGuard,
|
|
2813
|
+
RoleRepository: () => RoleRepository,
|
|
2814
|
+
RoleService: () => RoleService,
|
|
2815
|
+
RoleValidator: () => RoleValidator,
|
|
2816
|
+
assignRoleDto: () => assignRoleDto,
|
|
2817
|
+
createRoleDto: () => createRoleDto,
|
|
2818
|
+
defineRoles: () => defineRoles,
|
|
2819
|
+
isAdmin: () => isAdmin,
|
|
2820
|
+
isAdministrator: () => isAdministrator,
|
|
2821
|
+
roleIdParam: () => roleIdParam,
|
|
2822
|
+
updateRoleDto: () => updateRoleDto
|
|
2823
|
+
});
|
|
2824
|
+
|
|
2825
|
+
// src/roles/defineRoles.ts
|
|
2826
|
+
import { composeGuards as composeGuards2, createGuard as createGuard3 } from "najm-guard";
|
|
2827
|
+
var Role2 = createGuard3(RoleGuard);
|
|
2828
|
+
function defineRoles(roles, options) {
|
|
2829
|
+
const ROLES2 = roles;
|
|
2830
|
+
const superRoleKeys = options?.superRoles ?? [];
|
|
2831
|
+
function resolveRoleValues(keys) {
|
|
2832
|
+
return Array.from(new Set([...keys, ...superRoleKeys].map((key) => roles[key])));
|
|
2833
|
+
}
|
|
2834
|
+
__name(resolveRoleValues, "resolveRoleValues");
|
|
2835
|
+
const guards2 = {};
|
|
2836
|
+
for (const [key, value] of Object.entries(roles)) {
|
|
2837
|
+
const name = `is${key.charAt(0).toUpperCase()}${key.slice(1).toLowerCase()}`;
|
|
2838
|
+
const allowedValues = resolveRoleValues([key]);
|
|
2839
|
+
guards2[name] = composeGuards2(isAuth(), Role2(allowedValues.length === 1 ? value : allowedValues));
|
|
2840
|
+
}
|
|
2841
|
+
function createGroupGuard(keys) {
|
|
2842
|
+
const values = resolveRoleValues(keys);
|
|
2843
|
+
return composeGuards2(isAuth(), Role2(values));
|
|
2844
|
+
}
|
|
2845
|
+
__name(createGroupGuard, "createGroupGuard");
|
|
2846
|
+
function hasRole(userRole, ...keys) {
|
|
2847
|
+
if (!userRole)
|
|
2848
|
+
return false;
|
|
2849
|
+
const normalized = userRole.toLowerCase();
|
|
2850
|
+
return resolveRoleValues(keys).some((role) => role === normalized);
|
|
2851
|
+
}
|
|
2852
|
+
__name(hasRole, "hasRole");
|
|
2853
|
+
function isInGroup(userRole, keys) {
|
|
2854
|
+
return hasRole(userRole, ...keys);
|
|
2855
|
+
}
|
|
2856
|
+
__name(isInGroup, "isInGroup");
|
|
2857
|
+
return { ROLES: ROLES2, createGroupGuard, hasRole, isInGroup, ...guards2 };
|
|
2858
|
+
}
|
|
2859
|
+
__name(defineRoles, "defineRoles");
|
|
2860
|
+
|
|
2861
|
+
// src/roles/RoleController.ts
|
|
2862
|
+
import { Controller as Controller2 } from "najm-core";
|
|
2863
|
+
import { Get as Get2, Post as Post2, Put, Delete, ResMsg as ResMsg2 } from "najm-core";
|
|
2864
|
+
import { Params, Body as Body2 } from "najm-core";
|
|
2865
|
+
import { Validate as Validate2 } from "najm-validation";
|
|
2866
|
+
|
|
2867
|
+
// src/roles/RoleDto.ts
|
|
2868
|
+
import { z as z2 } from "zod";
|
|
2869
|
+
var nameField = z2.string().min(2, "Name must be at least 2 characters").max(50, "Name too long");
|
|
2870
|
+
var descriptionField = z2.string().max(255, "Description too long").optional();
|
|
2871
|
+
var createRoleDto = z2.object({
|
|
2872
|
+
name: nameField,
|
|
2873
|
+
description: descriptionField
|
|
2874
|
+
});
|
|
2875
|
+
var updateRoleDto = createRoleDto.partial();
|
|
2876
|
+
var roleIdParam = z2.object({
|
|
2877
|
+
id: z2.string().length(5, "Role ID must be 5 characters")
|
|
2878
|
+
});
|
|
2879
|
+
var assignRoleDto = z2.object({
|
|
2880
|
+
userId: z2.string().length(8, "User ID must be 8 characters"),
|
|
2881
|
+
roleId: z2.string().length(5, "Role ID must be 5 characters")
|
|
2882
|
+
});
|
|
2883
|
+
|
|
2884
|
+
// src/roles/RoleController.ts
|
|
2885
|
+
var __decorate16 = function(decorators, target, key, desc) {
|
|
2886
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2887
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2888
|
+
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;
|
|
2889
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2890
|
+
};
|
|
2891
|
+
var __metadata16 = function(k, v) {
|
|
2892
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
2893
|
+
};
|
|
2894
|
+
var __param6 = function(paramIndex, decorator) {
|
|
2895
|
+
return function(target, key) {
|
|
2896
|
+
decorator(target, key, paramIndex);
|
|
2897
|
+
};
|
|
2898
|
+
};
|
|
2899
|
+
var _a10;
|
|
2900
|
+
var RoleController = class RoleController2 {
|
|
2901
|
+
static {
|
|
2902
|
+
__name(this, "RoleController");
|
|
2903
|
+
}
|
|
2904
|
+
roleService;
|
|
2905
|
+
constructor(roleService) {
|
|
2906
|
+
this.roleService = roleService;
|
|
2907
|
+
}
|
|
2908
|
+
async getRoles() {
|
|
2909
|
+
return this.roleService.getAll();
|
|
2910
|
+
}
|
|
2911
|
+
async getRole(params) {
|
|
2912
|
+
return this.roleService.getById(params.id);
|
|
2913
|
+
}
|
|
2914
|
+
async createRole(body) {
|
|
2915
|
+
return this.roleService.create(body);
|
|
2916
|
+
}
|
|
2917
|
+
async updateRole(params, body) {
|
|
2918
|
+
return this.roleService.update(params.id, body);
|
|
2919
|
+
}
|
|
2920
|
+
async deleteRole(params) {
|
|
2921
|
+
return this.roleService.delete(params.id);
|
|
2922
|
+
}
|
|
2923
|
+
};
|
|
2924
|
+
__decorate16([
|
|
2925
|
+
Get2(),
|
|
2926
|
+
isAdmin(),
|
|
2927
|
+
ResMsg2("roles.success.retrieved"),
|
|
2928
|
+
__metadata16("design:type", Function),
|
|
2929
|
+
__metadata16("design:paramtypes", []),
|
|
2930
|
+
__metadata16("design:returntype", Promise)
|
|
2931
|
+
], RoleController.prototype, "getRoles", null);
|
|
2932
|
+
__decorate16([
|
|
2933
|
+
Get2("/:id"),
|
|
2934
|
+
isAdmin(),
|
|
2935
|
+
Validate2({ params: roleIdParam }),
|
|
2936
|
+
ResMsg2("roles.success.retrieved"),
|
|
2937
|
+
__param6(0, Params()),
|
|
2938
|
+
__metadata16("design:type", Function),
|
|
2939
|
+
__metadata16("design:paramtypes", [Object]),
|
|
2940
|
+
__metadata16("design:returntype", Promise)
|
|
2941
|
+
], RoleController.prototype, "getRole", null);
|
|
2942
|
+
__decorate16([
|
|
2943
|
+
Post2(),
|
|
2944
|
+
isAdmin(),
|
|
2945
|
+
Validate2(createRoleDto),
|
|
2946
|
+
ResMsg2("roles.success.created"),
|
|
2947
|
+
__param6(0, Body2()),
|
|
2948
|
+
__metadata16("design:type", Function),
|
|
2949
|
+
__metadata16("design:paramtypes", [Object]),
|
|
2950
|
+
__metadata16("design:returntype", Promise)
|
|
2951
|
+
], RoleController.prototype, "createRole", null);
|
|
2952
|
+
__decorate16([
|
|
2953
|
+
Put("/:id"),
|
|
2954
|
+
isAdmin(),
|
|
2955
|
+
Validate2({
|
|
2956
|
+
params: roleIdParam,
|
|
2957
|
+
body: updateRoleDto
|
|
2958
|
+
}),
|
|
2959
|
+
ResMsg2("roles.success.updated"),
|
|
2960
|
+
__param6(0, Params()),
|
|
2961
|
+
__param6(1, Body2()),
|
|
2962
|
+
__metadata16("design:type", Function),
|
|
2963
|
+
__metadata16("design:paramtypes", [Object, Object]),
|
|
2964
|
+
__metadata16("design:returntype", Promise)
|
|
2965
|
+
], RoleController.prototype, "updateRole", null);
|
|
2966
|
+
__decorate16([
|
|
2967
|
+
Delete("/:id"),
|
|
2968
|
+
isAdmin(),
|
|
2969
|
+
Validate2({ params: roleIdParam }),
|
|
2970
|
+
ResMsg2("roles.success.deleted"),
|
|
2971
|
+
__param6(0, Params()),
|
|
2972
|
+
__metadata16("design:type", Function),
|
|
2973
|
+
__metadata16("design:paramtypes", [Object]),
|
|
2974
|
+
__metadata16("design:returntype", Promise)
|
|
2975
|
+
], RoleController.prototype, "deleteRole", null);
|
|
2976
|
+
RoleController = __decorate16([
|
|
2977
|
+
Controller2("/roles"),
|
|
2978
|
+
__metadata16("design:paramtypes", [typeof (_a10 = typeof RoleService !== "undefined" && RoleService) === "function" ? _a10 : Object])
|
|
2979
|
+
], RoleController);
|
|
2980
|
+
|
|
2981
|
+
// src/users/UserController.ts
|
|
2922
2982
|
import { Validate as Validate3 } from "najm-validation";
|
|
2923
2983
|
var __decorate17 = function(decorators, target, key, desc) {
|
|
2924
2984
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -3291,8 +3351,8 @@ import { Injectable as Injectable10 } from "najm-core";
|
|
|
3291
3351
|
|
|
3292
3352
|
// src/permissions/PermissionValidator.ts
|
|
3293
3353
|
import { Injectable as Injectable9 } from "najm-core";
|
|
3294
|
-
import { I18n as
|
|
3295
|
-
import { Err as
|
|
3354
|
+
import { I18n as I18n7 } from "najm-i18n";
|
|
3355
|
+
import { Err as Err8 } from "najm-core";
|
|
3296
3356
|
var __decorate20 = function(decorators, target, key, desc) {
|
|
3297
3357
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3298
3358
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -3321,7 +3381,7 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3321
3381
|
async checkPermissionExists(id) {
|
|
3322
3382
|
const permission = await this.permissionRepository.getById(id);
|
|
3323
3383
|
if (!permission) {
|
|
3324
|
-
|
|
3384
|
+
Err8(this.t("errors.notFound"), 404);
|
|
3325
3385
|
}
|
|
3326
3386
|
return permission;
|
|
3327
3387
|
}
|
|
@@ -3331,7 +3391,7 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3331
3391
|
async checkPermissionExistsByName(name) {
|
|
3332
3392
|
const permission = await this.permissionRepository.getByName(name);
|
|
3333
3393
|
if (!permission) {
|
|
3334
|
-
|
|
3394
|
+
Err8(this.t("errors.notFound"), 404);
|
|
3335
3395
|
}
|
|
3336
3396
|
return permission;
|
|
3337
3397
|
}
|
|
@@ -3343,7 +3403,7 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3343
3403
|
return;
|
|
3344
3404
|
const existingPermission = await this.permissionRepository.getByName(name);
|
|
3345
3405
|
if (existingPermission && existingPermission.id !== excludeId) {
|
|
3346
|
-
|
|
3406
|
+
Err8(this.t("errors.nameExists"), 409);
|
|
3347
3407
|
}
|
|
3348
3408
|
}
|
|
3349
3409
|
/**
|
|
@@ -3366,12 +3426,12 @@ var PermissionValidator = class PermissionValidator2 {
|
|
|
3366
3426
|
await this.checkPermissionExists(permissionId);
|
|
3367
3427
|
const hasPermission = await this.permissionRepository.checkRoleHasPermission(roleId, permissionId);
|
|
3368
3428
|
if (hasPermission) {
|
|
3369
|
-
|
|
3429
|
+
Err8(this.t("errors.roleAlreadyHasPermission"), 409);
|
|
3370
3430
|
}
|
|
3371
3431
|
}
|
|
3372
3432
|
};
|
|
3373
3433
|
__decorate20([
|
|
3374
|
-
|
|
3434
|
+
I18n7("permissions"),
|
|
3375
3435
|
__metadata20("design:type", Object)
|
|
3376
3436
|
], PermissionValidator.prototype, "t", void 0);
|
|
3377
3437
|
PermissionValidator = __decorate20([
|
|
@@ -4393,7 +4453,8 @@ var en_default = {
|
|
|
4393
4453
|
unauthorized: "Unauthorized access",
|
|
4394
4454
|
sessionExpired: "Session has expired",
|
|
4395
4455
|
accountLocked: "Account is temporarily locked. Please try again later.",
|
|
4396
|
-
accountInactive: "Account is inactive. Please contact support."
|
|
4456
|
+
accountInactive: "Account is inactive. Please contact support.",
|
|
4457
|
+
emailNotVerified: "Please verify your email address before signing in."
|
|
4397
4458
|
},
|
|
4398
4459
|
success: {
|
|
4399
4460
|
login: "Login successful",
|
|
@@ -4436,7 +4497,9 @@ var en_default = {
|
|
|
4436
4497
|
notFound: "Role not found",
|
|
4437
4498
|
exists: "Role already exists",
|
|
4438
4499
|
nameRequired: "Role name is required",
|
|
4439
|
-
cannotDeleteSystem: "Cannot delete system role"
|
|
4500
|
+
cannotDeleteSystem: "Cannot delete system role",
|
|
4501
|
+
cannotRenameSystem: "Cannot rename the system admin role",
|
|
4502
|
+
roleInUse: "Cannot delete a role that is assigned to users"
|
|
4440
4503
|
},
|
|
4441
4504
|
success: {
|
|
4442
4505
|
created: "Role created successfully",
|
|
@@ -4500,6 +4563,8 @@ var mergeConfig = /* @__PURE__ */ __name((config) => {
|
|
|
4500
4563
|
defaultRole: config?.defaultRole ?? null,
|
|
4501
4564
|
frontendUrl: config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000",
|
|
4502
4565
|
registrationMode: config?.registrationMode ?? "active",
|
|
4566
|
+
requireVerifiedEmail: config?.requireVerifiedEmail ?? false,
|
|
4567
|
+
refreshCookiePath: config?.refreshCookiePath ?? "/",
|
|
4503
4568
|
lockout: {
|
|
4504
4569
|
maxAttempts: config?.lockout?.maxAttempts ?? 5,
|
|
4505
4570
|
duration: config?.lockout?.duration ?? "15m"
|
|
@@ -4513,10 +4578,10 @@ var mergeConfig = /* @__PURE__ */ __name((config) => {
|
|
|
4513
4578
|
}
|
|
4514
4579
|
};
|
|
4515
4580
|
if (!finalConfig.jwt.accessSecret) {
|
|
4516
|
-
throw
|
|
4581
|
+
throw Err9.configRequired("auth", "JWT_ACCESS_SECRET");
|
|
4517
4582
|
}
|
|
4518
4583
|
if (!finalConfig.jwt.refreshSecret) {
|
|
4519
|
-
throw
|
|
4584
|
+
throw Err9.configRequired("auth", "JWT_REFRESH_SECRET");
|
|
4520
4585
|
}
|
|
4521
4586
|
return finalConfig;
|
|
4522
4587
|
}, "mergeConfig");
|
|
@@ -4752,6 +4817,7 @@ export {
|
|
|
4752
4817
|
permissionsTable,
|
|
4753
4818
|
pickProps,
|
|
4754
4819
|
refreshTokenDto,
|
|
4820
|
+
registerDto,
|
|
4755
4821
|
resetPasswordDto,
|
|
4756
4822
|
revokeTokenDto,
|
|
4757
4823
|
roleIdParam,
|