najm-auth 4.1.0 → 4.2.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 CHANGED
@@ -220,7 +220,8 @@ All routes are prefixed with `/auth` and auto-registered by the plugin.
220
220
  Applications with an approval-owned onboarding flow should set
221
221
  `publicRegistration: false`. This removes the unauthenticated route while
222
222
  retaining `AuthService.registerUser()`, `provisionUser()`, and other internal
223
- account-management APIs for trusted application services.
223
+ account-management APIs for trusted application services. The registration
224
+ controller also answers 404 when disabled if an older core mounts it anyway.
224
225
 
225
226
  ### Identity presets
226
227
 
@@ -561,6 +562,36 @@ export class ProductRepository {
561
562
 
562
563
  ### Composable ownership (4.1+)
563
564
 
565
+ For custom queries, the property form puts the rules and type together:
566
+
567
+ ```typescript
568
+ import { Owned, type OwnedWhere } from 'najm-auth';
569
+
570
+ @Repository('default')
571
+ export class ProductRepository {
572
+ @DB() db!: Database;
573
+
574
+ @Owned(Product, SharedProduct)
575
+ private ownedWhere!: OwnedWhere;
576
+
577
+ async getById(id: string) {
578
+ const [row] = await this.db.select().from(products)
579
+ .where(and(this.ownedWhere(), eq(products.id, id))).limit(1);
580
+ return row ?? null;
581
+ }
582
+ }
583
+ ```
584
+
585
+ Use any instance property name; `OwnedWhere` is the shared function type.
586
+ Resolve the repository through Najm's container before calling it. Context
587
+ injection installs the function after construction, including when TypeScript
588
+ emits native class fields. The function reads the current request on every call,
589
+ so a singleton repository can safely serve different actors. Multiple decorated
590
+ properties may use independent rules, including on inherited repositories.
591
+ The class form and its `ownershipCondition`, `findMany`, `findOne`, and
592
+ `scopedQuery` helpers remain available. The property form supplies only the
593
+ decorated predicate; it does not rewrite queries or add CRUD helpers.
594
+
564
595
  `@Owned(Product)` now provides `ownershipCondition()` for custom queries.
565
596
  It returns a parameterized `id IN (authorized IDs)` predicate; join-based rules
566
597
  do not multiply outer rows. Combine it with filters in one
package/dist/index.d.ts CHANGED
@@ -2170,6 +2170,7 @@ declare class AuthIdentityContextService {
2170
2170
  */
2171
2171
  declare class RegistrationController {
2172
2172
  private authService;
2173
+ private config;
2173
2174
  constructor(authService: AuthService);
2174
2175
  registerUser(body: RegisterDto): Promise<SanitizedUser>;
2175
2176
  }
@@ -2856,8 +2857,11 @@ declare class ScopeContext {
2856
2857
  role: string;
2857
2858
  } | null;
2858
2859
  }
2859
- declare function Owned(token: OwnershipToken, ...alternatives: OwnershipToken[]): (target: Function) => void;
2860
+ /** Decorate a repository class, or an `ownedWhere!: OwnedWhere` property. */
2861
+ declare function Owned(token: OwnershipToken, ...alternatives: OwnershipToken[]): ClassDecorator & PropertyDecorator;
2860
2862
 
2863
+ /** Request-aware ownership predicate supplied by an @Owned property. */
2864
+ type OwnedWhere = () => SQL | undefined;
2861
2865
  /** Request context consumed by ownershipCondition; ScopeContext implements it. */
2862
2866
  interface OwnershipReadContext {
2863
2867
  hasActiveContext(): boolean;
@@ -3203,4 +3207,4 @@ declare const authSeed: (config: AuthSeedConfig) => Record<string, SeedEntry>;
3203
3207
  */
3204
3208
  declare function seedAuthData(config: SeedAuthDataConfig): Promise<SeedAuthDataResult>;
3205
3209
 
3206
- export { AUTH_CONFIG, AUTH_CORE_MODULE, en as AUTH_EN, AUTH_LOCALES, AUTH_LOGIN_RATE_LIMIT_ENV, AUTH_MODULE, AUTH_PERMISSIONS, AUTH_ROLE, AUTH_SCHEMA, AUTH_SUPPORTED_LANGUAGES, AUTH_USER, type AdministrativeDelivery, type AssignPermissionDto, type AssignRoleDto, type AssignRoleParams, type AuthConfig, AuthController, AuthGuard, type AuthLoginRateLimitConfig, type AuthPluginConfig, AuthQueries, type AuthRateLimitEnvironment, AuthResolver, type AuthSchema, type AuthSeedConfig, AuthService, AuthSessionService, type AuthUser, CREDENTIAL_SETUP_CODES, CREDENTIAL_SETUP_MODULE, Can, CanCreate, CanDelete, CanList, CanRead, CanUpdate, type ChainableGuard, type ChangePasswordDto, type CheckPermissionDto, type ConfiguredOwnership, type ConfirmResetPasswordDto, type ConsumedSetPasswordToken, CookieManager, type CreatePermissionDto, type CreateRoleDto, type CreateTokenDto, type CreateUserDto, type CredentialSetupChangeDto, type CredentialSetupCode, type CredentialSetupConfig, CredentialSetupController, type CredentialSetupOptions, type CredentialSetupPasswordOptions, type CredentialSetupPending, CredentialSetupRepository, CredentialSetupRequirementRepository, type CredentialSetupRequirementRow, CredentialSetupRequirementService, CredentialSetupService, type CredentialSetupSessionInfo, type CredentialSetupStarted, DEFAULT_AUTH_LOGIN_RATE_LIMIT, DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME, DEFAULT_CREDENTIAL_SETUP_TTL_MS, type DefineRolesOptions, type EmailParam, EncryptionService, type GitHubOAuthConfig, type GoogleOAuthConfig, IdentityConfig, type IdentityResolver, type InviteUserDto, type JwtConfig, type JwtPayload, type LanguageParam, type LoginDto, type LoginResult, NewPermission, NewRoleEntity, NewUser, type OAuthConfig, type OAuthProvider, Owned, type OwnedMethods, type OwnershipConditionMethods, type OwnershipConfig, type OwnershipProvider, type OwnershipReadContext, type OwnershipRule, OwnershipToken, type OwnershipTokenOptions, PASSWORD_SETUP_PURPOSE, PUBLIC_REGISTRATION_MODULE, PasswordSetupService, Permission, PermissionController, PermissionGuard, type PermissionIdParam, PermissionRepository, PermissionService, PermissionValidator, Policy, type ProvisionUserInput, type ProvisionUserWithPasswordInput, type ProvisionUserWithSetupInput, ROLES, ROLE_GROUPS, type RefreshTokenDto, type RegisterDto, RegistrationController, type ResetPasswordDto, type ResolvedCredentialSetupConfig, ResolvedIdentityConfig, type ResourceAccessor, type ResourceGuards, type ResourceGuardsOptions, type RevokeTokenDto, Role, RoleController, RoleEntity, RoleGuard, type RoleIdParam, type RoleInput, RolePermission, RoleRepository, RoleService, type RoleType, RoleValidator, type RunAsUser, type SanitizedUser, ScopeContext, type ScopeResult, type SeedAuthDataConfig, type SeedAuthDataResult, type SeedUserConfig, type SessionCookieData, SessionInvalidationService, type SetPasswordToken, type SetPasswordTokenType, TOKEN_STATUS, TOKEN_TYPE, TemporaryCredentialInput, type TemporaryCredentialReset, type TokenIdParam, type TokenPair, TokenRepository, TokenService, USER_STATUS, type UpdatePermissionDto, type UpdateRoleDto, type UpdateTokenDto, type UpdateUserDto, User, UserController, type UserIdInParam, type UserIdParam, type UserListQuery, UserRepository, UserService, UserValidator, type UserWithPermissions, type VerifyTokenDto, assignPermissionDto, assignRoleDto, assignRoleParams, auth$1 as auth, authEmailRateLimitKey, authIdentityRateLimitKey, authSeed, avatarsPath, calculateAge, calculateYearsOfExperience, changePasswordDto, checkPermissionDto, clean, configureOwnership, confirmResetPasswordDto, createIdentityResolver, createPermissionDto, createRoleDto, createTokenDto, createUserDto, credentialSetupChangeDto, credentialSetupError, defaultCredentialSetupPasswordSchema, defineRoles, emailParam, formatDate, getAuthLocale, getAvatarFile, inviteUserDto, isAdmin, isAdministrator, isAuth, isEmailIdentifier, isEmpty, isFile, isPath, join, languageParam, loginDto, normalizeAuthIdentifier, normalizeSetupPurpose, own, ownershipCondition, parseSchema, permissionIdParam, pickProps, refreshTokenDto, registerDto, resetPasswordDto, resolveAuthLoginRateLimitConfig, revokeTokenDto, roleIdParam, runAsUser, seedAuthData, tokenIdParam, updatePermissionDto, updateRoleDto, updateTokenDto, updateUserDto, userIdInParam, userIdParam, userListQuery, verifyTokenDto, where };
3210
+ export { AUTH_CONFIG, AUTH_CORE_MODULE, en as AUTH_EN, AUTH_LOCALES, AUTH_LOGIN_RATE_LIMIT_ENV, AUTH_MODULE, AUTH_PERMISSIONS, AUTH_ROLE, AUTH_SCHEMA, AUTH_SUPPORTED_LANGUAGES, AUTH_USER, type AdministrativeDelivery, type AssignPermissionDto, type AssignRoleDto, type AssignRoleParams, type AuthConfig, AuthController, AuthGuard, type AuthLoginRateLimitConfig, type AuthPluginConfig, AuthQueries, type AuthRateLimitEnvironment, AuthResolver, type AuthSchema, type AuthSeedConfig, AuthService, AuthSessionService, type AuthUser, CREDENTIAL_SETUP_CODES, CREDENTIAL_SETUP_MODULE, Can, CanCreate, CanDelete, CanList, CanRead, CanUpdate, type ChainableGuard, type ChangePasswordDto, type CheckPermissionDto, type ConfiguredOwnership, type ConfirmResetPasswordDto, type ConsumedSetPasswordToken, CookieManager, type CreatePermissionDto, type CreateRoleDto, type CreateTokenDto, type CreateUserDto, type CredentialSetupChangeDto, type CredentialSetupCode, type CredentialSetupConfig, CredentialSetupController, type CredentialSetupOptions, type CredentialSetupPasswordOptions, type CredentialSetupPending, CredentialSetupRepository, CredentialSetupRequirementRepository, type CredentialSetupRequirementRow, CredentialSetupRequirementService, CredentialSetupService, type CredentialSetupSessionInfo, type CredentialSetupStarted, DEFAULT_AUTH_LOGIN_RATE_LIMIT, DEFAULT_CREDENTIAL_SETUP_COOKIE_NAME, DEFAULT_CREDENTIAL_SETUP_TTL_MS, type DefineRolesOptions, type EmailParam, EncryptionService, type GitHubOAuthConfig, type GoogleOAuthConfig, IdentityConfig, type IdentityResolver, type InviteUserDto, type JwtConfig, type JwtPayload, type LanguageParam, type LoginDto, type LoginResult, NewPermission, NewRoleEntity, NewUser, type OAuthConfig, type OAuthProvider, Owned, type OwnedMethods, type OwnedWhere, type OwnershipConditionMethods, type OwnershipConfig, type OwnershipProvider, type OwnershipReadContext, type OwnershipRule, OwnershipToken, type OwnershipTokenOptions, PASSWORD_SETUP_PURPOSE, PUBLIC_REGISTRATION_MODULE, PasswordSetupService, Permission, PermissionController, PermissionGuard, type PermissionIdParam, PermissionRepository, PermissionService, PermissionValidator, Policy, type ProvisionUserInput, type ProvisionUserWithPasswordInput, type ProvisionUserWithSetupInput, ROLES, ROLE_GROUPS, type RefreshTokenDto, type RegisterDto, RegistrationController, type ResetPasswordDto, type ResolvedCredentialSetupConfig, ResolvedIdentityConfig, type ResourceAccessor, type ResourceGuards, type ResourceGuardsOptions, type RevokeTokenDto, Role, RoleController, RoleEntity, RoleGuard, type RoleIdParam, type RoleInput, RolePermission, RoleRepository, RoleService, type RoleType, RoleValidator, type RunAsUser, type SanitizedUser, ScopeContext, type ScopeResult, type SeedAuthDataConfig, type SeedAuthDataResult, type SeedUserConfig, type SessionCookieData, SessionInvalidationService, type SetPasswordToken, type SetPasswordTokenType, TOKEN_STATUS, TOKEN_TYPE, TemporaryCredentialInput, type TemporaryCredentialReset, type TokenIdParam, type TokenPair, TokenRepository, TokenService, USER_STATUS, type UpdatePermissionDto, type UpdateRoleDto, type UpdateTokenDto, type UpdateUserDto, User, UserController, type UserIdInParam, type UserIdParam, type UserListQuery, UserRepository, UserService, UserValidator, type UserWithPermissions, type VerifyTokenDto, assignPermissionDto, assignRoleDto, assignRoleParams, auth$1 as auth, authEmailRateLimitKey, authIdentityRateLimitKey, authSeed, avatarsPath, calculateAge, calculateYearsOfExperience, changePasswordDto, checkPermissionDto, clean, configureOwnership, confirmResetPasswordDto, createIdentityResolver, createPermissionDto, createRoleDto, createTokenDto, createUserDto, credentialSetupChangeDto, credentialSetupError, defaultCredentialSetupPasswordSchema, defineRoles, emailParam, formatDate, getAuthLocale, getAvatarFile, inviteUserDto, isAdmin, isAdministrator, isAuth, isEmailIdentifier, isEmpty, isFile, isPath, join, languageParam, loginDto, normalizeAuthIdentifier, normalizeSetupPurpose, own, ownershipCondition, parseSchema, permissionIdParam, pickProps, refreshTokenDto, registerDto, resetPasswordDto, resolveAuthLoginRateLimitConfig, revokeTokenDto, roleIdParam, runAsUser, seedAuthData, tokenIdParam, updatePermissionDto, updateRoleDto, updateTokenDto, updateUserDto, userIdInParam, userIdParam, userListQuery, verifyTokenDto, where };
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 Err16, plugin } from "najm-core";
9
+ import { Err as Err17, plugin } from "najm-core";
10
10
  import { cache } from "najm-cache";
11
11
 
12
12
  // src/auth.tokens.ts
@@ -4194,6 +4194,7 @@ var isAdmin = composeGuards(isAuth(), Role(ROLES.ADMIN));
4194
4194
  var isAdministrator = composeGuards(isAuth(), Role(ROLE_GROUPS.ADMINISTRATORS));
4195
4195
 
4196
4196
  // src/auth/AuthController.ts
4197
+ import { Public } from "najm-guard";
4197
4198
  import { Validate } from "najm-validation";
4198
4199
  import { RateLimit, UNRESOLVED_CLIENT_ADDRESS } from "najm-rate";
4199
4200
  import { createHash as createHash3 } from "crypto";
@@ -4447,6 +4448,7 @@ var AuthController = class AuthController2 {
4447
4448
  };
4448
4449
  __decorate21([
4449
4450
  Post("/login"),
4451
+ Public(),
4450
4452
  RateLimit({
4451
4453
  limit: loginRateLimit.limit,
4452
4454
  window: loginRateLimit.window,
@@ -4474,6 +4476,7 @@ __decorate21([
4474
4476
  ], AuthController.prototype, "inviteUser", null);
4475
4477
  __decorate21([
4476
4478
  Post("/refresh"),
4479
+ Public(),
4477
4480
  RateLimit({ limit: 15, window: "15m", key: cookieFingerprint() }),
4478
4481
  ResMsg("auth.success.tokenRefreshed"),
4479
4482
  __metadata21("design:type", Function),
@@ -4482,6 +4485,7 @@ __decorate21([
4482
4485
  ], AuthController.prototype, "refreshTokens", null);
4483
4486
  __decorate21([
4484
4487
  Post("/session/recover"),
4488
+ Public(),
4485
4489
  RateLimit({ limit: 120, window: "1m", key: cookieFingerprint() }),
4486
4490
  ResMsg("auth.success.sessionRecovered"),
4487
4491
  __param5(0, Headers("x-najm-session-recovery")),
@@ -4492,6 +4496,7 @@ __decorate21([
4492
4496
  ], AuthController.prototype, "recoverSession", null);
4493
4497
  __decorate21([
4494
4498
  Post("/logout"),
4499
+ Public(),
4495
4500
  __param5(0, User2("id")),
4496
4501
  __param5(1, Headers("authorization")),
4497
4502
  __metadata21("design:type", Function),
@@ -4511,6 +4516,7 @@ __decorate21([
4511
4516
  ], AuthController.prototype, "changePassword", null);
4512
4517
  __decorate21([
4513
4518
  Get("/me"),
4519
+ Public(),
4514
4520
  RateLimit({ limit: 30, window: "1m", key: cookieFingerprint() }),
4515
4521
  ResMsg("auth.users.success.retrieved"),
4516
4522
  __param5(0, Headers("authorization")),
@@ -4520,6 +4526,7 @@ __decorate21([
4520
4526
  ], AuthController.prototype, "userProfile", null);
4521
4527
  __decorate21([
4522
4528
  Post("/forgot-password"),
4529
+ Public(),
4523
4530
  RateLimit({ limit: 3, window: "15m", key: authEmailRateLimitKey, message: "Too many password reset requests. Please try again later." }),
4524
4531
  Validate(resetPasswordDto),
4525
4532
  ResMsg("auth.success.passwordResetSent"),
@@ -4530,6 +4537,7 @@ __decorate21([
4530
4537
  ], AuthController.prototype, "forgotPassword", null);
4531
4538
  __decorate21([
4532
4539
  Post("/reset-password"),
4540
+ Public(),
4533
4541
  RateLimit({ limit: 5, window: "15m", key: "ip", message: "Too many password reset attempts. Please try again later." }),
4534
4542
  Validate(confirmResetPasswordDto),
4535
4543
  ResMsg("auth.success.passwordReset"),
@@ -4744,8 +4752,9 @@ AuthIdentityContextService = __decorate23([
4744
4752
  ], AuthIdentityContextService);
4745
4753
 
4746
4754
  // src/auth/RegistrationController.ts
4747
- import { Body as Body2, Controller as Controller2, Post as Post2, ResMsg as ResMsg2 } from "najm-core";
4755
+ import { Body as Body2, Controller as Controller2, Err as Err14, Inject as Inject15, Post as Post2, ResMsg as ResMsg2 } from "najm-core";
4748
4756
  import { RateLimit as RateLimit2 } from "najm-rate";
4757
+ import { Public as Public2 } from "najm-guard";
4749
4758
  import { Validate as Validate2 } from "najm-validation";
4750
4759
  var __decorate24 = function(decorators, target, key, desc) {
4751
4760
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -4767,15 +4776,23 @@ var RegistrationController = class RegistrationController2 {
4767
4776
  __name(this, "RegistrationController");
4768
4777
  }
4769
4778
  authService;
4779
+ config;
4770
4780
  constructor(authService) {
4771
4781
  this.authService = authService;
4772
4782
  }
4773
4783
  async registerUser(body) {
4784
+ if (this.config.publicRegistration === false)
4785
+ Err14("Not Found", 404);
4774
4786
  return this.authService.registerUser(body);
4775
4787
  }
4776
4788
  };
4789
+ __decorate24([
4790
+ Inject15(AUTH_CONFIG),
4791
+ __metadata24("design:type", Object)
4792
+ ], RegistrationController.prototype, "config", void 0);
4777
4793
  __decorate24([
4778
4794
  Post2("/register"),
4795
+ Public2(),
4779
4796
  RateLimit2({ limit: 5, window: "15m", key: authEmailRateLimitKey }),
4780
4797
  Validate2(registerDto),
4781
4798
  ResMsg2("auth.success.register"),
@@ -5239,7 +5256,7 @@ __export(permissions_exports, {
5239
5256
 
5240
5257
  // src/permissions/PermissionRepository.ts
5241
5258
  import { eq as eq7, and as and4 } from "drizzle-orm";
5242
- import { Repository as Repository6, Inject as Inject15 } from "najm-core";
5259
+ import { Repository as Repository6, Inject as Inject16 } from "najm-core";
5243
5260
  import { DB as DB6 } from "najm-database";
5244
5261
  var __decorate27 = function(decorators, target, key, desc) {
5245
5262
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -5330,7 +5347,7 @@ __decorate27([
5330
5347
  __metadata27("design:type", Object)
5331
5348
  ], PermissionRepository.prototype, "db", void 0);
5332
5349
  __decorate27([
5333
- Inject15(AUTH_SCHEMA),
5350
+ Inject16(AUTH_SCHEMA),
5334
5351
  __metadata27("design:type", Object)
5335
5352
  ], PermissionRepository.prototype, "schema", void 0);
5336
5353
  PermissionRepository = __decorate27([
@@ -5407,7 +5424,7 @@ import { Injectable as Injectable15 } from "najm-core";
5407
5424
  // src/permissions/PermissionValidator.ts
5408
5425
  import { Injectable as Injectable14 } from "najm-core";
5409
5426
  import { I18n as I18n9 } from "najm-i18n";
5410
- import { Err as Err14 } from "najm-core";
5427
+ import { Err as Err15 } from "najm-core";
5411
5428
  var __decorate29 = function(decorators, target, key, desc) {
5412
5429
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5413
5430
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -5436,7 +5453,7 @@ var PermissionValidator = class PermissionValidator2 {
5436
5453
  async checkPermissionExists(id) {
5437
5454
  const permission = await this.permissionRepository.getById(id);
5438
5455
  if (!permission) {
5439
- Err14(this.t("errors.notFound"), 404);
5456
+ Err15(this.t("errors.notFound"), 404);
5440
5457
  }
5441
5458
  return permission;
5442
5459
  }
@@ -5446,7 +5463,7 @@ var PermissionValidator = class PermissionValidator2 {
5446
5463
  async checkPermissionExistsByName(name) {
5447
5464
  const permission = await this.permissionRepository.getByName(name);
5448
5465
  if (!permission) {
5449
- Err14(this.t("errors.notFound"), 404);
5466
+ Err15(this.t("errors.notFound"), 404);
5450
5467
  }
5451
5468
  return permission;
5452
5469
  }
@@ -5458,7 +5475,7 @@ var PermissionValidator = class PermissionValidator2 {
5458
5475
  return;
5459
5476
  const existingPermission = await this.permissionRepository.getByName(name);
5460
5477
  if (existingPermission && existingPermission.id !== excludeId) {
5461
- Err14(this.t("errors.nameExists"), 409);
5478
+ Err15(this.t("errors.nameExists"), 409);
5462
5479
  }
5463
5480
  }
5464
5481
  /**
@@ -5481,7 +5498,7 @@ var PermissionValidator = class PermissionValidator2 {
5481
5498
  await this.checkPermissionExists(permissionId);
5482
5499
  const hasPermission = await this.permissionRepository.checkRoleHasPermission(roleId, permissionId);
5483
5500
  if (hasPermission) {
5484
- Err14(this.t("errors.roleAlreadyHasPermission"), 409);
5501
+ Err15(this.t("errors.roleAlreadyHasPermission"), 409);
5485
5502
  }
5486
5503
  }
5487
5504
  };
@@ -6034,7 +6051,7 @@ function own(table, opts) {
6034
6051
  __name(own, "own");
6035
6052
 
6036
6053
  // src/ownership/configureOwnership.ts
6037
- import { Injectable as Injectable16, Inject as Inject16, User as User4, Body as Body6, Params as Params4 } from "najm-core";
6054
+ import { Injectable as Injectable16, Inject as Inject17, User as User4, Body as Body6, Params as Params4 } from "najm-core";
6038
6055
  import { createGuard as createGuard5, composeGuards as composeGuards4 } from "najm-guard";
6039
6056
  var __decorate32 = function(decorators, target, key, desc) {
6040
6057
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -6075,7 +6092,7 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
6075
6092
  }
6076
6093
  };
6077
6094
  __decorate32([
6078
- Inject16(ownershipClass),
6095
+ Inject17(ownershipClass),
6079
6096
  __metadata32("design:type", Object)
6080
6097
  ], AccessGuard.prototype, "ownership", void 0);
6081
6098
  __decorate32([
@@ -6099,7 +6116,7 @@ function createResourceGuards(ownershipClass, resourceType, resource, options) {
6099
6116
  }
6100
6117
  };
6101
6118
  __decorate32([
6102
- Inject16(ownershipClass),
6119
+ Inject17(ownershipClass),
6103
6120
  __metadata32("design:type", Object)
6104
6121
  ], ListGuard.prototype, "ownership", void 0);
6105
6122
  __decorate32([
@@ -6258,7 +6275,7 @@ function configureOwnership(config) {
6258
6275
  }
6259
6276
  };
6260
6277
  __decorate32([
6261
- Inject16(GeneratedOwnershipService),
6278
+ Inject17(GeneratedOwnershipService),
6262
6279
  __metadata32("design:type", GeneratedOwnershipService)
6263
6280
  ], BodyAccessGuard.prototype, "ownership", void 0);
6264
6281
  __decorate32([
@@ -6384,7 +6401,7 @@ __name(Policy, "Policy");
6384
6401
  // src/ownership/OwnedDecorator.ts
6385
6402
  import "reflect-metadata";
6386
6403
  import { sql as sql6, and as and5 } from "drizzle-orm";
6387
- import { Injectable as Injectable17, Inject as Inject17, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
6404
+ import { Injectable as Injectable17, Inject as Inject18, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
6388
6405
  import { USER as USER2 } from "najm-guard";
6389
6406
 
6390
6407
  // src/ownership/ownershipCondition.ts
@@ -6435,6 +6452,43 @@ var __metadata33 = function(k, v) {
6435
6452
  };
6436
6453
  var _a21;
6437
6454
  var OWNED_META = Symbol.for("najm:owned");
6455
+ var OWNED_PROPERTIES = Symbol.for("najm:owned-properties");
6456
+ var propertyContexts = /* @__PURE__ */ new WeakMap();
6457
+ function ownedProperty(proto, key, tokens) {
6458
+ const inherited = Reflect.getMetadata(OWNED_PROPERTIES, proto) ?? [];
6459
+ const properties = [...inherited.filter((property) => property.key !== key), { key, tokens }];
6460
+ Reflect.defineMetadata(OWNED_PROPERTIES, properties, proto);
6461
+ Object.defineProperty(proto, key, {
6462
+ value() {
6463
+ return ownershipCondition(this.db, tokens, this._scopeCtx);
6464
+ },
6465
+ configurable: true,
6466
+ enumerable: false
6467
+ });
6468
+ if (!Reflect.hasOwnMetadata(OWNED_PROPERTIES, proto, "_scopeCtx")) {
6469
+ Inject18(ScopeContext)(proto, "_scopeCtx");
6470
+ Reflect.defineMetadata(OWNED_PROPERTIES, true, proto, "_scopeCtx");
6471
+ Object.defineProperty(proto, "_scopeCtx", {
6472
+ get() {
6473
+ return propertyContexts.get(this);
6474
+ },
6475
+ set(context) {
6476
+ propertyContexts.set(this, context);
6477
+ const properties2 = Reflect.getMetadata(OWNED_PROPERTIES, this) ?? [];
6478
+ for (const property of properties2) {
6479
+ Object.defineProperty(this, property.key, {
6480
+ value: /* @__PURE__ */ __name(() => ownershipCondition(this.db, property.tokens, this._scopeCtx), "value"),
6481
+ configurable: true,
6482
+ enumerable: false
6483
+ });
6484
+ }
6485
+ },
6486
+ configurable: true,
6487
+ enumerable: false
6488
+ });
6489
+ }
6490
+ }
6491
+ __name(ownedProperty, "ownedProperty");
6438
6492
  var ScopeContext = class ScopeContext2 {
6439
6493
  static {
6440
6494
  __name(this, "ScopeContext");
@@ -6475,10 +6529,18 @@ ScopeContext = __decorate33([
6475
6529
  function Owned(token, ...alternatives) {
6476
6530
  const tokens = [token, ...alternatives];
6477
6531
  validateOwnershipAlternatives(tokens);
6478
- return function(target) {
6532
+ return function(target, propertyKey) {
6533
+ if (propertyKey !== void 0) {
6534
+ if (typeof target === "function")
6535
+ throw new Error("@Owned requires an instance property");
6536
+ ownedProperty(target, propertyKey, tokens);
6537
+ return;
6538
+ }
6539
+ if (typeof target !== "function")
6540
+ throw new Error("@Owned requires a repository class");
6479
6541
  Reflect.defineMetadata(OWNED_META, token, target);
6480
6542
  const proto = target.prototype;
6481
- Inject17(ScopeContext)(proto, "_scopeCtx");
6543
+ Inject18(ScopeContext)(proto, "_scopeCtx");
6482
6544
  Object.defineProperty(proto, "ownershipCondition", {
6483
6545
  value() {
6484
6546
  return ownershipCondition(this.db, tokens, this._scopeCtx);
@@ -6700,7 +6762,7 @@ __name(getAuthLocale, "getAuthLocale");
6700
6762
  var AUTH_SUPPORTED_LANGUAGES = Object.keys(AUTH_LOCALES);
6701
6763
 
6702
6764
  // src/oauth/google/GoogleOAuthProvider.ts
6703
- import { Inject as Inject19, Injectable as Injectable19 } from "najm-core";
6765
+ import { Inject as Inject20, Injectable as Injectable19 } from "najm-core";
6704
6766
 
6705
6767
  // src/oauth/types.ts
6706
6768
  var OAuthFlowError = class extends Error {
@@ -6718,7 +6780,7 @@ var OAuthFlowError = class extends Error {
6718
6780
  };
6719
6781
 
6720
6782
  // src/oauth/google/GoogleTokenVerifier.ts
6721
- import { Inject as Inject18, Injectable as Injectable18 } from "najm-core";
6783
+ import { Inject as Inject19, Injectable as Injectable18 } from "najm-core";
6722
6784
  import { createRemoteJWKSet, jwtVerify } from "jose";
6723
6785
  var __decorate34 = function(decorators, target, key, desc) {
6724
6786
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -6779,7 +6841,7 @@ var GoogleTokenVerifier = class GoogleTokenVerifier2 {
6779
6841
  }
6780
6842
  };
6781
6843
  __decorate34([
6782
- Inject18(AUTH_CONFIG),
6844
+ Inject19(AUTH_CONFIG),
6783
6845
  __metadata34("design:type", Object)
6784
6846
  ], GoogleTokenVerifier.prototype, "config", void 0);
6785
6847
  GoogleTokenVerifier = __decorate34([
@@ -6865,7 +6927,7 @@ var GoogleOAuthProvider = class GoogleOAuthProvider2 {
6865
6927
  }
6866
6928
  };
6867
6929
  __decorate35([
6868
- Inject19(AUTH_CONFIG),
6930
+ Inject20(AUTH_CONFIG),
6869
6931
  __metadata35("design:type", Object)
6870
6932
  ], GoogleOAuthProvider.prototype, "config", void 0);
6871
6933
  GoogleOAuthProvider = __decorate35([
@@ -6874,7 +6936,7 @@ GoogleOAuthProvider = __decorate35([
6874
6936
  ], GoogleOAuthProvider);
6875
6937
 
6876
6938
  // src/oauth/github/GitHubOAuthProvider.ts
6877
- import { Inject as Inject20, Injectable as Injectable20 } from "najm-core";
6939
+ import { Inject as Inject21, Injectable as Injectable20 } from "najm-core";
6878
6940
  var __decorate36 = function(decorators, target, key, desc) {
6879
6941
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6880
6942
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -6998,7 +7060,7 @@ var GitHubOAuthProvider = class GitHubOAuthProvider2 {
6998
7060
  }
6999
7061
  };
7000
7062
  __decorate36([
7001
- Inject20(AUTH_CONFIG),
7063
+ Inject21(AUTH_CONFIG),
7002
7064
  __metadata36("design:type", Object)
7003
7065
  ], GitHubOAuthProvider.prototype, "config", void 0);
7004
7066
  GitHubOAuthProvider = __decorate36([
@@ -7009,18 +7071,19 @@ GitHubOAuthProvider = __decorate36([
7009
7071
  import { createHash as createHash5 } from "crypto";
7010
7072
  import { Controller as Controller6, Ctx as Ctx2, Get as Get5, Post as Post6, Query as Query2, User as User5 } from "najm-core";
7011
7073
  import { RateLimit as RateLimit3 } from "najm-rate";
7074
+ import { Public as Public3 } from "najm-guard";
7012
7075
 
7013
7076
  // src/oauth/OAuthService.ts
7014
- import { Err as Err15, Inject as Inject23, Injectable as Injectable23, Log as Log2 } from "najm-core";
7077
+ import { Err as Err16, Inject as Inject24, Injectable as Injectable23, Log as Log2 } from "najm-core";
7015
7078
 
7016
7079
  // src/oauth/OAuthAccountService.ts
7017
7080
  import { randomBytes as randomBytes3 } from "crypto";
7018
- import { Inject as Inject22, Injectable as Injectable21 } from "najm-core";
7081
+ import { Inject as Inject23, Injectable as Injectable21 } from "najm-core";
7019
7082
  import { Transaction as Transaction5 } from "najm-database";
7020
7083
 
7021
7084
  // src/oauth/OAuthAccountRepository.ts
7022
7085
  import { and as and6, eq as eq9 } from "drizzle-orm";
7023
- import { Inject as Inject21, Repository as Repository7 } from "najm-core";
7086
+ import { Inject as Inject22, Repository as Repository7 } from "najm-core";
7024
7087
  import { DB as DB7 } from "najm-database";
7025
7088
  var __decorate37 = function(decorators, target, key, desc) {
7026
7089
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -7061,7 +7124,7 @@ __decorate37([
7061
7124
  __metadata37("design:type", Object)
7062
7125
  ], OAuthAccountRepository.prototype, "db", void 0);
7063
7126
  __decorate37([
7064
- Inject21(AUTH_SCHEMA),
7127
+ Inject22(AUTH_SCHEMA),
7065
7128
  __metadata37("design:type", Object)
7066
7129
  ], OAuthAccountRepository.prototype, "schema", void 0);
7067
7130
  OAuthAccountRepository = __decorate37([
@@ -7158,7 +7221,7 @@ var OAuthAccountService = class OAuthAccountService2 {
7158
7221
  }
7159
7222
  };
7160
7223
  __decorate38([
7161
- Inject22(AUTH_CONFIG),
7224
+ Inject23(AUTH_CONFIG),
7162
7225
  __metadata38("design:type", Object)
7163
7226
  ], OAuthAccountService.prototype, "config", void 0);
7164
7227
  __decorate38([
@@ -7362,7 +7425,7 @@ var OAuthService = class OAuthService2 {
7362
7425
  */
7363
7426
  failStart(error) {
7364
7427
  if (error instanceof OAuthFlowError) {
7365
- Err15(error.oauthCode, error.status);
7428
+ Err16(error.oauthCode, error.status);
7366
7429
  }
7367
7430
  throw error;
7368
7431
  }
@@ -7469,7 +7532,7 @@ var OAuthService = class OAuthService2 {
7469
7532
  }
7470
7533
  };
7471
7534
  __decorate40([
7472
- Inject23(AUTH_CONFIG),
7535
+ Inject24(AUTH_CONFIG),
7473
7536
  __metadata40("design:type", Object)
7474
7537
  ], OAuthService.prototype, "config", void 0);
7475
7538
  __decorate40([
@@ -7523,6 +7586,7 @@ var GitHubOAuthController = class GitHubOAuthController2 {
7523
7586
  };
7524
7587
  __decorate41([
7525
7588
  Get5("/start"),
7589
+ Public3(),
7526
7590
  RateLimit3({ limit: 20, window: "15m", key: "ip" }),
7527
7591
  __param13(0, Ctx2()),
7528
7592
  __param13(1, Query2("returnTo")),
@@ -7532,6 +7596,7 @@ __decorate41([
7532
7596
  ], GitHubOAuthController.prototype, "start", null);
7533
7597
  __decorate41([
7534
7598
  Get5("/callback"),
7599
+ Public3(),
7535
7600
  RateLimit3({ limit: 20, window: "15m", key: callbackKey }),
7536
7601
  __param13(0, Ctx2()),
7537
7602
  __param13(1, Query2("code")),
@@ -7560,6 +7625,7 @@ GitHubOAuthController = __decorate41([
7560
7625
  import { createHash as createHash6 } from "crypto";
7561
7626
  import { Controller as Controller7, Ctx as Ctx3, Get as Get6, Post as Post7, Query as Query3, User as User6 } from "najm-core";
7562
7627
  import { RateLimit as RateLimit4 } from "najm-rate";
7628
+ import { Public as Public4 } from "najm-guard";
7563
7629
  var __decorate42 = function(decorators, target, key, desc) {
7564
7630
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7565
7631
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -7602,6 +7668,7 @@ var OAuthController = class OAuthController2 {
7602
7668
  };
7603
7669
  __decorate42([
7604
7670
  Get6("/start"),
7671
+ Public4(),
7605
7672
  RateLimit4({ limit: 20, window: "15m", key: "ip" }),
7606
7673
  __param14(0, Ctx3()),
7607
7674
  __param14(1, Query3("returnTo")),
@@ -7611,6 +7678,7 @@ __decorate42([
7611
7678
  ], OAuthController.prototype, "start", null);
7612
7679
  __decorate42([
7613
7680
  Get6("/callback"),
7681
+ Public4(),
7614
7682
  RateLimit4({ limit: 20, window: "15m", key: callbackKey2 }),
7615
7683
  __param14(0, Ctx3()),
7616
7684
  __param14(1, Query3("code")),
@@ -7651,6 +7719,7 @@ var OAUTH_MODULE = [
7651
7719
  // src/credentialSetup/CredentialSetupController.ts
7652
7720
  import { Body as Body7, Controller as Controller8, Get as Get7, Post as Post8, ResMsg as ResMsg6 } from "najm-core";
7653
7721
  import { RateLimit as RateLimit5 } from "najm-rate";
7722
+ import { Public as Public5 } from "najm-guard";
7654
7723
  import { Validate as Validate6 } from "najm-validation";
7655
7724
 
7656
7725
  // src/credentialSetup/CredentialSetupDto.ts
@@ -7696,6 +7765,7 @@ var CredentialSetupController = class CredentialSetupController2 {
7696
7765
  };
7697
7766
  __decorate43([
7698
7767
  Get7("/setup"),
7768
+ Public5(),
7699
7769
  RateLimit5({ limit: 30, window: "15m", key: "ip" }),
7700
7770
  ResMsg6("auth.success.credentialSetupPending"),
7701
7771
  __metadata43("design:type", Function),
@@ -7704,6 +7774,7 @@ __decorate43([
7704
7774
  ], CredentialSetupController.prototype, "status", null);
7705
7775
  __decorate43([
7706
7776
  Post8("/change"),
7777
+ Public5(),
7707
7778
  RateLimit5({ limit: 5, window: "15m", key: "ip" }),
7708
7779
  Validate6(credentialSetupChangeDto),
7709
7780
  ResMsg6("auth.success.credentialSetupPasswordReplaced"),
@@ -7714,6 +7785,7 @@ __decorate43([
7714
7785
  ], CredentialSetupController.prototype, "change", null);
7715
7786
  __decorate43([
7716
7787
  Post8("/cancel"),
7788
+ Public5(),
7717
7789
  RateLimit5({ limit: 10, window: "15m", key: "ip" }),
7718
7790
  ResMsg6("auth.success.credentialSetupCancelled"),
7719
7791
  __metadata43("design:type", Function),
@@ -7776,9 +7848,9 @@ var resolveGoogleConfig = /* @__PURE__ */ __name((config) => {
7776
7848
  const clientId = google.clientId ?? process.env.GOOGLE_CLIENT_ID ?? "";
7777
7849
  const clientSecret = google.clientSecret ?? process.env.GOOGLE_CLIENT_SECRET ?? "";
7778
7850
  if (!clientId)
7779
- throw Err16.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
7851
+ throw Err17.configRequired("auth.oauth.google", "GOOGLE_CLIENT_ID");
7780
7852
  if (!clientSecret)
7781
- throw Err16.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
7853
+ throw Err17.configRequired("auth.oauth.google", "GOOGLE_CLIENT_SECRET");
7782
7854
  const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
7783
7855
  const callbackUrl = google.callbackUrl ?? process.env.GOOGLE_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/google/callback`;
7784
7856
  return {
@@ -7800,9 +7872,9 @@ var resolveGitHubConfig = /* @__PURE__ */ __name((config) => {
7800
7872
  const clientId = github.clientId ?? process.env.GITHUB_CLIENT_ID ?? "";
7801
7873
  const clientSecret = github.clientSecret ?? process.env.GITHUB_CLIENT_SECRET ?? "";
7802
7874
  if (!clientId)
7803
- throw Err16.configRequired("auth.oauth.github", "GITHUB_CLIENT_ID");
7875
+ throw Err17.configRequired("auth.oauth.github", "GITHUB_CLIENT_ID");
7804
7876
  if (!clientSecret)
7805
- throw Err16.configRequired("auth.oauth.github", "GITHUB_CLIENT_SECRET");
7877
+ throw Err17.configRequired("auth.oauth.github", "GITHUB_CLIENT_SECRET");
7806
7878
  const frontendUrl = config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000";
7807
7879
  const callbackUrl = github.callbackUrl ?? process.env.GITHUB_CALLBACK_URL ?? `${frontendUrl.replace(/\/$/, "")}/api/auth/oauth/github/callback`;
7808
7880
  return {
@@ -7872,10 +7944,10 @@ var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
7872
7944
  }
7873
7945
  };
7874
7946
  if (!finalConfig.jwt.accessSecret) {
7875
- throw Err16.configRequired("auth", "JWT_ACCESS_SECRET");
7947
+ throw Err17.configRequired("auth", "JWT_ACCESS_SECRET");
7876
7948
  }
7877
7949
  if (!finalConfig.jwt.refreshSecret) {
7878
- throw Err16.configRequired("auth", "JWT_REFRESH_SECRET");
7950
+ throw Err17.configRequired("auth", "JWT_REFRESH_SECRET");
7879
7951
  }
7880
7952
  return finalConfig;
7881
7953
  }, "resolveAuthConfig");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-auth",
3
- "version": "4.1.0",
3
+ "version": "4.2.1",
4
4
  "description": "Authentication and authorization library for najm framework",
5
5
  "type": "module",
6
6
  "files": [
@@ -92,9 +92,9 @@
92
92
  "dependencies": {
93
93
  "bcryptjs": "^3.0.2",
94
94
  "najm-cookies": "^2.0.2",
95
- "najm-core": "^2.0.6",
95
+ "najm-core": "^3.0.0",
96
96
  "najm-database": "^2.0.4",
97
- "najm-guard": "^2.0.2",
97
+ "najm-guard": "^2.1.0",
98
98
  "najm-i18n": "^2.1.2",
99
99
  "najm-cache": "^2.2.0",
100
100
  "najm-email": "^2.0.4",