@nest-util/nest-crud 1.0.8 → 1.0.9

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.
@@ -3,6 +3,7 @@ import { CrudEndpoint, CrudInterface } from '../interfaces/crud.interface';
3
3
  import { PaginationDto } from '../dtos/pagination.dto';
4
4
  import { FilterDto } from '../dtos/filter.dto';
5
5
  import { ListAuditLogsDto } from '../dtos/list-audit-logs.dto';
6
+ import type { OwnershipUser } from '../interfaces/find-mine.interface';
6
7
  export declare const AUTH_PERMISSIONS_METADATA_KEY = "auth:permissions";
7
8
  export type CrudEndpointPermissions = string | readonly string[];
8
9
  export type CrudPermissionsMap = Partial<Record<CrudEndpoint, CrudEndpointPermissions>>;
@@ -16,10 +17,10 @@ export interface IBaseController<CD, UD, RD> {
16
17
  data: RD[];
17
18
  meta?: unknown;
18
19
  } | RD[]>;
19
- findOne(id: number): Promise<RD>;
20
+ findOne(id: number, user?: OwnershipUser): Promise<RD>;
20
21
  create(dto: CD): Promise<RD>;
21
- update(id: number, dto: UD): Promise<RD>;
22
- remove(id: number): Promise<boolean>;
22
+ update(id: number, dto: UD, user?: OwnershipUser): Promise<RD>;
23
+ remove(id: number, user?: OwnershipUser): Promise<boolean>;
23
24
  findAuditLogs?(query: ListAuditLogsDto): Promise<unknown>;
24
25
  }
25
26
  export declare function CreateNestedCrudController<CD, UD, RD>(createDto: Type<CD>, updateDto: Type<UD>, responseDto: Type<RD>, options?: CrudControllerFactoryOptions): Type<IBaseController<CD, UD, RD>>;
