najm-auth 4.0.8 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -27
- package/dist/index.d.ts +25 -3
- package/dist/index.js +58 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -508,44 +508,36 @@ export const Product = own(products)
|
|
|
508
508
|
join(products.userId, _users.id),
|
|
509
509
|
where(_users.id)
|
|
510
510
|
)
|
|
511
|
-
.writeBy(products.userId); //
|
|
511
|
+
.writeBy(products.userId); // Metadata for consumers; not an automatic write guard
|
|
512
512
|
```
|
|
513
513
|
|
|
514
514
|
### Using @Policy and @Owned
|
|
515
515
|
|
|
516
516
|
```typescript
|
|
517
|
-
import {
|
|
518
|
-
|
|
519
|
-
const config = configureOwnership({
|
|
520
|
-
adminRoles: ['admin'],
|
|
521
|
-
rules: {
|
|
522
|
-
'user': {
|
|
523
|
-
'products': Product.getRules()['user']
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
});
|
|
517
|
+
import { Owned, Policy, CanList, CanRead, CanCreate, CanUpdate, CanDelete } from 'najm-auth';
|
|
518
|
+
import { and, eq, type SQL } from 'drizzle-orm';
|
|
527
519
|
|
|
528
520
|
@Policy(Product)
|
|
529
521
|
@Controller('/api/products')
|
|
530
522
|
export class ProductController {
|
|
531
523
|
@Get('/')
|
|
532
|
-
@CanList() //
|
|
533
|
-
getAll(
|
|
524
|
+
@CanList() // Checks read permission; repository scopes rows
|
|
525
|
+
getAll() { /* delegate to a scoped service/repository read */ }
|
|
534
526
|
|
|
535
527
|
@Get('/:id')
|
|
536
|
-
@CanRead() //
|
|
528
|
+
@CanRead() // Checks read permission; lookup must scope the ID
|
|
537
529
|
getOne() { }
|
|
538
530
|
|
|
539
531
|
@Post('/')
|
|
540
|
-
@CanCreate() //
|
|
532
|
+
@CanCreate() // Service must validate/assign ownership
|
|
541
533
|
create(@Body() data: any) { }
|
|
542
534
|
|
|
543
535
|
@Put('/:id')
|
|
544
|
-
@CanUpdate() //
|
|
536
|
+
@CanUpdate() // Service must load an owned record before writing
|
|
545
537
|
update(@Body() data: any) { }
|
|
546
538
|
|
|
547
539
|
@Delete('/:id')
|
|
548
|
-
@CanDelete() //
|
|
540
|
+
@CanDelete() // Service must load an owned record before deleting
|
|
549
541
|
delete() { }
|
|
550
542
|
}
|
|
551
543
|
|
|
@@ -554,21 +546,54 @@ export class ProductController {
|
|
|
554
546
|
export class ProductRepository {
|
|
555
547
|
@DB() db!: Database;
|
|
556
548
|
|
|
557
|
-
//
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
async findOne(opts: { where: any }) {
|
|
563
|
-
return this.findOne(opts); // Returns null if not owned
|
|
564
|
-
}
|
|
549
|
+
// These methods are supplied by @Owned; do not define recursive wrappers.
|
|
550
|
+
declare ownershipCondition: () => SQL | undefined;
|
|
551
|
+
declare findMany: (opts?: { where?: SQL; limit?: number }) => Promise<ProductRow[]>;
|
|
552
|
+
declare findOne: (opts: { where: SQL }) => Promise<ProductRow | null>;
|
|
565
553
|
|
|
566
|
-
async
|
|
567
|
-
|
|
554
|
+
async getById(id: string) {
|
|
555
|
+
const [row] = await this.db.select().from(products)
|
|
556
|
+
.where(and(this.ownershipCondition(), eq(products.id, id))).limit(1);
|
|
557
|
+
return row ?? null;
|
|
568
558
|
}
|
|
569
559
|
}
|
|
570
560
|
```
|
|
571
561
|
|
|
562
|
+
### Composable ownership (4.1+)
|
|
563
|
+
|
|
564
|
+
`@Owned(Product)` now provides `ownershipCondition()` for custom queries.
|
|
565
|
+
It returns a parameterized `id IN (authorized IDs)` predicate; join-based rules
|
|
566
|
+
do not multiply outer rows. Combine it with filters in one
|
|
567
|
+
`.where(and(this.ownershipCondition(), filter))`. The owned table must have an
|
|
568
|
+
`id` column. A standalone `ownershipCondition(db, tokens, context)` and the
|
|
569
|
+
`OwnershipReadContext` / `OwnershipConditionMethods` types are also exported.
|
|
570
|
+
|
|
571
|
+
`@Owned(Product, SharedProduct)` grants either rule (OR), then your query's
|
|
572
|
+
filters apply (AND). Every alternative must reference the same table object.
|
|
573
|
+
Alternatives work with `ownershipCondition`, `findMany`, `findOne`, and
|
|
574
|
+
`scopedQuery`. Single-token helpers retain their existing behavior.
|
|
575
|
+
|
|
576
|
+
Configure school-wide, tenant-wide, or other privileged roles in the app:
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
const Product = own(products, { adminRoles: ['admin', 'operations'] })
|
|
580
|
+
.for('member', where(products.userId));
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
Those roles bypass row ownership only; route permissions still apply. Unknown
|
|
584
|
+
roles and anonymous active requests get no rows. Outside request context,
|
|
585
|
+
seed/job reads remain unscoped for compatibility; never treat a manually
|
|
586
|
+
constructed repository without request injection as an authenticated boundary.
|
|
587
|
+
|
|
588
|
+
**Migrating custom queries:** replace `this.scope(query).where(filter)` with
|
|
589
|
+
`query.where(and(this.ownershipCondition(), filter))`. Drizzle replaces an
|
|
590
|
+
earlier WHERE when another `.where()` is called. The legacy `scope()` and
|
|
591
|
+
`scopedQuery()` APIs remain for compatibility, but their result must not be
|
|
592
|
+
followed by `.where()`; for simple reads use `findMany({ where: filter })`.
|
|
593
|
+
An upgrade alone does not rewrite unsafe queries in consumers. Keep role
|
|
594
|
+
and cross-user integration tests in each app. `@Policy` and `@CanRead` check
|
|
595
|
+
permissions, not the ownership of a requested record ID.
|
|
596
|
+
|
|
572
597
|
### Advanced Ownership: Multi-Role Scoping
|
|
573
598
|
|
|
574
599
|
```typescript
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export { CredentialSetupRequirement, CredentialSetupSession, NewCredentialSetupR
|
|
|
14
14
|
import { CookieService } from 'najm-cookies';
|
|
15
15
|
import { Context } from 'hono';
|
|
16
16
|
import { GuardResult } from 'najm-guard';
|
|
17
|
-
import 'drizzle-orm';
|
|
17
|
+
import { SQL } from 'drizzle-orm';
|
|
18
18
|
import 'drizzle-orm/pg-core';
|
|
19
19
|
|
|
20
20
|
interface CredentialSetupOptions {
|
|
@@ -2856,7 +2856,29 @@ declare class ScopeContext {
|
|
|
2856
2856
|
role: string;
|
|
2857
2857
|
} | null;
|
|
2858
2858
|
}
|
|
2859
|
-
declare function Owned(token: OwnershipToken): (target: Function) => void;
|
|
2859
|
+
declare function Owned(token: OwnershipToken, ...alternatives: OwnershipToken[]): (target: Function) => void;
|
|
2860
|
+
|
|
2861
|
+
/** Request context consumed by ownershipCondition; ScopeContext implements it. */
|
|
2862
|
+
interface OwnershipReadContext {
|
|
2863
|
+
hasActiveContext(): boolean;
|
|
2864
|
+
getUser(): {
|
|
2865
|
+
id: string;
|
|
2866
|
+
role: string;
|
|
2867
|
+
} | null;
|
|
2868
|
+
}
|
|
2869
|
+
/** Additional custom-query method installed by @Owned. */
|
|
2870
|
+
interface OwnershipConditionMethods {
|
|
2871
|
+
ownershipCondition(): SQL | undefined;
|
|
2872
|
+
}
|
|
2873
|
+
/**
|
|
2874
|
+
* Compose this predicate with application filters in ONE .where(and(...)).
|
|
2875
|
+
* Each token grants alternative access to the same table through an ID
|
|
2876
|
+
* subquery, so joins cannot duplicate outer rows or collide with outer joins.
|
|
2877
|
+
* The table must expose an `id` column. Roles and ownership rules remain
|
|
2878
|
+
* application-owned. Unknown roles and anonymous active requests deny all.
|
|
2879
|
+
* Outside a request, reads remain unscoped for seed/job compatibility.
|
|
2880
|
+
*/
|
|
2881
|
+
declare function ownershipCondition(db: any, tokens: readonly OwnershipToken[], context: OwnershipReadContext | undefined): SQL | undefined;
|
|
2860
2882
|
|
|
2861
2883
|
/**
|
|
2862
2884
|
* Shared query builders used across auth repositories.
|
|
@@ -3181,4 +3203,4 @@ declare const authSeed: (config: AuthSeedConfig) => Record<string, SeedEntry>;
|
|
|
3181
3203
|
*/
|
|
3182
3204
|
declare function seedAuthData(config: SeedAuthDataConfig): Promise<SeedAuthDataResult>;
|
|
3183
3205
|
|
|
3184
|
-
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 OwnershipConfig, type OwnershipProvider, 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, parseSchema, permissionIdParam, pickProps, refreshTokenDto, registerDto, resetPasswordDto, resolveAuthLoginRateLimitConfig, revokeTokenDto, roleIdParam, runAsUser, seedAuthData, tokenIdParam, updatePermissionDto, updateRoleDto, updateTokenDto, updateUserDto, userIdInParam, userIdParam, userListQuery, verifyTokenDto, where };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1993,9 +1993,7 @@ var UserService = class UserService2 {
|
|
|
1993
1993
|
if (!config?.email || !config?.password) {
|
|
1994
1994
|
Err5("Admin email and password must be provided via config parameter");
|
|
1995
1995
|
}
|
|
1996
|
-
|
|
1997
|
-
Err5("Admin password must be at least 12 characters");
|
|
1998
|
-
}
|
|
1996
|
+
this.userValidator.validatePasswordStrength(config.password);
|
|
1999
1997
|
const adminRole = await this.roleValidator.checkAdminRoleExists();
|
|
2000
1998
|
const existingUser = await this.userRepository.getByEmail(config.email);
|
|
2001
1999
|
if (existingUser) {
|
|
@@ -5973,7 +5971,7 @@ var OwnershipToken = class {
|
|
|
5973
5971
|
symbol;
|
|
5974
5972
|
name;
|
|
5975
5973
|
table;
|
|
5976
|
-
_rules =
|
|
5974
|
+
_rules = /* @__PURE__ */ Object.create(null);
|
|
5977
5975
|
_writeScopeCol;
|
|
5978
5976
|
_adminRoles;
|
|
5979
5977
|
constructor(table, opts) {
|
|
@@ -6385,9 +6383,47 @@ __name(Policy, "Policy");
|
|
|
6385
6383
|
|
|
6386
6384
|
// src/ownership/OwnedDecorator.ts
|
|
6387
6385
|
import "reflect-metadata";
|
|
6388
|
-
import { sql as
|
|
6386
|
+
import { sql as sql6, and as and5 } from "drizzle-orm";
|
|
6389
6387
|
import { Injectable as Injectable17, Inject as Inject17, DI as DI3, Container as Container2, REQUEST_ID } from "najm-core";
|
|
6390
6388
|
import { USER as USER2 } from "najm-guard";
|
|
6389
|
+
|
|
6390
|
+
// src/ownership/ownershipCondition.ts
|
|
6391
|
+
import { inArray, or, sql as sql5 } from "drizzle-orm";
|
|
6392
|
+
function validateOwnershipAlternatives(tokens) {
|
|
6393
|
+
if (!tokens.length)
|
|
6394
|
+
throw new Error("Ownership requires at least one token");
|
|
6395
|
+
const table = tokens[0].table;
|
|
6396
|
+
if (tokens.some((token) => token.table !== table)) {
|
|
6397
|
+
throw new Error("Ownership alternatives must refer to the same table");
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
__name(validateOwnershipAlternatives, "validateOwnershipAlternatives");
|
|
6401
|
+
function ownershipCondition(db, tokens, context) {
|
|
6402
|
+
validateOwnershipAlternatives(tokens);
|
|
6403
|
+
const idColumn = tokens[0].table.id;
|
|
6404
|
+
if (!idColumn)
|
|
6405
|
+
throw new Error("ownershipCondition requires a table with an id column");
|
|
6406
|
+
if (!context?.hasActiveContext())
|
|
6407
|
+
return void 0;
|
|
6408
|
+
const user = context.getUser();
|
|
6409
|
+
if (!user)
|
|
6410
|
+
return sql5`1 = 0`;
|
|
6411
|
+
const conditions = [];
|
|
6412
|
+
for (const token of tokens) {
|
|
6413
|
+
const { query, condition } = token.applyScopeSplit(user.id, user.role, db.select({ id: idColumn }).from(token.table));
|
|
6414
|
+
if (condition === null)
|
|
6415
|
+
return void 0;
|
|
6416
|
+
if (!Object.prototype.hasOwnProperty.call(token.getRules(), user.role))
|
|
6417
|
+
continue;
|
|
6418
|
+
conditions.push(inArray(idColumn, query.where(condition)));
|
|
6419
|
+
}
|
|
6420
|
+
if (!conditions.length)
|
|
6421
|
+
return sql5`1 = 0`;
|
|
6422
|
+
return conditions.length === 1 ? conditions[0] : or(...conditions);
|
|
6423
|
+
}
|
|
6424
|
+
__name(ownershipCondition, "ownershipCondition");
|
|
6425
|
+
|
|
6426
|
+
// src/ownership/OwnedDecorator.ts
|
|
6391
6427
|
var __decorate33 = function(decorators, target, key, desc) {
|
|
6392
6428
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
6393
6429
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -6436,11 +6472,20 @@ __decorate33([
|
|
|
6436
6472
|
ScopeContext = __decorate33([
|
|
6437
6473
|
Injectable17()
|
|
6438
6474
|
], ScopeContext);
|
|
6439
|
-
function Owned(token) {
|
|
6475
|
+
function Owned(token, ...alternatives) {
|
|
6476
|
+
const tokens = [token, ...alternatives];
|
|
6477
|
+
validateOwnershipAlternatives(tokens);
|
|
6440
6478
|
return function(target) {
|
|
6441
6479
|
Reflect.defineMetadata(OWNED_META, token, target);
|
|
6442
6480
|
const proto = target.prototype;
|
|
6443
6481
|
Inject17(ScopeContext)(proto, "_scopeCtx");
|
|
6482
|
+
Object.defineProperty(proto, "ownershipCondition", {
|
|
6483
|
+
value() {
|
|
6484
|
+
return ownershipCondition(this.db, tokens, this._scopeCtx);
|
|
6485
|
+
},
|
|
6486
|
+
configurable: true,
|
|
6487
|
+
enumerable: false
|
|
6488
|
+
});
|
|
6444
6489
|
function getUser(self) {
|
|
6445
6490
|
return self._scopeCtx?.getUser() ?? null;
|
|
6446
6491
|
}
|
|
@@ -6472,9 +6517,11 @@ function Owned(token) {
|
|
|
6472
6517
|
return (query) => {
|
|
6473
6518
|
if (!hasActiveContext(this))
|
|
6474
6519
|
return query;
|
|
6520
|
+
if (alternatives.length)
|
|
6521
|
+
return query.where(this.ownershipCondition());
|
|
6475
6522
|
const user = getUser(this);
|
|
6476
6523
|
if (!user)
|
|
6477
|
-
return query.where(
|
|
6524
|
+
return query.where(sql6`1 = 0`);
|
|
6478
6525
|
return token.applyScope(user.id, user.role, query);
|
|
6479
6526
|
};
|
|
6480
6527
|
},
|
|
@@ -6491,6 +6538,9 @@ function Owned(token) {
|
|
|
6491
6538
|
if (!user)
|
|
6492
6539
|
return [];
|
|
6493
6540
|
const base = this.db.select().from(token.table);
|
|
6541
|
+
if (alternatives.length) {
|
|
6542
|
+
return applyQueryOptions(base, opts, combineConditions(this.ownershipCondition(), opts.where));
|
|
6543
|
+
}
|
|
6494
6544
|
const { query: q, condition: scopeCondition } = token.applyScopeSplit(user.id, user.role, base);
|
|
6495
6545
|
return applyQueryOptions(q, opts, combineConditions(scopeCondition, opts.where));
|
|
6496
6546
|
};
|
|
@@ -8115,6 +8165,7 @@ export {
|
|
|
8115
8165
|
normalizeTunisianPhone,
|
|
8116
8166
|
oauthAccountsTable,
|
|
8117
8167
|
own,
|
|
8168
|
+
ownershipCondition,
|
|
8118
8169
|
parseSchema,
|
|
8119
8170
|
permissionIdParam,
|
|
8120
8171
|
permissionsTable,
|