mongodb-dynamic-api 2.1.1 → 2.1.3
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/builders/casl/casl-ability.builder.d.ts +2 -2
- package/src/builders/casl/casl-ability.builder.js +7 -4
- package/src/dtos/delete.presenter.d.ts +3 -0
- package/src/{routes/delete-one/delete-one.presenter.js → dtos/delete.presenter.js} +4 -4
- package/src/dtos/index.d.ts +1 -0
- package/src/dtos/index.js +1 -0
- package/src/guards/base-policies.guard.d.ts +2 -2
- package/src/helpers/controller-ability-predicates.helper.d.ts +2 -2
- package/src/helpers/controller-mixin.helper.d.ts +66 -0
- package/src/helpers/controller-mixin.helper.js +159 -0
- package/src/helpers/format.helper.d.ts +1 -0
- package/src/helpers/format.helper.js +5 -1
- package/src/interfaces/dynamic-api-casl-ability.interface.d.ts +8 -5
- package/src/interfaces/dynamic-api-casl-ability.interface.js +3 -0
- package/src/interfaces/dynamic-api-controller-options.interface.d.ts +2 -2
- package/src/interfaces/dynamic-api-policy-handler.interface.d.ts +3 -5
- package/src/interfaces/dynamic-api-route-config.interface.d.ts +2 -2
- package/src/mixins/create-policies-guard.mixin.d.ts +2 -2
- package/src/modules/auth/interfaces/auth-options.interface.d.ts +2 -2
- package/src/modules/auth/mixins/auth-register-policies-guard.mixin.d.ts +2 -2
- package/src/modules/auth/services/base-auth.service.d.ts +1 -0
- package/src/modules/auth/services/base-auth.service.js +7 -4
- package/src/routes/create-many/create-many-controller.mixin.d.ts +1 -1
- package/src/routes/create-many/create-many-controller.mixin.js +6 -54
- package/src/routes/create-one/create-one-controller.mixin.d.ts +1 -1
- package/src/routes/create-one/create-one-controller.mixin.js +6 -35
- package/src/routes/delete-many/base-delete-many.service.d.ts +2 -2
- package/src/routes/delete-many/base-delete-many.service.js +2 -2
- package/src/routes/delete-many/delete-many-controller.mixin.d.ts +1 -1
- package/src/routes/delete-many/delete-many-controller.mixin.js +4 -28
- package/src/routes/delete-many/index.d.ts +0 -1
- package/src/routes/delete-many/index.js +0 -1
- package/src/routes/delete-one/base-delete-one.service.d.ts +2 -2
- package/src/routes/delete-one/base-delete-one.service.js +2 -2
- package/src/routes/delete-one/delete-one-controller.mixin.d.ts +1 -1
- package/src/routes/delete-one/delete-one-controller.mixin.js +5 -37
- package/src/routes/delete-one/index.d.ts +0 -1
- package/src/routes/delete-one/index.js +0 -1
- package/src/routes/duplicate-many/duplicate-many-controller.mixin.d.ts +1 -1
- package/src/routes/duplicate-many/duplicate-many-controller.mixin.js +6 -35
- package/src/routes/duplicate-one/duplicate-one-controller.mixin.d.ts +1 -1
- package/src/routes/duplicate-one/duplicate-one-controller.mixin.js +6 -42
- package/src/routes/get-many/get-many-controller.mixin.d.ts +1 -1
- package/src/routes/get-many/get-many-controller.mixin.js +5 -35
- package/src/routes/get-one/get-one-controller.mixin.d.ts +1 -1
- package/src/routes/get-one/get-one-controller.mixin.js +5 -42
- package/src/routes/replace-one/replace-one-controller.mixin.d.ts +1 -1
- package/src/routes/replace-one/replace-one-controller.mixin.js +6 -43
- package/src/routes/update-many/update-many-controller.mixin.d.ts +1 -1
- package/src/routes/update-many/update-many-controller.mixin.js +5 -34
- package/src/routes/update-one/update-one-controller.mixin.d.ts +1 -1
- package/src/routes/update-one/update-one-controller.mixin.js +6 -43
- package/src/version.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/src/routes/delete-one/delete-one.presenter.d.ts +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.3](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.1.2...v2.1.3) (2024-03-29)
|
|
4
|
+
|
|
5
|
+
## [2.1.2](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.1.1...v2.1.2) (2024-03-26)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
* rename all custom dto to avoid swagger conflicts ([0bc7e5f](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/0bc7e5fe85f3c44ce3382839e5a502d3232e5526))
|
|
9
|
+
|
|
3
10
|
## [2.1.1](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.1.0...v2.1.1) (2024-03-21)
|
|
4
11
|
|
|
5
12
|
## [2.1.0](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v2.0.0...v2.1.0) (2024-03-20)
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Type } from '@nestjs/common';
|
|
2
|
-
import { AppAbility,
|
|
2
|
+
import { AppAbility, RouteAbilityPredicate, RouteType } from '../../interfaces';
|
|
3
3
|
import { BaseEntity } from '../../models';
|
|
4
|
-
declare function CaslAbilityBuilder<Entity extends BaseEntity>(entity: Type<Entity>, routeType: RouteType, abilityPredicate:
|
|
4
|
+
declare function CaslAbilityBuilder<Entity extends BaseEntity>(entity: Type<Entity>, routeType: RouteType, abilityPredicate: RouteAbilityPredicate<Entity>, user: unknown): AppAbility<Entity>;
|
|
5
5
|
export { CaslAbilityBuilder };
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CaslAbilityBuilder = void 0;
|
|
4
4
|
const ability_1 = require("@casl/ability");
|
|
5
|
+
const interfaces_1 = require("../../interfaces");
|
|
5
6
|
function CaslAbilityBuilder(entity, routeType, abilityPredicate, user) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
can(routeType, entity);
|
|
7
|
+
if (!entity || !routeType || !abilityPredicate || !user) {
|
|
8
|
+
throw new Error('Invalid parameters, cannot build ability');
|
|
9
9
|
}
|
|
10
|
+
const { can, build } = new ability_1.AbilityBuilder(ability_1.PureAbility);
|
|
11
|
+
can(routeType, entity, (instance) => abilityPredicate(instance, user));
|
|
10
12
|
return build({
|
|
11
|
-
|
|
13
|
+
conditionsMatcher: interfaces_1.lambdaMatcher,
|
|
14
|
+
detectSubjectType: (object) => object.constructor,
|
|
12
15
|
});
|
|
13
16
|
}
|
|
14
17
|
exports.CaslAbilityBuilder = CaslAbilityBuilder;
|
|
@@ -9,12 +9,12 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.DeletePresenter = void 0;
|
|
13
13
|
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
-
class
|
|
14
|
+
class DeletePresenter {
|
|
15
15
|
}
|
|
16
|
-
exports.
|
|
16
|
+
exports.DeletePresenter = DeletePresenter;
|
|
17
17
|
__decorate([
|
|
18
18
|
(0, swagger_1.ApiProperty)(),
|
|
19
19
|
__metadata("design:type", Number)
|
|
20
|
-
],
|
|
20
|
+
], DeletePresenter.prototype, "deletedCount", void 0);
|
package/src/dtos/index.d.ts
CHANGED
package/src/dtos/index.js
CHANGED
|
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./delete-many-entity.query"), exports);
|
|
18
|
+
__exportStar(require("./delete.presenter"), exports);
|
|
18
19
|
__exportStar(require("./entity.param"), exports);
|
|
19
20
|
__exportStar(require("./entity.query"), exports);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { CanActivate, ExecutionContext, Type } from '@nestjs/common';
|
|
2
2
|
import { Reflector } from '@nestjs/core';
|
|
3
|
-
import {
|
|
3
|
+
import { RouteAbilityPredicate, RouteType } from '../interfaces';
|
|
4
4
|
import { BaseEntity } from '../models';
|
|
5
5
|
export declare abstract class BasePoliciesGuard<Entity extends BaseEntity> implements CanActivate {
|
|
6
6
|
protected readonly reflector: Reflector;
|
|
7
7
|
protected routeType: RouteType;
|
|
8
8
|
protected entity: Type<Entity>;
|
|
9
|
-
protected abilityPredicate:
|
|
9
|
+
protected abilityPredicate: RouteAbilityPredicate<Entity> | undefined;
|
|
10
10
|
protected constructor(reflector: Reflector);
|
|
11
11
|
canActivate(context: ExecutionContext): boolean;
|
|
12
12
|
private execPolicyHandler;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ControllerAbilityPredicate, RouteAbilityPredicate, RouteType } from '../interfaces';
|
|
2
2
|
import { BaseEntity } from '../models';
|
|
3
|
-
declare function getPredicateFromControllerAbilityPredicates<Entity extends BaseEntity>(controllerAbilityPredicates:
|
|
3
|
+
declare function getPredicateFromControllerAbilityPredicates<Entity extends BaseEntity>(controllerAbilityPredicates: ControllerAbilityPredicate<Entity>[], route: RouteType): RouteAbilityPredicate<Entity>;
|
|
4
4
|
export { getPredicateFromControllerAbilityPredicates };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Type } from '@nestjs/common';
|
|
2
|
+
import { EntityParam } from '../dtos';
|
|
3
|
+
import { DynamicApiControllerOptions, DynamicAPIRouteConfig } from '../interfaces';
|
|
4
|
+
import { BaseEntity } from '../models';
|
|
5
|
+
declare function getControllerMixinData<Entity extends BaseEntity>(entity: Type<Entity>, { path, apiTag, isPublic: isPublicController, abilityPredicates: controllerAbilityPredicates, }: DynamicApiControllerOptions<Entity>, { type: routeType, description, dTOs, isPublic: isPublicRoute, abilityPredicate: routeAbilityPredicate, }: DynamicAPIRouteConfig<Entity>, version?: string): {
|
|
6
|
+
routeType: import("../interfaces/dynamic-api-route-type.type").RouteType;
|
|
7
|
+
displayedName: string;
|
|
8
|
+
description: string;
|
|
9
|
+
isPublic: boolean;
|
|
10
|
+
abilityPredicate: import("../interfaces/dynamic-api-casl-ability.interface").RouteAbilityPredicate<Entity>;
|
|
11
|
+
RouteBody: Type<any>;
|
|
12
|
+
RoutePresenter: Type<any>;
|
|
13
|
+
EntityParam?: undefined;
|
|
14
|
+
RouteQuery?: undefined;
|
|
15
|
+
} | {
|
|
16
|
+
routeType: import("../interfaces/dynamic-api-route-type.type").RouteType;
|
|
17
|
+
displayedName: string;
|
|
18
|
+
description: string;
|
|
19
|
+
isPublic: boolean;
|
|
20
|
+
abilityPredicate: import("../interfaces/dynamic-api-casl-ability.interface").RouteAbilityPredicate<Entity>;
|
|
21
|
+
RoutePresenter: Type<any>;
|
|
22
|
+
RouteBody?: undefined;
|
|
23
|
+
EntityParam?: undefined;
|
|
24
|
+
RouteQuery?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
routeType: import("../interfaces/dynamic-api-route-type.type").RouteType;
|
|
27
|
+
displayedName: string;
|
|
28
|
+
description: string;
|
|
29
|
+
isPublic: boolean;
|
|
30
|
+
abilityPredicate: import("../interfaces/dynamic-api-casl-ability.interface").RouteAbilityPredicate<Entity>;
|
|
31
|
+
EntityParam: typeof EntityParam;
|
|
32
|
+
RoutePresenter: Type<any>;
|
|
33
|
+
RouteBody?: undefined;
|
|
34
|
+
RouteQuery?: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
routeType: import("../interfaces/dynamic-api-route-type.type").RouteType;
|
|
37
|
+
displayedName: string;
|
|
38
|
+
description: string;
|
|
39
|
+
isPublic: boolean;
|
|
40
|
+
abilityPredicate: import("../interfaces/dynamic-api-casl-ability.interface").RouteAbilityPredicate<Entity>;
|
|
41
|
+
RouteBody: Type<any>;
|
|
42
|
+
RoutePresenter: Type<any>;
|
|
43
|
+
EntityParam: typeof EntityParam;
|
|
44
|
+
RouteQuery?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
routeType: import("../interfaces/dynamic-api-route-type.type").RouteType;
|
|
47
|
+
displayedName: string;
|
|
48
|
+
description: string;
|
|
49
|
+
isPublic: boolean;
|
|
50
|
+
abilityPredicate: import("../interfaces/dynamic-api-casl-ability.interface").RouteAbilityPredicate<Entity>;
|
|
51
|
+
RouteQuery: Type<any>;
|
|
52
|
+
RoutePresenter: Type<any>;
|
|
53
|
+
RouteBody?: undefined;
|
|
54
|
+
EntityParam?: undefined;
|
|
55
|
+
} | {
|
|
56
|
+
routeType: import("../interfaces/dynamic-api-route-type.type").RouteType;
|
|
57
|
+
displayedName: string;
|
|
58
|
+
description: string;
|
|
59
|
+
isPublic: boolean;
|
|
60
|
+
abilityPredicate: import("../interfaces/dynamic-api-casl-ability.interface").RouteAbilityPredicate<Entity>;
|
|
61
|
+
EntityParam: typeof EntityParam;
|
|
62
|
+
RouteQuery: Type<any>;
|
|
63
|
+
RoutePresenter: Type<any>;
|
|
64
|
+
RouteBody?: undefined;
|
|
65
|
+
};
|
|
66
|
+
export { getControllerMixinData };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getControllerMixinData = void 0;
|
|
13
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
+
const class_transformer_1 = require("class-transformer");
|
|
15
|
+
const class_validator_1 = require("class-validator");
|
|
16
|
+
const dtos_1 = require("../dtos");
|
|
17
|
+
const mixins_1 = require("../mixins");
|
|
18
|
+
const controller_ability_predicates_helper_1 = require("./controller-ability-predicates.helper");
|
|
19
|
+
const format_helper_1 = require("./format.helper");
|
|
20
|
+
const versioning_config_helper_1 = require("./versioning-config.helper");
|
|
21
|
+
function buildCreateManyBodyDTO(entity, displayedName, version, CustomBody) {
|
|
22
|
+
class DtoBody extends (0, mixins_1.EntityBodyMixin)(entity) {
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(DtoBody, 'name', {
|
|
25
|
+
value: `${displayedName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}Dto`,
|
|
26
|
+
writable: false,
|
|
27
|
+
});
|
|
28
|
+
class CreateManyBody {
|
|
29
|
+
}
|
|
30
|
+
__decorate([
|
|
31
|
+
(0, swagger_1.ApiProperty)({ type: [DtoBody] }),
|
|
32
|
+
(0, class_validator_1.ValidateNested)({ each: true }),
|
|
33
|
+
(0, class_validator_1.IsInstance)(DtoBody, { each: true }),
|
|
34
|
+
(0, class_validator_1.ArrayMinSize)(1),
|
|
35
|
+
(0, class_transformer_1.Type)(() => DtoBody),
|
|
36
|
+
__metadata("design:type", Array)
|
|
37
|
+
], CreateManyBody.prototype, "list", void 0);
|
|
38
|
+
class RouteBody extends (0, swagger_1.PickType)(CustomBody ?? CreateManyBody, ['list']) {
|
|
39
|
+
}
|
|
40
|
+
Object.defineProperty(RouteBody, 'name', {
|
|
41
|
+
value: CustomBody ? CustomBody.name : `CreateMany${displayedName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}Dto`,
|
|
42
|
+
writable: false,
|
|
43
|
+
});
|
|
44
|
+
return RouteBody;
|
|
45
|
+
}
|
|
46
|
+
function buildDeletePresenterDTO(displayedName, version, CustomPresenter) {
|
|
47
|
+
class RoutePresenter extends (CustomPresenter ?? dtos_1.DeletePresenter) {
|
|
48
|
+
}
|
|
49
|
+
Object.defineProperty(RoutePresenter, 'name', {
|
|
50
|
+
value: CustomPresenter ? CustomPresenter.name : `Delete${displayedName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}Presenter`,
|
|
51
|
+
writable: false,
|
|
52
|
+
});
|
|
53
|
+
return RoutePresenter;
|
|
54
|
+
}
|
|
55
|
+
function buildDefaultRouteQuery(entity, routeType, displayedName, version, CustomQuery) {
|
|
56
|
+
class RouteQuery extends (CustomQuery ?? dtos_1.EntityQuery) {
|
|
57
|
+
}
|
|
58
|
+
Object.defineProperty(RouteQuery, 'name', {
|
|
59
|
+
value: CustomQuery ? CustomQuery.name : `${routeType}${displayedName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}Query`,
|
|
60
|
+
writable: false,
|
|
61
|
+
});
|
|
62
|
+
return RouteQuery;
|
|
63
|
+
}
|
|
64
|
+
function buildDefaultRouteBody(entity, routeType, displayedName, version, CustomBody) {
|
|
65
|
+
const optionalBody = routeType !== 'CreateOne' && routeType !== 'ReplaceOne';
|
|
66
|
+
class RouteBody extends (CustomBody ?? (0, mixins_1.EntityBodyMixin)(entity, optionalBody)) {
|
|
67
|
+
}
|
|
68
|
+
Object.defineProperty(RouteBody, 'name', {
|
|
69
|
+
value: CustomBody ? CustomBody.name : `${routeType}${displayedName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}Dto`,
|
|
70
|
+
writable: false,
|
|
71
|
+
});
|
|
72
|
+
return RouteBody;
|
|
73
|
+
}
|
|
74
|
+
function buildDefaultRoutePresenter(entity, routeType, displayedName, version, CustomPresenter) {
|
|
75
|
+
class RoutePresenter extends (CustomPresenter ?? (0, mixins_1.EntityPresenterMixin)(entity)) {
|
|
76
|
+
}
|
|
77
|
+
Object.defineProperty(RoutePresenter, 'name', {
|
|
78
|
+
value: CustomPresenter ? CustomPresenter.name : `${displayedName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}Presenter`,
|
|
79
|
+
writable: false,
|
|
80
|
+
});
|
|
81
|
+
return RoutePresenter;
|
|
82
|
+
}
|
|
83
|
+
function getDTOsByRouteType(entity, routeType, displayedName, version, dTOs) {
|
|
84
|
+
const { query: CustomQuery, body: CustomBody, presenter: CustomPresenter, } = dTOs ?? {};
|
|
85
|
+
Object.defineProperty(dtos_1.EntityParam, 'name', {
|
|
86
|
+
value: `${displayedName}${(0, versioning_config_helper_1.addVersionSuffix)(version)}Param`,
|
|
87
|
+
writable: false,
|
|
88
|
+
});
|
|
89
|
+
const RouteQuery = buildDefaultRouteQuery(entity, routeType, displayedName, version, CustomQuery);
|
|
90
|
+
const RouteBody = buildDefaultRouteBody(entity, routeType, displayedName, version, CustomBody);
|
|
91
|
+
const RoutePresenter = buildDefaultRoutePresenter(entity, routeType, displayedName, version, CustomPresenter);
|
|
92
|
+
switch (routeType) {
|
|
93
|
+
case 'CreateMany':
|
|
94
|
+
return {
|
|
95
|
+
RouteBody: buildCreateManyBodyDTO(entity, displayedName, version, CustomBody),
|
|
96
|
+
RoutePresenter,
|
|
97
|
+
};
|
|
98
|
+
case 'DeleteMany':
|
|
99
|
+
return {
|
|
100
|
+
RoutePresenter: buildDeletePresenterDTO(displayedName, version, CustomPresenter),
|
|
101
|
+
};
|
|
102
|
+
case 'DeleteOne':
|
|
103
|
+
return {
|
|
104
|
+
EntityParam: dtos_1.EntityParam,
|
|
105
|
+
RoutePresenter: buildDeletePresenterDTO(displayedName, version, CustomPresenter),
|
|
106
|
+
};
|
|
107
|
+
case 'CreateOne':
|
|
108
|
+
case 'DuplicateMany':
|
|
109
|
+
case 'UpdateMany':
|
|
110
|
+
return {
|
|
111
|
+
RouteBody,
|
|
112
|
+
RoutePresenter,
|
|
113
|
+
};
|
|
114
|
+
case 'DuplicateOne':
|
|
115
|
+
case 'ReplaceOne':
|
|
116
|
+
case 'UpdateOne':
|
|
117
|
+
return {
|
|
118
|
+
RouteBody,
|
|
119
|
+
RoutePresenter,
|
|
120
|
+
EntityParam: dtos_1.EntityParam,
|
|
121
|
+
};
|
|
122
|
+
case 'GetMany':
|
|
123
|
+
return {
|
|
124
|
+
RouteQuery,
|
|
125
|
+
RoutePresenter,
|
|
126
|
+
};
|
|
127
|
+
case 'GetOne':
|
|
128
|
+
return {
|
|
129
|
+
EntityParam: dtos_1.EntityParam,
|
|
130
|
+
RouteQuery,
|
|
131
|
+
RoutePresenter,
|
|
132
|
+
};
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(`Route type ${routeType} is not supported`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function getControllerMixinData(entity, { path, apiTag, isPublic: isPublicController, abilityPredicates: controllerAbilityPredicates, }, { type: routeType, description, dTOs, isPublic: isPublicRoute, abilityPredicate: routeAbilityPredicate, }, version) {
|
|
138
|
+
const displayedName = (0, format_helper_1.getFormattedApiTag)(apiTag, entity.name);
|
|
139
|
+
let isPublic;
|
|
140
|
+
if (typeof isPublicRoute === 'boolean') {
|
|
141
|
+
isPublic = isPublicRoute;
|
|
142
|
+
}
|
|
143
|
+
else if (typeof isPublicController === 'boolean') {
|
|
144
|
+
isPublic = isPublicController;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
isPublic = false;
|
|
148
|
+
}
|
|
149
|
+
const abilityPredicate = routeAbilityPredicate ?? (0, controller_ability_predicates_helper_1.getPredicateFromControllerAbilityPredicates)(controllerAbilityPredicates, routeType);
|
|
150
|
+
return {
|
|
151
|
+
...getDTOsByRouteType(entity, routeType, displayedName, version, dTOs),
|
|
152
|
+
routeType,
|
|
153
|
+
displayedName,
|
|
154
|
+
description,
|
|
155
|
+
isPublic,
|
|
156
|
+
abilityPredicate,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
exports.getControllerMixinData = getControllerMixinData;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isValidVersion = exports.pascalCase = void 0;
|
|
3
|
+
exports.getFormattedApiTag = exports.isValidVersion = exports.pascalCase = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
function pascalCase(str) {
|
|
6
6
|
return str ? (0, lodash_1.upperFirst)((0, lodash_1.camelCase)(str)) : undefined;
|
|
@@ -10,3 +10,7 @@ function isValidVersion(version) {
|
|
|
10
10
|
return /^\d+$/.test(version);
|
|
11
11
|
}
|
|
12
12
|
exports.isValidVersion = isValidVersion;
|
|
13
|
+
function getFormattedApiTag(apiTag, entityName) {
|
|
14
|
+
return pascalCase(apiTag) ?? entityName;
|
|
15
|
+
}
|
|
16
|
+
exports.getFormattedApiTag = getFormattedApiTag;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { AbilityTuple, MatchConditions, PureAbility } from '@casl/ability';
|
|
1
2
|
import { BaseEntity } from '../models';
|
|
2
3
|
import { RouteType } from './dynamic-api-route-type.type';
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
type
|
|
4
|
+
type AppAbility<Entity extends BaseEntity> = PureAbility<AbilityTuple, MatchConditions<Entity>>;
|
|
5
|
+
declare const lambdaMatcher: <Entity extends BaseEntity>(matchConditions: MatchConditions<Entity>) => MatchConditions<Entity>;
|
|
6
|
+
type RouteAbilityPredicate<Entity extends BaseEntity, User = any> = (entity: Entity, user: User) => boolean;
|
|
7
|
+
type RegisterAbilityPredicate<User = any> = (user: User) => boolean;
|
|
8
|
+
type ControllerAbilityPredicate<Entity extends BaseEntity> = {
|
|
6
9
|
targets: RouteType[];
|
|
7
|
-
predicate:
|
|
10
|
+
predicate: RouteAbilityPredicate<Entity>;
|
|
8
11
|
};
|
|
9
|
-
export {
|
|
12
|
+
export { AppAbility, ControllerAbilityPredicate, RegisterAbilityPredicate, RouteAbilityPredicate, lambdaMatcher, };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ValidationPipeOptions } from '@nestjs/common';
|
|
2
2
|
import { BaseEntity } from '../models';
|
|
3
|
-
import {
|
|
3
|
+
import { ControllerAbilityPredicate } from './dynamic-api-casl-ability.interface';
|
|
4
4
|
interface DynamicApiControllerOptions<Entity extends BaseEntity> {
|
|
5
5
|
path: string;
|
|
6
6
|
apiTag?: string;
|
|
7
7
|
version?: string;
|
|
8
8
|
isPublic?: boolean;
|
|
9
9
|
validationPipeOptions?: ValidationPipeOptions;
|
|
10
|
-
abilityPredicates?:
|
|
10
|
+
abilityPredicates?: ControllerAbilityPredicate<Entity>[];
|
|
11
11
|
}
|
|
12
12
|
export { DynamicApiControllerOptions };
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ExecutionContext, Type } from '@nestjs/common';
|
|
1
|
+
import { ExecutionContext } from '@nestjs/common';
|
|
3
2
|
import { Reflector } from '@nestjs/core';
|
|
4
3
|
import { BaseEntity } from '../models';
|
|
5
|
-
import {
|
|
6
|
-
type AppAbility<Entity extends BaseEntity> = MongoAbility<[RouteType, Type<Entity>]>;
|
|
4
|
+
import { AppAbility } from './dynamic-api-casl-ability.interface';
|
|
7
5
|
interface IPolicyHandler<Entity extends BaseEntity> {
|
|
8
6
|
handle(ability: AppAbility<Entity>): boolean;
|
|
9
7
|
}
|
|
@@ -13,4 +11,4 @@ interface PoliciesGuard<Entity extends BaseEntity> {
|
|
|
13
11
|
canActivate(context: ExecutionContext): boolean;
|
|
14
12
|
}
|
|
15
13
|
type PoliciesGuardConstructor<Entity extends BaseEntity> = new (reflector: Reflector) => PoliciesGuard<Entity>;
|
|
16
|
-
export {
|
|
14
|
+
export { PolicyHandler, PoliciesGuardConstructor, PoliciesGuard };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ValidationPipeOptions } from '@nestjs/common';
|
|
2
2
|
import { BaseEntity } from '../models';
|
|
3
|
-
import {
|
|
3
|
+
import { RouteAbilityPredicate } from './dynamic-api-casl-ability.interface';
|
|
4
4
|
import { DTOsBundle } from './dynamic-api-route-dtos-bundle.type';
|
|
5
5
|
import { RouteType } from './dynamic-api-route-type.type';
|
|
6
6
|
interface DynamicAPIRouteConfig<Entity extends BaseEntity> {
|
|
@@ -10,6 +10,6 @@ interface DynamicAPIRouteConfig<Entity extends BaseEntity> {
|
|
|
10
10
|
version?: string;
|
|
11
11
|
dTOs?: DTOsBundle;
|
|
12
12
|
validationPipeOptions?: ValidationPipeOptions;
|
|
13
|
-
abilityPredicate?:
|
|
13
|
+
abilityPredicate?: RouteAbilityPredicate<Entity>;
|
|
14
14
|
}
|
|
15
15
|
export { DynamicAPIRouteConfig };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Type } from '@nestjs/common';
|
|
2
|
-
import {
|
|
2
|
+
import { RouteAbilityPredicate, PoliciesGuardConstructor, RouteType } from '../interfaces';
|
|
3
3
|
import { BaseEntity } from '../models';
|
|
4
|
-
declare function CreatePoliciesGuardMixin<Entity extends BaseEntity>(entity: Type<Entity>, routeType: RouteType, version: string | undefined, abilityPredicate:
|
|
4
|
+
declare function CreatePoliciesGuardMixin<Entity extends BaseEntity>(entity: Type<Entity>, routeType: RouteType, version: string | undefined, abilityPredicate: RouteAbilityPredicate<Entity> | undefined): PoliciesGuardConstructor<Entity>;
|
|
5
5
|
export { CreatePoliciesGuardMixin };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Type } from '@nestjs/common';
|
|
2
|
-
import {
|
|
2
|
+
import { RegisterAbilityPredicate } from '../../../interfaces';
|
|
3
3
|
import { BaseEntity } from '../../../models';
|
|
4
4
|
type DynamicApiRegisterOptions<Entity extends BaseEntity = any> = {
|
|
5
5
|
protected?: boolean;
|
|
6
|
-
abilityPredicate?:
|
|
6
|
+
abilityPredicate?: RegisterAbilityPredicate;
|
|
7
7
|
additionalFields?: (keyof Entity | {
|
|
8
8
|
name: keyof Entity;
|
|
9
9
|
required?: boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from '@nestjs/common';
|
|
2
|
-
import {
|
|
2
|
+
import { RegisterAbilityPredicate, PoliciesGuardConstructor, RouteType } from '../../../interfaces';
|
|
3
3
|
import { BaseEntity } from '../../../models';
|
|
4
4
|
declare const registerRouteType: RouteType;
|
|
5
|
-
declare function AuthRegisterPoliciesGuardMixin<Entity extends BaseEntity>(entity: Type<Entity>, abilityPredicate:
|
|
5
|
+
declare function AuthRegisterPoliciesGuardMixin<Entity extends BaseEntity>(entity: Type<Entity>, abilityPredicate: RegisterAbilityPredicate | undefined): PoliciesGuardConstructor<Entity>;
|
|
6
6
|
export { AuthRegisterPoliciesGuardMixin, registerRouteType };
|
|
@@ -14,7 +14,7 @@ class BaseAuthService extends services_1.BaseService {
|
|
|
14
14
|
}
|
|
15
15
|
async validateUser(login, pass) {
|
|
16
16
|
const user = (await this.model.findOne({ [this.loginField]: login }).lean().exec());
|
|
17
|
-
if (!user || !await this.bcryptService.comparePassword(pass, user[this.passwordField])) {
|
|
17
|
+
if (!user || !(await this.bcryptService.comparePassword(pass, user[this.passwordField]))) {
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
20
|
const fieldsToBuild = [
|
|
@@ -22,7 +22,7 @@ class BaseAuthService extends services_1.BaseService {
|
|
|
22
22
|
this.loginField,
|
|
23
23
|
...this.additionalRequestFields,
|
|
24
24
|
];
|
|
25
|
-
return this.
|
|
25
|
+
return this.buildUserFields(user, fieldsToBuild);
|
|
26
26
|
}
|
|
27
27
|
async login(user) {
|
|
28
28
|
const fieldsToBuild = [
|
|
@@ -31,7 +31,7 @@ class BaseAuthService extends services_1.BaseService {
|
|
|
31
31
|
this.loginField,
|
|
32
32
|
...this.additionalRequestFields,
|
|
33
33
|
];
|
|
34
|
-
const payload = this.
|
|
34
|
+
const payload = this.buildUserFields(user, fieldsToBuild);
|
|
35
35
|
return {
|
|
36
36
|
accessToken: this.jwtService.sign(payload),
|
|
37
37
|
};
|
|
@@ -49,7 +49,7 @@ class BaseAuthService extends services_1.BaseService {
|
|
|
49
49
|
this.loginField,
|
|
50
50
|
...this.additionalRequestFields,
|
|
51
51
|
];
|
|
52
|
-
return this.
|
|
52
|
+
return this.buildUserFields(user, fieldsToBuild);
|
|
53
53
|
}
|
|
54
54
|
async changePassword(userId, newPassword) {
|
|
55
55
|
const hashedPassword = await this.bcryptService.hashPassword(newPassword);
|
|
@@ -60,5 +60,8 @@ class BaseAuthService extends services_1.BaseService {
|
|
|
60
60
|
async getUserById(userId) {
|
|
61
61
|
return (await this.model.findOne({ _id: userId }).lean().exec());
|
|
62
62
|
}
|
|
63
|
+
buildUserFields(user, fieldsToBuild) {
|
|
64
|
+
return this.buildInstance(fieldsToBuild.reduce((acc, field) => (user[field] !== undefined ? { ...acc, [field]: user[field] } : acc), {}));
|
|
65
|
+
}
|
|
63
66
|
}
|
|
64
67
|
exports.BaseAuthService = BaseAuthService;
|
|
@@ -2,5 +2,5 @@ import { Type } from '@nestjs/common';
|
|
|
2
2
|
import { DynamicApiControllerOptions, DynamicAPIRouteConfig } from '../../interfaces';
|
|
3
3
|
import { BaseEntity } from '../../models';
|
|
4
4
|
import { CreateManyControllerConstructor } from './create-many-controller.interface';
|
|
5
|
-
declare function CreateManyControllerMixin<Entity extends BaseEntity>(entity: Type<Entity>,
|
|
5
|
+
declare function CreateManyControllerMixin<Entity extends BaseEntity>(entity: Type<Entity>, controllerOptions: DynamicApiControllerOptions<Entity>, routeConfig: DynamicAPIRouteConfig<Entity>, version?: string): CreateManyControllerConstructor<Entity>;
|
|
6
6
|
export { CreateManyControllerMixin };
|
|
@@ -14,66 +14,18 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.CreateManyControllerMixin = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
-
const swagger_1 = require("@nestjs/swagger");
|
|
18
|
-
const class_transformer_1 = require("class-transformer");
|
|
19
|
-
const class_validator_1 = require("class-validator");
|
|
20
17
|
const builders_1 = require("../../builders");
|
|
21
18
|
const decorators_1 = require("../../decorators");
|
|
22
19
|
const helpers_1 = require("../../helpers");
|
|
23
|
-
const
|
|
20
|
+
const controller_mixin_helper_1 = require("../../helpers/controller-mixin.helper");
|
|
24
21
|
const mixins_1 = require("../../mixins");
|
|
25
|
-
function CreateManyControllerMixin(entity,
|
|
26
|
-
|
|
27
|
-
const {
|
|
28
|
-
|
|
29
|
-
if (typeof isPublicRoute === 'boolean') {
|
|
30
|
-
isPublic = isPublicRoute;
|
|
31
|
-
}
|
|
32
|
-
else if (typeof isPublicController === 'boolean') {
|
|
33
|
-
isPublic = isPublicController;
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
isPublic = false;
|
|
37
|
-
}
|
|
38
|
-
class DtoBody extends (0, mixins_1.EntityBodyMixin)(entity) {
|
|
39
|
-
}
|
|
40
|
-
Object.defineProperty(DtoBody, 'name', {
|
|
41
|
-
value: `${displayedName}${(0, helpers_1.addVersionSuffix)(version)}Dto`,
|
|
42
|
-
writable: false,
|
|
43
|
-
});
|
|
44
|
-
class CreateManyBody {
|
|
45
|
-
}
|
|
46
|
-
__decorate([
|
|
47
|
-
(0, swagger_1.ApiProperty)({ type: [DtoBody] }),
|
|
48
|
-
(0, class_validator_1.ValidateNested)({ each: true }),
|
|
49
|
-
(0, class_validator_1.IsInstance)(DtoBody, { each: true }),
|
|
50
|
-
(0, class_validator_1.ArrayMinSize)(1),
|
|
51
|
-
(0, class_transformer_1.Type)(() => DtoBody),
|
|
52
|
-
__metadata("design:type", Array)
|
|
53
|
-
], CreateManyBody.prototype, "list", void 0);
|
|
54
|
-
class RouteBody extends (0, swagger_1.PickType)(CustomBody ?? CreateManyBody, ['list']) {
|
|
55
|
-
}
|
|
56
|
-
if (!CustomBody) {
|
|
57
|
-
Object.defineProperty(RouteBody, 'name', {
|
|
58
|
-
value: `CreateMany${displayedName}${(0, helpers_1.addVersionSuffix)(version)}Dto`,
|
|
59
|
-
writable: false,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
class RoutePresenter extends (CustomPresenter ?? (0, mixins_1.EntityPresenterMixin)(entity)) {
|
|
63
|
-
}
|
|
64
|
-
if (!CustomPresenter) {
|
|
65
|
-
Object.defineProperty(RoutePresenter, 'name', {
|
|
66
|
-
value: `${displayedName}${(0, helpers_1.addVersionSuffix)(version)}Presenter`,
|
|
67
|
-
writable: false,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
const routeDecoratorsBuilder = new builders_1.RouteDecoratorsBuilder('CreateMany', entity, version, description, isPublic, {
|
|
71
|
-
param: undefined,
|
|
72
|
-
query: undefined,
|
|
22
|
+
function CreateManyControllerMixin(entity, controllerOptions, routeConfig, version) {
|
|
23
|
+
var _a;
|
|
24
|
+
const { routeType, description, isPublic, RouteBody, RoutePresenter, abilityPredicate, } = (0, controller_mixin_helper_1.getControllerMixinData)(entity, controllerOptions, routeConfig, version);
|
|
25
|
+
const routeDecoratorsBuilder = new builders_1.RouteDecoratorsBuilder(routeType, entity, version, description, isPublic, {
|
|
73
26
|
body: RouteBody,
|
|
74
27
|
presenter: RoutePresenter,
|
|
75
28
|
});
|
|
76
|
-
const abilityPredicate = routeAbilityPredicate ?? (0, controller_ability_predicates_helper_1.getPredicateFromControllerAbilityPredicates)(controllerAbilityPredicates, routeType);
|
|
77
29
|
class CreateManyPoliciesGuard extends (0, mixins_1.CreatePoliciesGuardMixin)(entity, routeType, version, abilityPredicate) {
|
|
78
30
|
}
|
|
79
31
|
class BaseCreateManyController {
|
|
@@ -91,7 +43,7 @@ function CreateManyControllerMixin(entity, { path, apiTag, isPublic: isPublicCon
|
|
|
91
43
|
(0, decorators_1.CheckPolicies)((ability) => ability.can(routeType, entity)),
|
|
92
44
|
__param(0, (0, common_1.Body)()),
|
|
93
45
|
__metadata("design:type", Function),
|
|
94
|
-
__metadata("design:paramtypes", [RouteBody]),
|
|
46
|
+
__metadata("design:paramtypes", [typeof (_a = typeof RouteBody !== "undefined" && RouteBody) === "function" ? _a : Object]),
|
|
95
47
|
__metadata("design:returntype", Promise)
|
|
96
48
|
], BaseCreateManyController.prototype, "createMany", null);
|
|
97
49
|
Object.defineProperty(BaseCreateManyController, 'name', {
|
|
@@ -2,5 +2,5 @@ import { Type } from '@nestjs/common';
|
|
|
2
2
|
import { DynamicApiControllerOptions, DynamicAPIRouteConfig } from '../../interfaces';
|
|
3
3
|
import { BaseEntity } from '../../models';
|
|
4
4
|
import { CreateOneControllerConstructor } from './create-one-controller.interface';
|
|
5
|
-
declare function CreateOneControllerMixin<Entity extends BaseEntity>(entity: Type<Entity>,
|
|
5
|
+
declare function CreateOneControllerMixin<Entity extends BaseEntity>(entity: Type<Entity>, controllerOptions: DynamicApiControllerOptions<Entity>, routeConfig: DynamicAPIRouteConfig<Entity>, version?: string): CreateOneControllerConstructor<Entity>;
|
|
6
6
|
export { CreateOneControllerMixin };
|