@@ -1 +1 @@
1
- {"version":3,"file":"nest-crud.controller.d.ts","sourceRoot":"","sources":["../../../src/lib/controllers/nest-crud.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,IAAI,EACL,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,eAAO,MAAM,6BAA6B,qBAAqB,CAAC;AAEhE,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;AAEjE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACtC,MAAM,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAC9C,CAAC;AAEF,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;IACzC,OAAO,EAAE,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,CACL,KAAK,EAAE,aAAa,GAAG,SAAS,GAC/B,OAAO,CAAC;QAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3D;AAyDD,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EACnD,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,EACnB,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,EACnB,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,EACrB,OAAO,CAAC,EAAE,4BAA4B,GACrC,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CA8HnC"}
1
+ {"version":3,"file":"nest-crud.controller.d.ts","sourceRoot":"","sources":["../../../src/lib/controllers/nest-crud.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,IAAI,EACL,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,eAAO,MAAM,6BAA6B,qBAAqB,CAAC;AAEhE,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;AAEjE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACtC,MAAM,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAC9C,CAAC;AAEF,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;IACzC,OAAO,EAAE,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,CACL,KAAK,EAAE,aAAa,GAAG,SAAS,GAC/B,OAAO,CAAC;QAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,aAAa,CAAC,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3D;AAyDD,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EACnD,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,EACnB,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,EACnB,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,EACrB,OAAO,CAAC,EAAE,4BAA4B,GACrC,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAwInC"}
@@ -72,13 +72,13 @@ function CreateNestedCrudController(createDto, updateDto, responseDto, options)
72
72
  this.ensureEndpointEnabled('create');
73
73
  return this.service.create(dto);
74
74
  }
75
- update(id, dto) {
75
+ update(id, dto, user) {
76
76
  this.ensureEndpointEnabled('update');
77
- return this.service.update(id, dto);
77
+ return this.service.update(id, dto, user);
78
78
  }
79
- remove(id) {
79
+ remove(id, user) {
80
80
  this.ensureEndpointEnabled('remove');
81
- return this.service.remove(id);
81
+ return this.service.remove(id, user);
82
82
  }
83
83
  findAuditLogs(query) {
84
84
  this.ensureEndpointEnabled('findAuditLogs');
@@ -87,9 +87,9 @@ function CreateNestedCrudController(createDto, updateDto, responseDto, options)
87
87
  }
88
88
  return this.service.findAuditLogs(query);
89
89
  }
90
- findOne(id) {
90
+ findOne(id, user) {
91
91
  this.ensureEndpointEnabled('findOne');
92
- return this.service.findOne(id);
92
+ return this.service.findOne(id, user);
93
93
  }
94
94
  }
95
95
  tslib_1.__decorate([
@@ -160,8 +160,9 @@ function CreateNestedCrudController(createDto, updateDto, responseDto, options)
160
160
  (0, swagger_1.ApiResponse)({ type: responseDto }),
161
161
  tslib_1.__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
162
162
  tslib_1.__param(1, (0, common_1.Body)()),
163
+ tslib_1.__param(2, (0, nest_auth_1.CurrentUser)()),
163
164
  tslib_1.__metadata("design:type", Function),
164
- tslib_1.__metadata("design:paramtypes", [Number, Object]),
165
+ tslib_1.__metadata("design:paramtypes", [Number, Object, Object]),
165
166
  tslib_1.__metadata("design:returntype", void 0)
166
167
  ], BaseController.prototype, "update", null);
167
168
  tslib_1.__decorate([
@@ -169,8 +170,9 @@ function CreateNestedCrudController(createDto, updateDto, responseDto, options)
169
170
  (0, response_message_decorator_1.Message)('deleted'),
170
171
  (0, audit_log_decorator_1.Audit)({ action: 'DELETE' }),
171
172
  tslib_1.__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
173
+ tslib_1.__param(1, (0, nest_auth_1.CurrentUser)()),
172
174
  tslib_1.__metadata("design:type", Function),
173
- tslib_1.__metadata("design:paramtypes", [Number]),
175
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
174
176
  tslib_1.__metadata("design:returntype", void 0)
175
177
  ], BaseController.prototype, "remove", null);
176
178
  tslib_1.__decorate([
@@ -186,8 +188,9 @@ function CreateNestedCrudController(createDto, updateDto, responseDto, options)
186
188
  (0, response_message_decorator_1.Message)('fetched'),
187
189
  (0, swagger_1.ApiResponse)({ type: responseDto }),
188
190
  tslib_1.__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
191
+ tslib_1.__param(1, (0, nest_auth_1.CurrentUser)()),
189
192
  tslib_1.__metadata("design:type", Function),
190
- tslib_1.__metadata("design:paramtypes", [Number]),
193
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
191
194
  tslib_1.__metadata("design:returntype", void 0)
192
195
  ], BaseController.prototype, "findOne", null);
193
196
  applyPermissionMetadata(BaseController, options?.permissions);
@@ -1,6 +1,7 @@
1
1
  import { FilterDto } from '../dtos/filter.dto';
2
2
  import { PaginationDto } from '../dtos/pagination.dto';
3
3
  import { CursorPaginationDto } from '../dtos/cursor-pagination.dto';
4
+ import { OwnershipUser } from './find-mine.interface';
4
5
  export type CrudEndpoint = 'findAll' | 'findOne' | 'create' | 'update' | 'remove' | 'findAuditLogs' | 'findMine';
5
6
  export interface AuditLogQuery {
6
7
  user_id?: string;
@@ -25,10 +26,10 @@ export interface CrudInterface<CreateDto, UpdateDto, ResponseDto> {
25
26
  meta?: unknown;
26
27
  }>;
27
28
  findAllWithCursor?(query: CursorPaginationDto & FilterDto): Promise<CursorPaginationResult<ResponseDto>>;
28
- findOne(id: number): Promise<ResponseDto>;
29
+ findOne(id: number, user?: OwnershipUser): Promise<ResponseDto>;
29
30
  create(dto: CreateDto): Promise<ResponseDto>;
30
- update(id: number, dto: UpdateDto): Promise<ResponseDto>;
31
- remove(id: number): Promise<boolean>;
31
+ update(id: number, dto: UpdateDto, user?: OwnershipUser): Promise<ResponseDto>;
32
+ remove(id: number, user?: OwnershipUser): Promise<boolean>;
32
33
  findAuditLogs?(query: AuditLogQuery): Promise<unknown>;
33
34
  findMine?(userId: string | number, query: PaginationDto & FilterDto): Promise<{
34
35
  data: ResponseDto[];
@@ -1 +1 @@
1
- {"version":3,"file":"crud.interface.d.ts","sourceRoot":"","sources":["../../../src/lib/interfaces/crud.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,UAAU,CAAC;AAEf,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW;IAC9D,iBAAiB,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAE5C,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;QACjD,IAAI,EAAE,WAAW,EAAE,CAAC;QACpB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;IAEH,iBAAiB,CAAC,CAChB,KAAK,EAAE,mBAAmB,GAAG,SAAS,GACrC,OAAO,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC;IAEhD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAE1C,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAE7C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEzD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErC,aAAa,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvD,QAAQ,CAAC,CACP,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,KAAK,EAAE,aAAa,GAAG,SAAS,GAC/B,OAAO,CAAC;QAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrD"}
1
+ {"version":3,"file":"crud.interface.d.ts","sourceRoot":"","sources":["../../../src/lib/interfaces/crud.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,UAAU,CAAC;AAEf,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW;IAC9D,iBAAiB,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAE5C,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;QACjD,IAAI,EAAE,WAAW,EAAE,CAAC;QACpB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;IAEH,iBAAiB,CAAC,CAChB,KAAK,EAAE,mBAAmB,GAAG,SAAS,GACrC,OAAO,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC;IAEhD,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEhE,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAE7C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAE/E,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3D,aAAa,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvD,QAAQ,CAAC,CACP,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,KAAK,EAAE,aAAa,GAAG,SAAS,GAC/B,OAAO,CAAC;QAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrD"}
@@ -1,6 +1,32 @@
1
1
  import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
2
+ /**
3
+ * Minimal structural view of the authenticated user passed to ownership
4
+ * enforcement. Compatible with `AuthUser` from `@nest-util/nest-auth`.
5
+ */
6
+ export interface OwnershipUser {
7
+ id?: string | number;
8
+ permissions?: readonly string[];
9
+ [key: string]: unknown;
10
+ }
2
11
  export interface FindMineConfig<TEntity extends ObjectLiteral> {
3
12
  userOwnershipField?: keyof TEntity;
4
13
  findMineQuery?: (qb: SelectQueryBuilder<TEntity>, userId: string | number) => void;
14
+ /**
15
+ * When true (and an ownership field/query is configured), the generic
16
+ * `findOne`, `update`, and `remove` operations are scoped to records owned
17
+ * by the passed-in user. Non-owned records resolve to 404; missing user
18
+ * resolves to 403. Defaults to false - existing behavior is preserved.
19
+ */
20
+ enforceOwnership?: boolean;
21
+ /**
22
+ * Permission strings that grant full access and bypass ownership checks.
23
+ * Example: ['admin.access'].
24
+ */
25
+ ownershipBypassPermissions?: readonly string[];
26
+ /**
27
+ * Custom predicate that grants full access and bypasses ownership checks.
28
+ * Takes precedence alongside ownershipBypassPermissions.
29
+ */
30
+ ownershipBypass?: (user: OwnershipUser) => boolean;
5
31
  }
6
32
  //# sourceMappingURL=find-mine.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"find-mine.interface.d.ts","sourceRoot":"","sources":["../../../src/lib/interfaces/find-mine.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE5D,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,aAAa;IAC3D,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC;IACnC,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;CACpF"}
1
+ {"version":3,"file":"find-mine.interface.d.ts","sourceRoot":"","sources":["../../../src/lib/interfaces/find-mine.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE5D;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,aAAa;IAC3D,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC;IACnC,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IAEnF;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,0BAA0B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAE/C;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC;CACpD"}
@@ -7,7 +7,7 @@ import { FilterDto } from '../dtos/filter.dto';
7
7
  import { CrudEndpoint, CrudInterface, CursorPaginationResult } from '../interfaces/crud.interface';
8
8
  import { CursorStrategy } from '../interfaces/cursor-strategy.interface';
9
9
  import { CrudHooks, TransactionConfig } from '../interfaces/hooks.interface';
10
- import { FindMineConfig } from '../interfaces/find-mine.interface';
10
+ import { FindMineConfig, OwnershipUser } from '../interfaces/find-mine.interface';
11
11
  export interface CrudServiceOptions<Entity extends ObjectLiteral, ResponseDto> extends FindMineConfig<Entity> {
12
12
  repository: Repository<Entity>;
13
13
  allowedFilters?: readonly (keyof Entity)[];
@@ -45,11 +45,20 @@ export declare class NestCrudService<Entity extends ObjectLiteral, CreateDto = P
45
45
  protected readonly transactionConfig: TransactionConfig;
46
46
  protected readonly userOwnershipField?: keyof Entity;
47
47
  protected readonly findMineQuery?: (qb: SelectQueryBuilder<Entity>, userId: string | number) => void;
48
+ protected readonly enforceOwnership: boolean;
49
+ protected readonly ownershipBypassPermissions: readonly string[];
50
+ protected readonly ownershipBypass?: (user: OwnershipUser) => boolean;
48
51
  constructor(options: CrudServiceOptions<Entity, ResponseDto>);
49
52
  private resolveRelations;
50
53
  private executeInTransaction;
51
54
  private executeHook;
52
55
  private buildRelationsObject;
56
+ private applyIncludeJoins;
57
+ private isOwnershipConfigured;
58
+ private canBypassOwnership;
59
+ private enforceOwnershipFor;
60
+ private applyOwnershipCondition;
61
+ private findOwnedEntity;
53
62
  findAll(query: PaginationDto & FilterDto): Promise<{
54
63
  data: ResponseDto[];
55
64
  meta: {
@@ -66,10 +75,10 @@ export declare class NestCrudService<Entity extends ObjectLiteral, CreateDto = P
66
75
  meta?: unknown;
67
76
  }>;
68
77
  findAllWithCursor(query: CursorPaginationDto & FilterDto): Promise<CursorPaginationResult<ResponseDto>>;
69
- findOne(id: number): Promise<ResponseDto>;
78
+ findOne(id: number, user?: OwnershipUser): Promise<ResponseDto>;
70
79
  create(payload: CreateDto): Promise<ResponseDto>;
71
- update(id: number, payload: UpdateDto): Promise<ResponseDto>;
72
- remove(id: number): Promise<boolean>;
80
+ update(id: number, payload: UpdateDto, user?: OwnershipUser): Promise<ResponseDto>;
81
+ remove(id: number, user?: OwnershipUser): Promise<boolean>;
73
82
  findAuditLogs(query: {
74
83
  user_id?: string;
75
84
  start_date?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"nest-crud.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/nest-crud.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nest-crud.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/nest-crud.service.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,9 @@ let NestCrudService = class NestCrudService {
24
24
  this.transactionConfig = options.transactionConfig ?? {};
25
25
  this.userOwnershipField = options.userOwnershipField;
26
26
  this.findMineQuery = options.findMineQuery;
27
+ this.enforceOwnership = options.enforceOwnership ?? false;
28
+ this.ownershipBypassPermissions = options.ownershipBypassPermissions ?? [];
29
+ this.ownershipBypass = options.ownershipBypass;
27
30
  }
28
31
  async resolveRelations(payload) {
29
32
  if (!this.relations.length)
@@ -92,22 +95,67 @@ let NestCrudService = class NestCrudService {
92
95
  }
93
96
  return result;
94
97
  }
98
+ applyIncludeJoins(qb) {
99
+ if (this.include.length === 0)
100
+ return;
101
+ this.include.forEach((relation) => {
102
+ const parts = relation.split('.');
103
+ if (parts.length === 1) {
104
+ qb.leftJoinAndSelect(`e.${parts[0]}`, parts[0]);
105
+ }
106
+ else {
107
+ const parentAlias = parts.slice(0, -1).join('_');
108
+ const field = parts[parts.length - 1];
109
+ const alias = parts.join('_');
110
+ qb.leftJoinAndSelect(`${parentAlias}.${field}`, alias);
111
+ }
112
+ });
113
+ }
114
+ isOwnershipConfigured() {
115
+ return Boolean(this.userOwnershipField || this.findMineQuery);
116
+ }
117
+ canBypassOwnership(user) {
118
+ if (!user)
119
+ return false;
120
+ if (this.ownershipBypass && this.ownershipBypass(user)) {
121
+ return true;
122
+ }
123
+ if (this.ownershipBypassPermissions.length > 0) {
124
+ const userPermissions = Array.isArray(user.permissions)
125
+ ? user.permissions
126
+ : [];
127
+ return this.ownershipBypassPermissions.some((permission) => userPermissions.includes(permission));
128
+ }
129
+ return false;
130
+ }
131
+ enforceOwnershipFor(user) {
132
+ return Boolean(this.enforceOwnership &&
133
+ this.isOwnershipConfigured() &&
134
+ !this.canBypassOwnership(user));
135
+ }
136
+ applyOwnershipCondition(qb, userId) {
137
+ if (this.findMineQuery) {
138
+ this.findMineQuery(qb, userId);
139
+ }
140
+ else if (this.userOwnershipField) {
141
+ qb.where(`e.${String(this.userOwnershipField)} = :userId`, { userId });
142
+ }
143
+ }
144
+ async findOwnedEntity(id, user) {
145
+ const userId = user?.id;
146
+ if (userId === undefined || userId === null) {
147
+ throw new common_1.ForbiddenException('Authentication required to access this resource');
148
+ }
149
+ const qb = this.repo.createQueryBuilder('e');
150
+ this.applyOwnershipCondition(qb, userId);
151
+ qb.andWhere('e.id = :id', { id });
152
+ this.applyIncludeJoins(qb);
153
+ const rows = await qb.getMany();
154
+ return rows[0] ?? null;
155
+ }
95
156
  async findAll(query) {
96
157
  const qb = this.repo.createQueryBuilder('e');
97
- if (this.include.length > 0) {
98
- this.include.forEach((relation) => {
99
- const parts = relation.split('.');
100
- if (parts.length === 1) {
101
- qb.leftJoinAndSelect(`e.${parts[0]}`, parts[0]);
102
- }
103
- else {
104
- const parentAlias = parts.slice(0, -1).join('_');
105
- const field = parts[parts.length - 1];
106
- const alias = parts.join('_');
107
- qb.leftJoinAndSelect(`${parentAlias}.${field}`, alias);
108
- }
109
- });
110
- }
158
+ this.applyIncludeJoins(qb);
111
159
  (0, filter_helper_1.applyFilters)(qb, query.filter, this.allowedFilters);
112
160
  const paginationMeta = (0, pagination_helper_1.applyPagination)(qb, query);
113
161
  if (query.orderBy) {
@@ -130,26 +178,8 @@ let NestCrudService = class NestCrudService {
130
178
  throw new common_1.BadRequestException('findMine not configured');
131
179
  }
132
180
  const qb = this.repo.createQueryBuilder('e');
133
- if (this.findMineQuery) {
134
- this.findMineQuery(qb, userId);
135
- }
136
- else if (this.userOwnershipField) {
137
- qb.where(`e.${String(this.userOwnershipField)} = :userId`, { userId });
138
- }
139
- if (this.include.length > 0) {
140
- this.include.forEach((relation) => {
141
- const parts = relation.split('.');
142
- if (parts.length === 1) {
143
- qb.leftJoinAndSelect(`e.${parts[0]}`, parts[0]);
144
- }
145
- else {
146
- const parentAlias = parts.slice(0, -1).join('_');
147
- const field = parts[parts.length - 1];
148
- const alias = parts.join('_');
149
- qb.leftJoinAndSelect(`${parentAlias}.${field}`, alias);
150
- }
151
- });
152
- }
181
+ this.applyOwnershipCondition(qb, userId);
182
+ this.applyIncludeJoins(qb);
153
183
  (0, filter_helper_1.applyFilters)(qb, query.filter, this.allowedFilters);
154
184
  const paginationMeta = (0, pagination_helper_1.applyPagination)(qb, query);
155
185
  if (query.orderBy) {
@@ -173,20 +203,7 @@ let NestCrudService = class NestCrudService {
173
203
  const orderDirection = 'DESC';
174
204
  const qb = this.repo.createQueryBuilder('e');
175
205
  // Join relations
176
- if (this.include.length > 0) {
177
- this.include.forEach((relation) => {
178
- const parts = relation.split('.');
179
- if (parts.length === 1) {
180
- qb.leftJoinAndSelect(`e.${parts[0]}`, parts[0]);
181
- }
182
- else {
183
- const parentAlias = parts.slice(0, -1).join('_');
184
- const field = parts[parts.length - 1];
185
- const alias = parts.join('_');
186
- qb.leftJoinAndSelect(`${parentAlias}.${field}`, alias);
187
- }
188
- });
189
- }
206
+ this.applyIncludeJoins(qb);
190
207
  // Apply filters
191
208
  (0, filter_helper_1.applyFilters)(qb, query.filter, this.allowedFilters);
192
209
  // Apply cursor filter
@@ -232,15 +249,21 @@ let NestCrudService = class NestCrudService {
232
249
  },
233
250
  };
234
251
  }
235
- async findOne(id) {
252
+ async findOne(id, user) {
236
253
  await this.executeHook(this.hooks.beforeFindOne, { id });
237
- const relationsObj = this.include.length > 0
238
- ? this.buildRelationsObject(this.include)
239
- : undefined;
240
- const entity = await this.repo.findOne({
241
- where: { id },
242
- relations: relationsObj,
243
- });
254
+ let entity;
255
+ if (this.enforceOwnershipFor(user)) {
256
+ entity = await this.findOwnedEntity(id, user);
257
+ }
258
+ else {
259
+ const relationsObj = this.include.length > 0
260
+ ? this.buildRelationsObject(this.include)
261
+ : undefined;
262
+ entity = await this.repo.findOne({
263
+ where: { id },
264
+ relations: relationsObj,
265
+ });
266
+ }
244
267
  if (!entity) {
245
268
  throw new common_1.NotFoundException('Resource not found');
246
269
  }
@@ -261,10 +284,16 @@ let NestCrudService = class NestCrudService {
261
284
  await this.executeHook(this.hooks.afterCreate, { entity, payload: payloadSnapshot });
262
285
  return result;
263
286
  }
264
- async update(id, payload) {
265
- const existing = await this.repo.findOneBy({
266
- id,
267
- });
287
+ async update(id, payload, user) {
288
+ let existing;
289
+ if (this.enforceOwnershipFor(user)) {
290
+ existing = await this.findOwnedEntity(id, user);
291
+ }
292
+ else {
293
+ existing = await this.repo.findOneBy({
294
+ id,
295
+ });
296
+ }
268
297
  if (!existing) {
269
298
  throw new common_1.NotFoundException('Resource not found');
270
299
  }
@@ -273,14 +302,20 @@ let NestCrudService = class NestCrudService {
273
302
  const resolved = await this.resolveRelations(payload);
274
303
  this.repo.merge(existing, resolved);
275
304
  await this.repo.save(existing);
276
- const result = await this.findOne(id);
305
+ const result = await this.findOne(id, user);
277
306
  await this.executeHook(this.hooks.afterUpdate, { entity: result, payload: payloadSnapshot, id });
278
307
  return result;
279
308
  }
280
- async remove(id) {
281
- const existing = await this.repo.findOneBy({
282
- id,
283
- });
309
+ async remove(id, user) {
310
+ let existing;
311
+ if (this.enforceOwnershipFor(user)) {
312
+ existing = await this.findOwnedEntity(id, user);
313
+ }
314
+ else {
315
+ existing = await this.repo.findOneBy({
316
+ id,
317
+ });
318
+ }
284
319
  if (!existing) {
285
320
  throw new common_1.NotFoundException('Resource not found');
286
321
  }
@@ -71,7 +71,7 @@ function crudControllerTests(config) {
71
71
  const expectedResult = { id: 1, name: 'Test' };
72
72
  service.findOne.mockResolvedValue(expectedResult);
73
73
  const result = await controller.findOne(1);
74
- expect(service.findOne).toHaveBeenCalledWith(1);
74
+ expect(service.findOne).toHaveBeenCalledWith(1, undefined);
75
75
  expect(result).toEqual(expectedResult);
76
76
  });
77
77
  });
@@ -91,7 +91,7 @@ function crudControllerTests(config) {
91
91
  const expectedResult = { id: 1 };
92
92
  service.update.mockResolvedValue(expectedResult);
93
93
  const result = await controller.update(1, dto);
94
- expect(service.update).toHaveBeenCalledWith(1, dto);
94
+ expect(service.update).toHaveBeenCalledWith(1, dto, undefined);
95
95
  expect(result).toEqual(expectedResult);
96
96
  });
97
97
  });
@@ -99,7 +99,7 @@ function crudControllerTests(config) {
99
99
  it('should call service.remove', async () => {
100
100
  service.remove.mockResolvedValue(true);
101
101
  const result = await controller.remove(1);
102
- expect(service.remove).toHaveBeenCalledWith(1);
102
+ expect(service.remove).toHaveBeenCalledWith(1, undefined);
103
103
  expect(result).toBe(true);
104
104
  });
105
105
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nest-util/nest-crud",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",