najm-auth 1.1.16 → 1.1.19

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 CHANGED
@@ -198,11 +198,13 @@ class PostController {
198
198
  ```typescript
199
199
  import { defineRoles } from 'najm-auth';
200
200
 
201
- const roles = defineRoles({
202
- ADMIN: 'admin',
203
- MODERATOR: 'moderator',
204
- USER: 'user',
205
- });
201
+ const roles = defineRoles({
202
+ ADMIN: 'admin',
203
+ MODERATOR: 'moderator',
204
+ USER: 'user',
205
+ }, {
206
+ superRoles: ['ADMIN'], // admin also passes moderator/user role guards
207
+ });
206
208
 
207
209
  export const { isAdmin, isModerator, isUser } = roles;
208
210
 
package/dist/index.d.ts CHANGED
@@ -403,7 +403,7 @@ declare class UserValidator {
403
403
  emailVerified: boolean;
404
404
  password: string;
405
405
  image: string;
406
- status: "active" | "inactive" | "pending";
406
+ status: "active" | "pending" | "inactive";
407
407
  roleId: string;
408
408
  lastLogin: string;
409
409
  failedLoginAttempts: number;
@@ -423,7 +423,7 @@ declare class UserValidator {
423
423
  emailVerified: boolean;
424
424
  password: string;
425
425
  image: string;
426
- status: "active" | "inactive" | "pending";
426
+ status: "active" | "pending" | "inactive";
427
427
  roleId: string;
428
428
  lastLogin: string;
429
429
  failedLoginAttempts: number;
@@ -771,8 +771,8 @@ declare const createUserDto: z.ZodObject<{
771
771
  emailVerified: z.ZodDefault<z.ZodBoolean>;
772
772
  status: z.ZodOptional<z.ZodEnum<{
773
773
  active: "active";
774
- inactive: "inactive";
775
774
  pending: "pending";
775
+ inactive: "inactive";
776
776
  }>>;
777
777
  }, z.core.$strip>;
778
778
  declare const updateUserDto: z.ZodObject<{
@@ -784,8 +784,8 @@ declare const updateUserDto: z.ZodObject<{
784
784
  emailVerified: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
785
785
  status: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
786
786
  active: "active";
787
- inactive: "inactive";
788
787
  pending: "pending";
788
+ inactive: "inactive";
789
789
  }>>>;
790
790
  }, z.core.$strip>;
791
791
  declare const userIdParam: z.ZodObject<{
@@ -860,6 +860,13 @@ declare class AuthService {
860
860
  getUserFromCookie(): Promise<SanitizedUser & {
861
861
  language: string;
862
862
  }>;
863
+ /**
864
+ * Get current user — prefer access token (no cookie rotation risk),
865
+ * fall back to cookie when no Authorization header is present.
866
+ */
867
+ getMe(authorization?: string): Promise<SanitizedUser & {
868
+ language: string;
869
+ }>;
863
870
  forgotPassword(email: string): Promise<{
864
871
  message: string;
865
872
  }>;
@@ -887,7 +894,7 @@ declare class AuthController {
887
894
  changePassword(userId: string, body: ChangePasswordDto): Promise<{
888
895
  message: string;
889
896
  }>;
890
- userProfile(): Promise<Omit<{
897
+ userProfile(authorization?: string): Promise<Omit<{
891
898
  id: string;
892
899
  name: string;
893
900
  createdAt: string;
@@ -896,7 +903,7 @@ declare class AuthController {
896
903
  emailVerified: boolean;
897
904
  password: string;
898
905
  image: string;
899
- status: "active" | "inactive" | "pending";
906
+ status: "active" | "pending" | "inactive";
900
907
  roleId: string;
901
908
  lastLogin: string;
902
909
  failedLoginAttempts: number;
@@ -982,6 +989,13 @@ type RoleInput = string | string[];
982
989
  type IsGuards<T extends Record<string, string>> = {
983
990
  [K in keyof T as `is${Capitalize<Lowercase<string & K>>}`]: () => ClassDecorator & MethodDecorator;
984
991
  };
992
+ interface DefineRolesOptions<T extends Record<string, string>> {
993
+ /**
994
+ * Role keys that should implicitly pass every generated role guard, group guard,
995
+ * and service-layer role check created by defineRoles.
996
+ */
997
+ superRoles?: Array<keyof T>;
998
+ }
985
999
  interface DefineRolesResult<T extends Record<string, string>> {
986
1000
  /** The original roles record */
987
1001
  ROLES: T;
@@ -1001,6 +1015,8 @@ interface DefineRolesResult<T extends Record<string, string>> {
1001
1015
  * ADMIN: 'admin',
1002
1016
  * TEACHER: 'teacher',
1003
1017
  * STUDENT: 'student',
1018
+ * }, {
1019
+ * superRoles: ['ADMIN'],
1004
1020
  * });
1005
1021
  *
1006
1022
  * // HTTP guards
@@ -1010,7 +1026,7 @@ interface DefineRolesResult<T extends Record<string, string>> {
1010
1026
  * if (hasRole(user.role, 'ADMIN', 'TEACHER')) { ... }
1011
1027
  * ```
1012
1028
  */
1013
- declare function defineRoles<T extends Record<string, string>>(roles: T): DefineRolesResult<T> & IsGuards<T>;
1029
+ declare function defineRoles<T extends Record<string, string>>(roles: T, options?: DefineRolesOptions<T>): DefineRolesResult<T> & IsGuards<T>;
1014
1030
 
1015
1031
  declare class RoleGuard {
1016
1032
  canActivate(allowedRoles: RoleInput, userRole: string): false | {
@@ -1818,4 +1834,4 @@ declare const authSeed: (config: AuthSeedConfig) => Record<string, SeedEntry>;
1818
1834
  */
1819
1835
  declare function seedAuthData(config: SeedAuthDataConfig): Promise<SeedAuthDataResult>;
1820
1836
 
1821
- export { AUTH_CONFIG, en as AUTH_EN, AUTH_LOCALES, AUTH_MODULE, AUTH_PERMISSIONS, AUTH_ROLE, AUTH_SCHEMA, AUTH_SUPPORTED_LANGUAGES, AUTH_USER, type AssignPermissionDto, type AssignRoleDto, type AssignRoleParams, type AuthConfig, AuthController, AuthGuard, type AuthPluginConfig, AuthQueries, AuthResolver, type AuthSchema, type AuthSeedConfig, AuthService, type AuthUser, Can, CanCreate, CanDelete, CanList, CanRead, CanUpdate, type ChainableGuard, type ChangePasswordDto, type CheckPermissionDto, type ConfiguredOwnership, type ConfirmResetPasswordDto, CookieManager, type CreatePermissionDto, type CreateRoleDto, type CreateTokenDto, type CreateUserDto, type EmailParam, EncryptionService, type JwtConfig, type JwtPayload, type LanguageParam, type LoginDto, NewPermission, NewRoleEntity, NewUser, Owned, type OwnedMethods, type OwnershipConfig, type OwnershipProvider, type OwnershipRule, OwnershipToken, type OwnershipTokenOptions, Permission, PermissionController, PermissionGuard, type PermissionIdParam, PermissionRepository, PermissionService, PermissionValidator, Policy, ROLES, ROLE_GROUPS, type RefreshTokenDto, type ResetPasswordDto, type ResourceAccessor, type ResourceGuards, type ResourceGuardsOptions, type RevokeTokenDto, Role, RoleController, RoleEntity, RoleGuard, type RoleIdParam, type RoleInput, RolePermission, RoleRepository, RoleService, type RoleType, RoleValidator, type SanitizedUser, ScopeContext, type ScopeResult, type SeedAuthDataConfig, type SeedAuthDataResult, type SeedUserConfig, TOKEN_STATUS, TOKEN_TYPE, type TokenIdParam, type TokenPair, TokenRepository, TokenService, USER_STATUS, type UpdatePermissionDto, type UpdateRoleDto, type UpdateTokenDto, type UpdateUserDto, User, UserController, type UserIdInParam, type UserIdParam, UserRepository, UserService, UserValidator, type UserWithPermissions, type VerifyTokenDto, assignPermissionDto, assignRoleDto, assignRoleParams, auth$1 as auth, authSeed, avatarsPath, calculateAge, calculateYearsOfExperience, changePasswordDto, checkPermissionDto, clean, configureOwnership, confirmResetPasswordDto, createPermissionDto, createRoleDto, createTokenDto, createUserDto, defineRoles, emailParam, formatDate, getAuthLocale, getAvatarFile, isAdmin, isAdministrator, isAuth, isEmpty, isFile, isPath, join, languageParam, loginDto, own, parseSchema, permissionIdParam, pickProps, refreshTokenDto, resetPasswordDto, revokeTokenDto, roleIdParam, seedAuthData, setConfiguredCookieName, tokenIdParam, updatePermissionDto, updateRoleDto, updateTokenDto, updateUserDto, userIdInParam, userIdParam, verifyTokenDto, where };
1837
+ export { AUTH_CONFIG, en as AUTH_EN, AUTH_LOCALES, AUTH_MODULE, AUTH_PERMISSIONS, AUTH_ROLE, AUTH_SCHEMA, AUTH_SUPPORTED_LANGUAGES, AUTH_USER, type AssignPermissionDto, type AssignRoleDto, type AssignRoleParams, type AuthConfig, AuthController, AuthGuard, type AuthPluginConfig, AuthQueries, AuthResolver, type AuthSchema, type AuthSeedConfig, AuthService, type AuthUser, Can, CanCreate, CanDelete, CanList, CanRead, CanUpdate, type ChainableGuard, type ChangePasswordDto, type CheckPermissionDto, type ConfiguredOwnership, type ConfirmResetPasswordDto, CookieManager, type CreatePermissionDto, type CreateRoleDto, type CreateTokenDto, type CreateUserDto, type DefineRolesOptions, type EmailParam, EncryptionService, type JwtConfig, type JwtPayload, type LanguageParam, type LoginDto, NewPermission, NewRoleEntity, NewUser, Owned, type OwnedMethods, type OwnershipConfig, type OwnershipProvider, type OwnershipRule, OwnershipToken, type OwnershipTokenOptions, Permission, PermissionController, PermissionGuard, type PermissionIdParam, PermissionRepository, PermissionService, PermissionValidator, Policy, ROLES, ROLE_GROUPS, type RefreshTokenDto, type ResetPasswordDto, type ResourceAccessor, type ResourceGuards, type ResourceGuardsOptions, type RevokeTokenDto, Role, RoleController, RoleEntity, RoleGuard, type RoleIdParam, type RoleInput, RolePermission, RoleRepository, RoleService, type RoleType, RoleValidator, type SanitizedUser, ScopeContext, type ScopeResult, type SeedAuthDataConfig, type SeedAuthDataResult, type SeedUserConfig, TOKEN_STATUS, TOKEN_TYPE, type TokenIdParam, type TokenPair, TokenRepository, TokenService, USER_STATUS, type UpdatePermissionDto, type UpdateRoleDto, type UpdateTokenDto, type UpdateUserDto, User, UserController, type UserIdInParam, type UserIdParam, UserRepository, UserService, UserValidator, type UserWithPermissions, type VerifyTokenDto, assignPermissionDto, assignRoleDto, assignRoleParams, auth$1 as auth, authSeed, avatarsPath, calculateAge, calculateYearsOfExperience, changePasswordDto, checkPermissionDto, clean, configureOwnership, confirmResetPasswordDto, createPermissionDto, createRoleDto, createTokenDto, createUserDto, defineRoles, emailParam, formatDate, getAuthLocale, getAvatarFile, isAdmin, isAdministrator, isAuth, isEmpty, isFile, isPath, join, languageParam, loginDto, own, parseSchema, permissionIdParam, pickProps, refreshTokenDto, resetPasswordDto, revokeTokenDto, roleIdParam, seedAuthData, setConfiguredCookieName, tokenIdParam, updatePermissionDto, updateRoleDto, updateTokenDto, updateUserDto, userIdInParam, userIdParam, verifyTokenDto, where };
package/dist/index.js CHANGED
@@ -32,9 +32,9 @@ var baseFields = /* @__PURE__ */ __name((idLength = 5) => ({
32
32
  createdAt: timestamp("created_at", { mode: "string" }).defaultNow(),
33
33
  updatedAt: timestamp("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql`CURRENT_TIMESTAMP`)
34
34
  }), "baseFields");
35
- var userStatusEnum = pgEnum("user_status", USER_STATUS);
36
- var tokenStatusEnum = pgEnum("token_status", TOKEN_STATUS);
37
- var tokenTypeEnum = pgEnum("token_type", TOKEN_TYPE);
35
+ var userStatusEnum = pgEnum("userStatus", USER_STATUS);
36
+ var tokenStatusEnum = pgEnum("tokenStatus", TOKEN_STATUS);
37
+ var tokenTypeEnum = pgEnum("tokenType", TOKEN_TYPE);
38
38
  var rolesTable = pgTable("roles", {
39
39
  ...baseFields(5),
40
40
  name: text("name").notNull(),
@@ -1758,6 +1758,20 @@ var AuthService = class AuthService2 {
1758
1758
  const lang = this.i18nService.getCurrentLanguage();
1759
1759
  return { ...user, language: lang };
1760
1760
  }
1761
+ /**
1762
+ * Get current user — prefer access token (no cookie rotation risk),
1763
+ * fall back to cookie when no Authorization header is present.
1764
+ */
1765
+ async getMe(authorization) {
1766
+ if (authorization) {
1767
+ const user = await this.tokenService.getUser(authorization);
1768
+ if (user) {
1769
+ const lang = this.i18nService.getCurrentLanguage();
1770
+ return { ...user, language: lang };
1771
+ }
1772
+ }
1773
+ return this.getUserFromCookie();
1774
+ }
1761
1775
  async forgotPassword(email2) {
1762
1776
  const user = await this.userService.findByEmail(email2);
1763
1777
  if (user) {
@@ -1966,8 +1980,8 @@ var AuthController = class AuthController2 {
1966
1980
  async changePassword(userId, body) {
1967
1981
  return this.authService.changePassword(userId, body.currentPassword, body.newPassword);
1968
1982
  }
1969
- async userProfile() {
1970
- return this.authService.getUserFromCookie();
1983
+ async userProfile(authorization) {
1984
+ return this.authService.getMe(authorization);
1971
1985
  }
1972
1986
  async forgotPassword(body) {
1973
1987
  return this.authService.forgotPassword(body.email);
@@ -2029,8 +2043,9 @@ __decorate13([
2029
2043
  Get("/me"),
2030
2044
  RateLimit({ limit: 30, window: "1m", key: cookieFingerprint() }),
2031
2045
  ResMsg("auth.users.success.retrieved"),
2046
+ __param3(0, Headers("authorization")),
2032
2047
  __metadata13("design:type", Function),
2033
- __metadata13("design:paramtypes", []),
2048
+ __metadata13("design:paramtypes", [String]),
2034
2049
  __metadata13("design:returntype", Promise)
2035
2050
  ], AuthController.prototype, "userProfile", null);
2036
2051
  __decorate13([
@@ -2299,15 +2314,21 @@ var isAdministrator = composeGuards(isAuth(), Role(ROLE_GROUPS.ADMINISTRATORS));
2299
2314
 
2300
2315
  // src/roles/defineRoles.ts
2301
2316
  var Role2 = createGuard3(RoleGuard);
2302
- function defineRoles(roles) {
2317
+ function defineRoles(roles, options) {
2303
2318
  const ROLES2 = roles;
2319
+ const superRoleKeys = options?.superRoles ?? [];
2320
+ function resolveRoleValues(keys) {
2321
+ return Array.from(new Set([...keys, ...superRoleKeys].map((key) => roles[key])));
2322
+ }
2323
+ __name(resolveRoleValues, "resolveRoleValues");
2304
2324
  const guards2 = {};
2305
2325
  for (const [key, value] of Object.entries(roles)) {
2306
2326
  const name = `is${key.charAt(0).toUpperCase()}${key.slice(1).toLowerCase()}`;
2307
- guards2[name] = composeGuards2(isAuth(), Role2(value));
2327
+ const allowedValues = resolveRoleValues([key]);
2328
+ guards2[name] = composeGuards2(isAuth(), Role2(allowedValues.length === 1 ? value : allowedValues));
2308
2329
  }
2309
2330
  function createGroupGuard(keys) {
2310
- const values = keys.map((k) => roles[k]);
2331
+ const values = resolveRoleValues(keys);
2311
2332
  return composeGuards2(isAuth(), Role2(values));
2312
2333
  }
2313
2334
  __name(createGroupGuard, "createGroupGuard");
@@ -2315,7 +2336,7 @@ function defineRoles(roles) {
2315
2336
  if (!userRole)
2316
2337
  return false;
2317
2338
  const normalized = userRole.toLowerCase();
2318
- return keys.some((k) => roles[k] === normalized);
2339
+ return resolveRoleValues(keys).some((role) => role === normalized);
2319
2340
  }
2320
2341
  __name(hasRole, "hasRole");
2321
2342
  function isInGroup(userRole, keys) {
@@ -198,7 +198,7 @@ declare const usersTable: drizzle_orm_mysql_core.MySqlTableWithColumns<{
198
198
  tableName: "users";
199
199
  dataType: "string";
200
200
  columnType: "MySqlEnumColumn";
201
- data: "active" | "inactive" | "pending";
201
+ data: "active" | "pending" | "inactive";
202
202
  driverParam: string;
203
203
  notNull: false;
204
204
  hasDefault: true;
@@ -780,7 +780,7 @@ declare const authSchema: {
780
780
  tableName: "users";
781
781
  dataType: "string";
782
782
  columnType: "MySqlEnumColumn";
783
- data: "active" | "inactive" | "pending";
783
+ data: "active" | "pending" | "inactive";
784
784
  driverParam: string;
785
785
  notNull: false;
786
786
  hasDefault: true;
@@ -201,7 +201,7 @@ declare const usersTable: drizzle_orm_pg_core.PgTableWithColumns<{
201
201
  tableName: "users";
202
202
  dataType: "string";
203
203
  columnType: "PgEnumColumn";
204
- data: "active" | "inactive" | "pending";
204
+ data: "active" | "pending" | "inactive";
205
205
  driverParam: string;
206
206
  notNull: false;
207
207
  hasDefault: true;
@@ -783,7 +783,7 @@ declare const authSchema: {
783
783
  tableName: "users";
784
784
  dataType: "string";
785
785
  columnType: "PgEnumColumn";
786
- data: "active" | "inactive" | "pending";
786
+ data: "active" | "pending" | "inactive";
787
787
  driverParam: string;
788
788
  notNull: false;
789
789
  hasDefault: true;
package/dist/schema/pg.js CHANGED
@@ -17,9 +17,9 @@ var baseFields = /* @__PURE__ */ __name((idLength = 5) => ({
17
17
  createdAt: timestamp("created_at", { mode: "string" }).defaultNow(),
18
18
  updatedAt: timestamp("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql`CURRENT_TIMESTAMP`)
19
19
  }), "baseFields");
20
- var userStatusEnum = pgEnum("user_status", USER_STATUS);
21
- var tokenStatusEnum = pgEnum("token_status", TOKEN_STATUS);
22
- var tokenTypeEnum = pgEnum("token_type", TOKEN_TYPE);
20
+ var userStatusEnum = pgEnum("userStatus", USER_STATUS);
21
+ var tokenStatusEnum = pgEnum("tokenStatus", TOKEN_STATUS);
22
+ var tokenTypeEnum = pgEnum("tokenType", TOKEN_TYPE);
23
23
  var rolesTable = pgTable("roles", {
24
24
  ...baseFields(5),
25
25
  name: text("name").notNull(),
@@ -216,7 +216,7 @@ declare const usersTable: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
216
216
  tableName: "users";
217
217
  dataType: "string";
218
218
  columnType: "SQLiteText";
219
- data: "active" | "inactive" | "pending";
219
+ data: "active" | "pending" | "inactive";
220
220
  driverParam: string;
221
221
  notNull: false;
222
222
  hasDefault: true;
@@ -229,7 +229,7 @@ declare const usersTable: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
229
229
  generated: undefined;
230
230
  }, {}, {
231
231
  length: number;
232
- $type: "active" | "inactive" | "pending";
232
+ $type: "active" | "pending" | "inactive";
233
233
  }>;
234
234
  roleId: drizzle_orm_sqlite_core.SQLiteColumn<{
235
235
  name: "role_id";
@@ -899,7 +899,7 @@ declare const authSchema: {
899
899
  tableName: "users";
900
900
  dataType: "string";
901
901
  columnType: "SQLiteText";
902
- data: "active" | "inactive" | "pending";
902
+ data: "active" | "pending" | "inactive";
903
903
  driverParam: string;
904
904
  notNull: false;
905
905
  hasDefault: true;
@@ -912,7 +912,7 @@ declare const authSchema: {
912
912
  generated: undefined;
913
913
  }, {}, {
914
914
  length: number;
915
- $type: "active" | "inactive" | "pending";
915
+ $type: "active" | "pending" | "inactive";
916
916
  }>;
917
917
  roleId: drizzle_orm_sqlite_core.SQLiteColumn<{
918
918
  name: "role_id";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-auth",
3
- "version": "1.1.16",
3
+ "version": "1.1.19",
4
4
  "description": "Authentication and authorization library for najm framework",
5
5
  "type": "module",
6
6
  "files": [