mongodb-dynamic-api 1.3.3 → 1.4.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/CHANGELOG.md +15 -0
- package/README.md +476 -21
- package/package.json +11 -1
- package/src/builders/casl/casl-ability.builder.d.ts +5 -0
- package/src/builders/casl/casl-ability.builder.js +14 -0
- package/src/builders/index.d.ts +3 -1
- package/src/builders/index.js +3 -1
- package/src/builders/route-decorators/auth-decorators.builder.d.ts +7 -0
- package/src/builders/route-decorators/auth-decorators.builder.js +14 -0
- package/src/builders/route-decorators/route-decorators.builder.d.ts +23 -0
- package/src/builders/{route-decorators.builder.js → route-decorators/route-decorators.builder.js} +45 -23
- package/src/decorators/check-policies.decorator.d.ts +5 -0
- package/src/decorators/check-policies.decorator.js +8 -0
- package/src/decorators/index.d.ts +2 -0
- package/src/decorators/index.js +2 -0
- package/src/decorators/public.decorator.d.ts +3 -0
- package/src/decorators/public.decorator.js +8 -0
- package/src/dynamic-api.module.d.ts +5 -4
- package/src/dynamic-api.module.js +132 -87
- package/src/guards/base-policies.guard.d.ts +13 -0
- package/src/guards/base-policies.guard.js +32 -0
- package/src/guards/dynamic-api-jwt-auth.guard.d.ts +11 -0
- package/src/guards/dynamic-api-jwt-auth.guard.js +38 -0
- package/src/guards/index.d.ts +2 -0
- package/src/guards/index.js +18 -0
- package/src/helpers/controller-ability-predicates.helper.d.ts +4 -0
- package/src/helpers/controller-ability-predicates.helper.js +23 -0
- package/src/helpers/index.d.ts +1 -0
- package/src/helpers/index.js +1 -0
- package/src/helpers/route-decorators.helper.d.ts +2 -2
- package/src/helpers/schema.helper.d.ts +28 -0
- package/src/helpers/schema.helper.js +22 -0
- package/src/index.d.ts +3 -1
- package/src/index.js +3 -1
- package/src/interceptors/dynamic-api-cache.interceptor.d.ts +16 -0
- package/src/interceptors/dynamic-api-cache.interceptor.js +48 -0
- package/src/interceptors/index.d.ts +1 -0
- package/src/interceptors/index.js +17 -0
- package/src/interfaces/controller-options.interface.d.ts +5 -1
- package/src/interfaces/decorator-builder.interface.d.ts +5 -0
- package/src/interfaces/dynamic-api-cache-options.interface.d.ts +1 -0
- package/src/interfaces/dynamic-api-casl-ability.interface.d.ts +17 -0
- package/src/interfaces/dynamic-api-casl-ability.interface.js +11 -0
- package/src/interfaces/dynamic-api-global-state.interface.d.ts +16 -0
- package/src/interfaces/dynamic-api-options.interface.d.ts +5 -2
- package/src/interfaces/dynamic-api-options.interface.js +3 -0
- package/src/interfaces/dynamic-api-policy-handler.interface.d.ts +16 -0
- package/src/interfaces/dynamic-api-route-config.interface.d.ts +7 -9
- package/src/interfaces/dynamic-api-route-dtos-bundle.type.d.ts +8 -0
- package/src/interfaces/dynamic-api-route-module.type.d.ts +3 -0
- package/src/interfaces/dynamic-api-route-type.type.d.ts +2 -0
- package/src/interfaces/index.d.ts +11 -2
- package/src/interfaces/index.js +11 -2
- package/src/mixins/create-policies-guard.mixin.d.ts +5 -0
- package/src/mixins/create-policies-guard.mixin.js +37 -0
- package/src/mixins/index.d.ts +1 -0
- package/src/mixins/index.js +1 -0
- package/src/modules/auth/auth.helper.d.ts +10 -0
- package/src/modules/auth/auth.helper.js +103 -0
- package/src/modules/auth/auth.module.d.ts +12 -0
- package/src/modules/auth/auth.module.js +55 -0
- package/src/modules/auth/guards/index.d.ts +2 -0
- package/src/modules/auth/guards/index.js +18 -0
- package/src/modules/auth/guards/jwt-auth.guard.d.ts +4 -0
- package/src/modules/auth/guards/jwt-auth.guard.js +17 -0
- package/src/modules/auth/guards/local-auth.guard.d.ts +4 -0
- package/src/modules/auth/guards/local-auth.guard.js +17 -0
- package/src/modules/auth/index.d.ts +7 -0
- package/src/modules/auth/index.js +23 -0
- package/src/modules/auth/interfaces/auth-controller.interface.d.ts +9 -0
- package/src/modules/auth/interfaces/auth-options.interface.d.ts +22 -0
- package/src/modules/auth/interfaces/auth-service.interface.d.ts +12 -0
- package/src/modules/auth/interfaces/index.d.ts +3 -0
- package/src/modules/auth/interfaces/index.js +19 -0
- package/src/modules/auth/mixins/auth-controller.mixin.d.ts +6 -0
- package/src/modules/auth/mixins/auth-controller.mixin.js +101 -0
- package/src/modules/auth/mixins/auth-register-policies-guard.mixin.d.ts +6 -0
- package/src/modules/auth/mixins/auth-register-policies-guard.mixin.js +59 -0
- package/src/modules/auth/mixins/index.d.ts +2 -0
- package/src/modules/auth/mixins/index.js +18 -0
- package/src/modules/auth/services/base-auth.service.d.ts +51 -0
- package/src/modules/auth/services/base-auth.service.js +64 -0
- package/src/modules/auth/services/index.d.ts +1 -0
- package/src/modules/auth/services/index.js +17 -0
- package/src/modules/auth/strategies/index.d.ts +1 -0
- package/src/modules/auth/strategies/index.js +17 -0
- package/src/modules/auth/strategies/jwt.strategy.d.ts +8 -0
- package/src/modules/auth/strategies/jwt.strategy.js +35 -0
- package/src/modules/dynamic-api-config/dynamic-api-config.module.d.ts +5 -0
- package/src/modules/dynamic-api-config/dynamic-api-config.module.js +31 -0
- package/src/modules/dynamic-api-config/index.d.ts +1 -0
- package/src/modules/dynamic-api-config/index.js +17 -0
- package/src/modules/index.d.ts +2 -11
- package/src/modules/index.js +2 -11
- package/src/routes/create-many/create-many-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/create-many/create-many-controller.mixin.js +26 -4
- package/src/{modules → routes}/create-many/create-many.helper.d.ts +2 -2
- package/src/{modules → routes}/create-many/create-many.helper.js +6 -4
- package/src/{modules → routes}/create-many/create-many.module.d.ts +1 -1
- package/src/{modules → routes}/create-many/create-many.module.js +2 -2
- package/src/routes/create-one/create-one-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/create-one/create-one-controller.mixin.js +25 -3
- package/src/{modules → routes}/create-one/create-one.helper.d.ts +2 -2
- package/src/{modules → routes}/create-one/create-one.helper.js +6 -4
- package/src/routes/create-one/create-one.module.d.ts +6 -0
- package/src/{modules → routes}/create-one/create-one.module.js +3 -3
- package/src/routes/delete-many/delete-many-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/delete-many/delete-many-controller.mixin.js +26 -3
- package/src/{modules → routes}/delete-many/delete-many.helper.d.ts +2 -2
- package/src/{modules → routes}/delete-many/delete-many.helper.js +6 -4
- package/src/routes/delete-many/delete-many.module.d.ts +6 -0
- package/src/{modules → routes}/delete-many/delete-many.module.js +3 -3
- package/src/routes/delete-one/delete-one-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/delete-one/delete-one-controller.mixin.js +26 -3
- package/src/{modules → routes}/delete-one/delete-one.helper.d.ts +2 -2
- package/src/{modules → routes}/delete-one/delete-one.helper.js +6 -4
- package/src/routes/delete-one/delete-one.module.d.ts +6 -0
- package/src/{modules → routes}/delete-one/delete-one.module.js +3 -3
- package/src/routes/duplicate-many/duplicate-many-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/duplicate-many/duplicate-many-controller.mixin.js +25 -3
- package/src/{modules → routes}/duplicate-many/duplicate-many.helper.d.ts +2 -2
- package/src/{modules → routes}/duplicate-many/duplicate-many.helper.js +6 -4
- package/src/routes/duplicate-many/duplicate-many.module.d.ts +6 -0
- package/src/{modules → routes}/duplicate-many/duplicate-many.module.js +3 -3
- package/src/routes/duplicate-one/duplicate-one-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/duplicate-one/duplicate-one-controller.mixin.js +25 -3
- package/src/{modules → routes}/duplicate-one/duplicate-one.helper.d.ts +2 -2
- package/src/{modules → routes}/duplicate-one/duplicate-one.helper.js +6 -4
- package/src/routes/duplicate-one/duplicate-one.module.d.ts +6 -0
- package/src/{modules → routes}/duplicate-one/duplicate-one.module.js +3 -3
- package/src/routes/get-many/get-many-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/get-many/get-many-controller.mixin.js +28 -6
- package/src/routes/get-many/get-many-service.interface.js +2 -0
- package/src/{modules → routes}/get-many/get-many.helper.d.ts +2 -2
- package/src/{modules → routes}/get-many/get-many.helper.js +6 -4
- package/src/routes/get-many/get-many.module.d.ts +6 -0
- package/src/{modules → routes}/get-many/get-many.module.js +3 -3
- package/src/routes/get-one/get-one-controller.interface.js +2 -0
- package/src/routes/get-one/get-one-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/get-one/get-one-controller.mixin.js +25 -3
- package/src/routes/get-one/get-one-service.interface.js +2 -0
- package/src/{modules → routes}/get-one/get-one.helper.d.ts +2 -2
- package/src/{modules → routes}/get-one/get-one.helper.js +6 -4
- package/src/routes/get-one/get-one.module.d.ts +6 -0
- package/src/{modules → routes}/get-one/get-one.module.js +3 -3
- package/src/routes/index.d.ts +11 -0
- package/src/routes/index.js +27 -0
- package/src/routes/replace-one/replace-one-controller.interface.js +2 -0
- package/src/routes/replace-one/replace-one-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/replace-one/replace-one-controller.mixin.js +25 -3
- package/src/routes/replace-one/replace-one-service.interface.js +2 -0
- package/src/{modules → routes}/replace-one/replace-one.helper.d.ts +2 -2
- package/src/{modules → routes}/replace-one/replace-one.helper.js +6 -4
- package/src/routes/replace-one/replace-one.module.d.ts +6 -0
- package/src/{modules → routes}/replace-one/replace-one.module.js +3 -3
- package/src/routes/update-many/update-many-controller.interface.js +2 -0
- package/src/routes/update-many/update-many-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/update-many/update-many-controller.mixin.js +25 -3
- package/src/routes/update-many/update-many-service.interface.js +2 -0
- package/src/{modules → routes}/update-many/update-many.helper.d.ts +2 -2
- package/src/{modules → routes}/update-many/update-many.helper.js +6 -4
- package/src/routes/update-many/update-many.module.d.ts +6 -0
- package/src/{modules → routes}/update-many/update-many.module.js +3 -3
- package/src/routes/update-one/update-one-controller.interface.js +2 -0
- package/src/routes/update-one/update-one-controller.mixin.d.ts +6 -0
- package/src/{modules → routes}/update-one/update-one-controller.mixin.js +25 -3
- package/src/routes/update-one/update-one-service.interface.js +2 -0
- package/src/{modules → routes}/update-one/update-one.helper.d.ts +2 -2
- package/src/{modules → routes}/update-one/update-one.helper.js +6 -4
- package/src/routes/update-one/update-one.module.d.ts +6 -0
- package/src/{modules → routes}/update-one/update-one.module.js +3 -3
- package/src/services/{base.service.d.ts → base/base.service.d.ts} +1 -1
- package/src/services/{base.service.js → base/base.service.js} +2 -2
- package/src/services/bcrypt/bcrypt.service.d.ts +5 -0
- package/src/services/bcrypt/bcrypt.service.js +26 -0
- package/src/services/dynamic-api-global-state/dynamic-api-global-state.service.d.ts +11 -0
- package/src/services/dynamic-api-global-state/dynamic-api-global-state.service.js +36 -0
- package/src/services/index.d.ts +3 -1
- package/src/services/index.js +3 -1
- package/src/version.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/src/builders/route-decorators.builder.d.ts +0 -20
- package/src/modules/create-many/create-many-controller.mixin.d.ts +0 -6
- package/src/modules/create-one/create-one-controller.mixin.d.ts +0 -6
- package/src/modules/create-one/create-one.module.d.ts +0 -6
- package/src/modules/delete-many/delete-many-controller.mixin.d.ts +0 -6
- package/src/modules/delete-many/delete-many.module.d.ts +0 -6
- package/src/modules/delete-one/delete-one-controller.mixin.d.ts +0 -6
- package/src/modules/delete-one/delete-one.module.d.ts +0 -6
- package/src/modules/duplicate-many/duplicate-many-controller.mixin.d.ts +0 -6
- package/src/modules/duplicate-many/duplicate-many.module.d.ts +0 -6
- package/src/modules/duplicate-one/duplicate-one-controller.mixin.d.ts +0 -6
- package/src/modules/duplicate-one/duplicate-one.module.d.ts +0 -6
- package/src/modules/get-many/get-many-controller.mixin.d.ts +0 -6
- package/src/modules/get-many/get-many.module.d.ts +0 -6
- package/src/modules/get-one/get-one-controller.mixin.d.ts +0 -6
- package/src/modules/get-one/get-one.module.d.ts +0 -6
- package/src/modules/replace-one/replace-one-controller.mixin.d.ts +0 -6
- package/src/modules/replace-one/replace-one.module.d.ts +0 -6
- package/src/modules/update-many/update-many-controller.mixin.d.ts +0 -6
- package/src/modules/update-many/update-many.module.d.ts +0 -6
- package/src/modules/update-one/update-one-controller.mixin.d.ts +0 -6
- package/src/modules/update-one/update-one.module.d.ts +0 -6
- /package/src/{modules/create-many/create-many-controller.interface.js → interfaces/decorator-builder.interface.js} +0 -0
- /package/src/{modules/create-many/create-many-service.interface.js → interfaces/dynamic-api-global-state.interface.js} +0 -0
- /package/src/{modules/create-one/create-one-controller.interface.js → interfaces/dynamic-api-policy-handler.interface.js} +0 -0
- /package/src/{modules/create-one/create-one-service.interface.js → interfaces/dynamic-api-route-dtos-bundle.type.js} +0 -0
- /package/src/{modules/delete-many/delete-many-controller.interface.js → interfaces/dynamic-api-route-module.type.js} +0 -0
- /package/src/{modules/delete-many/delete-many-service.interface.js → interfaces/dynamic-api-route-type.type.js} +0 -0
- /package/src/modules/{delete-one/delete-one-controller.interface.js → auth/interfaces/auth-controller.interface.js} +0 -0
- /package/src/modules/{delete-one/delete-one-service.interface.js → auth/interfaces/auth-options.interface.js} +0 -0
- /package/src/modules/{duplicate-many/duplicate-many-controller.interface.js → auth/interfaces/auth-service.interface.js} +0 -0
- /package/src/{modules → routes}/create-many/base-create-many.service.d.ts +0 -0
- /package/src/{modules → routes}/create-many/base-create-many.service.js +0 -0
- /package/src/{modules → routes}/create-many/create-many-controller.interface.d.ts +0 -0
- /package/src/{modules/duplicate-many/duplicate-many-service.interface.js → routes/create-many/create-many-controller.interface.js} +0 -0
- /package/src/{modules → routes}/create-many/create-many-service.interface.d.ts +0 -0
- /package/src/{modules/duplicate-one/duplicate-one-controller.interface.js → routes/create-many/create-many-service.interface.js} +0 -0
- /package/src/{modules → routes}/create-many/index.d.ts +0 -0
- /package/src/{modules → routes}/create-many/index.js +0 -0
- /package/src/{modules → routes}/create-one/base-create-one.service.d.ts +0 -0
- /package/src/{modules → routes}/create-one/base-create-one.service.js +0 -0
- /package/src/{modules → routes}/create-one/create-one-controller.interface.d.ts +0 -0
- /package/src/{modules/duplicate-one/duplicate-one-service.interface.js → routes/create-one/create-one-controller.interface.js} +0 -0
- /package/src/{modules → routes}/create-one/create-one-service.interface.d.ts +0 -0
- /package/src/{modules/get-many/get-many-controller.interface.js → routes/create-one/create-one-service.interface.js} +0 -0
- /package/src/{modules → routes}/create-one/index.d.ts +0 -0
- /package/src/{modules → routes}/create-one/index.js +0 -0
- /package/src/{modules → routes}/delete-many/base-delete-many.service.d.ts +0 -0
- /package/src/{modules → routes}/delete-many/base-delete-many.service.js +0 -0
- /package/src/{modules → routes}/delete-many/delete-many-controller.interface.d.ts +0 -0
- /package/src/{modules/get-many/get-many-service.interface.js → routes/delete-many/delete-many-controller.interface.js} +0 -0
- /package/src/{modules → routes}/delete-many/delete-many-service.interface.d.ts +0 -0
- /package/src/{modules/get-one/get-one-controller.interface.js → routes/delete-many/delete-many-service.interface.js} +0 -0
- /package/src/{modules → routes}/delete-many/delete-many.presenter.d.ts +0 -0
- /package/src/{modules → routes}/delete-many/delete-many.presenter.js +0 -0
- /package/src/{modules → routes}/delete-many/index.d.ts +0 -0
- /package/src/{modules → routes}/delete-many/index.js +0 -0
- /package/src/{modules → routes}/delete-one/base-delete-one.service.d.ts +0 -0
- /package/src/{modules → routes}/delete-one/base-delete-one.service.js +0 -0
- /package/src/{modules → routes}/delete-one/delete-one-controller.interface.d.ts +0 -0
- /package/src/{modules/get-one/get-one-service.interface.js → routes/delete-one/delete-one-controller.interface.js} +0 -0
- /package/src/{modules → routes}/delete-one/delete-one-service.interface.d.ts +0 -0
- /package/src/{modules/replace-one/replace-one-controller.interface.js → routes/delete-one/delete-one-service.interface.js} +0 -0
- /package/src/{modules → routes}/delete-one/delete-one.presenter.d.ts +0 -0
- /package/src/{modules → routes}/delete-one/delete-one.presenter.js +0 -0
- /package/src/{modules → routes}/delete-one/index.d.ts +0 -0
- /package/src/{modules → routes}/delete-one/index.js +0 -0
- /package/src/{modules → routes}/duplicate-many/base-duplicate-many.service.d.ts +0 -0
- /package/src/{modules → routes}/duplicate-many/base-duplicate-many.service.js +0 -0
- /package/src/{modules → routes}/duplicate-many/duplicate-many-controller.interface.d.ts +0 -0
- /package/src/{modules/replace-one/replace-one-service.interface.js → routes/duplicate-many/duplicate-many-controller.interface.js} +0 -0
- /package/src/{modules → routes}/duplicate-many/duplicate-many-service.interface.d.ts +0 -0
- /package/src/{modules/update-many/update-many-controller.interface.js → routes/duplicate-many/duplicate-many-service.interface.js} +0 -0
- /package/src/{modules → routes}/duplicate-many/index.d.ts +0 -0
- /package/src/{modules → routes}/duplicate-many/index.js +0 -0
- /package/src/{modules → routes}/duplicate-one/base-duplicate-one.service.d.ts +0 -0
- /package/src/{modules → routes}/duplicate-one/base-duplicate-one.service.js +0 -0
- /package/src/{modules → routes}/duplicate-one/duplicate-one-controller.interface.d.ts +0 -0
- /package/src/{modules/update-many/update-many-service.interface.js → routes/duplicate-one/duplicate-one-controller.interface.js} +0 -0
- /package/src/{modules → routes}/duplicate-one/duplicate-one-service.interface.d.ts +0 -0
- /package/src/{modules/update-one/update-one-controller.interface.js → routes/duplicate-one/duplicate-one-service.interface.js} +0 -0
- /package/src/{modules → routes}/duplicate-one/index.d.ts +0 -0
- /package/src/{modules → routes}/duplicate-one/index.js +0 -0
- /package/src/{modules → routes}/get-many/base-get-many.service.d.ts +0 -0
- /package/src/{modules → routes}/get-many/base-get-many.service.js +0 -0
- /package/src/{modules → routes}/get-many/get-many-controller.interface.d.ts +0 -0
- /package/src/{modules/update-one/update-one-service.interface.js → routes/get-many/get-many-controller.interface.js} +0 -0
- /package/src/{modules → routes}/get-many/get-many-service.interface.d.ts +0 -0
- /package/src/{modules → routes}/get-many/index.d.ts +0 -0
- /package/src/{modules → routes}/get-many/index.js +0 -0
- /package/src/{modules → routes}/get-one/base-get-one.service.d.ts +0 -0
- /package/src/{modules → routes}/get-one/base-get-one.service.js +0 -0
- /package/src/{modules → routes}/get-one/get-one-controller.interface.d.ts +0 -0
- /package/src/{modules → routes}/get-one/get-one-service.interface.d.ts +0 -0
- /package/src/{modules → routes}/get-one/index.d.ts +0 -0
- /package/src/{modules → routes}/get-one/index.js +0 -0
- /package/src/{modules → routes}/replace-one/base-replace-one.service.d.ts +0 -0
- /package/src/{modules → routes}/replace-one/base-replace-one.service.js +0 -0
- /package/src/{modules → routes}/replace-one/index.d.ts +0 -0
- /package/src/{modules → routes}/replace-one/index.js +0 -0
- /package/src/{modules → routes}/replace-one/replace-one-controller.interface.d.ts +0 -0
- /package/src/{modules → routes}/replace-one/replace-one-service.interface.d.ts +0 -0
- /package/src/{modules → routes}/update-many/base-update-many.service.d.ts +0 -0
- /package/src/{modules → routes}/update-many/base-update-many.service.js +0 -0
- /package/src/{modules → routes}/update-many/index.d.ts +0 -0
- /package/src/{modules → routes}/update-many/index.js +0 -0
- /package/src/{modules → routes}/update-many/update-many-controller.interface.d.ts +0 -0
- /package/src/{modules → routes}/update-many/update-many-service.interface.d.ts +0 -0
- /package/src/{modules → routes}/update-one/base-update-one.service.d.ts +0 -0
- /package/src/{modules → routes}/update-one/base-update-one.service.js +0 -0
- /package/src/{modules → routes}/update-one/index.d.ts +0 -0
- /package/src/{modules → routes}/update-one/index.js +0 -0
- /package/src/{modules → routes}/update-one/update-one-controller.interface.d.ts +0 -0
- /package/src/{modules → routes}/update-one/update-one-service.interface.d.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
|
|
3
|
+
## [1.4.1](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v1.4.0...v1.4.1) (2024-03-12)
|
|
4
|
+
|
|
5
|
+
## [1.4.0](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v1.3.3...v1.4.0) (2024-03-11)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### authentication
|
|
9
|
+
|
|
10
|
+
* **authentication:** add register ability predicate ([811b085](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/811b0853ed836ce33a7a56312c3e045b5f73f5ee))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### api
|
|
14
|
+
|
|
15
|
+
* **api:** add authentication ([a692b7b](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/a692b7b0fcd774dc5152b9f82ed22107c543110a))
|
|
16
|
+
* **api:** add casl ability to control route access ([6202a24](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/6202a247d301a7a72ce47f596a288d66724999f1))
|
|
17
|
+
|
|
3
18
|
## [1.3.3](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v1.3.2...v1.3.3) (2024-03-06)
|
|
4
19
|
|
|
5
20
|
|
package/README.md
CHANGED
|
@@ -67,6 +67,17 @@
|
|
|
67
67
|
npm install --save mongodb-dynamic-api
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
___
|
|
71
|
+
|
|
72
|
+
### Table of Contents
|
|
73
|
+
|
|
74
|
+
[Introduction](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#how-to-enjoy-it)
|
|
75
|
+
- [Swagger UI](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#swagger-ui-optional-but-strongly-recommended)
|
|
76
|
+
- [Validation](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#validation-optional)
|
|
77
|
+
- [Versioning](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#versioning-optional)
|
|
78
|
+
- [Caching](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#caching-enabled-by-default)
|
|
79
|
+
- [Authentication](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#authentication-optional)
|
|
80
|
+
- [Casl](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#casl-only-with-authentication)
|
|
70
81
|
|
|
71
82
|
---
|
|
72
83
|
### HOW TO ENJOY IT
|
|
@@ -85,13 +96,13 @@ npm i -S mongodb-dynamic-api
|
|
|
85
96
|
- Add `DynamicApiModule.forRoot` to your `app.module.ts` and pass your **MongoDB connection string** to the method.
|
|
86
97
|
|
|
87
98
|
```typescript
|
|
88
|
-
// app.module.ts
|
|
99
|
+
// src/app.module.ts
|
|
89
100
|
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
90
101
|
|
|
91
102
|
@Module({
|
|
92
103
|
imports: [
|
|
93
104
|
DynamicApiModule.forRoot(
|
|
94
|
-
'mongodb
|
|
105
|
+
'mongodb-uri', // <- replace by your own MongoDB connection string
|
|
95
106
|
),
|
|
96
107
|
// ...
|
|
97
108
|
],
|
|
@@ -103,19 +114,19 @@ export class AppModule {}
|
|
|
103
114
|
**Basic Usage**
|
|
104
115
|
|
|
105
116
|
- Ok, now let's add our first content with just 2 files. It will be a simple `User` with a `name` and an `email` field.
|
|
106
|
-
- We use the `@Schema` and `@Prop` decorators from the
|
|
117
|
+
- We use the `@Schema` and `@Prop` decorators from the <a href="https://docs.nestjs.com/techniques/mongodb#model-injection" target="_blank">@nestjs/mongoose</a> package to define our MongoDB model.
|
|
107
118
|
|
|
108
119
|
|
|
109
120
|
- You must extend the `BaseEntity` (or `SoftDeletableEntity`) class from the `mongodb-dynamic-api` package **for all your collection models**.
|
|
110
121
|
- Just create a new file `user.ts` and add the following code.
|
|
111
122
|
|
|
112
123
|
```typescript
|
|
113
|
-
// users/user.ts
|
|
124
|
+
// src/users/user.ts
|
|
114
125
|
import { Prop, Schema } from '@nestjs/mongoose';
|
|
115
126
|
import { BaseEntity } from 'mongodb-dynamic-api';
|
|
116
127
|
|
|
117
128
|
@Schema({ collection: 'users' })
|
|
118
|
-
export class User extends BaseEntity {
|
|
129
|
+
export class User extends BaseEntity { // <- extends BaseEntity
|
|
119
130
|
@Prop({ type: String, required: true })
|
|
120
131
|
name: string;
|
|
121
132
|
|
|
@@ -124,12 +135,12 @@ export class User extends BaseEntity {
|
|
|
124
135
|
}
|
|
125
136
|
```
|
|
126
137
|
|
|
127
|
-
- Then we will use the `DynamicApiModule.forFeature` method to add the `User`
|
|
138
|
+
- Then we will use the `DynamicApiModule.forFeature` method to add the `User` API to our application.
|
|
128
139
|
- We pass the `User` class to the `entity` property and specify the path `users` to the `controllerOptions` property.
|
|
129
140
|
- Create a new file `users.module.ts` and add the following code.
|
|
130
141
|
|
|
131
142
|
```typescript
|
|
132
|
-
// users/users.module.ts
|
|
143
|
+
// src/users/users.module.ts
|
|
133
144
|
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
134
145
|
import { User } from './user';
|
|
135
146
|
|
|
@@ -149,7 +160,7 @@ export class UsersModule {}
|
|
|
149
160
|
- Last step, add the `UsersModule` to the **imports** in the `app.module.ts` after the `DynamicApiModule.forRoot` method.
|
|
150
161
|
|
|
151
162
|
```typescript
|
|
152
|
-
// app.module.ts
|
|
163
|
+
// src/app.module.ts
|
|
153
164
|
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
154
165
|
import { UsersModule } from './users/users.module';
|
|
155
166
|
|
|
@@ -183,6 +194,15 @@ export class AppModule {}
|
|
|
183
194
|
| **POST /users/duplicate** <br>*Duplicate many* | `{ name?: string; email?: string; }` | x | `ids: string[]` |
|
|
184
195
|
| **POST /users/duplicate/:id**<br>*Duplicate one* | `{ name?: string; email?: string; }` | `id: string` | x |
|
|
185
196
|
|
|
197
|
+
___
|
|
198
|
+
|
|
199
|
+
- TOC > [Validation](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#validation-optional)
|
|
200
|
+
/ [Versioning](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#versioning-optional)
|
|
201
|
+
/ [Caching](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#caching-enabled-by-default)
|
|
202
|
+
/ [Authentication](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#authentication-optional)
|
|
203
|
+
/ [Casl](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#casl-only-with-authentication)
|
|
204
|
+
|
|
205
|
+
___
|
|
186
206
|
|
|
187
207
|
### [Swagger UI](https://docs.nestjs.com/openapi/introduction#document-options) (optional but strongly recommended)
|
|
188
208
|
`function enableDynamicAPISwagger(app: INestApplication, options?: DynamicAPISwaggerOptions): void`
|
|
@@ -190,7 +210,7 @@ export class AppModule {}
|
|
|
190
210
|
**Configuration**
|
|
191
211
|
|
|
192
212
|
```typescript
|
|
193
|
-
// main.ts
|
|
213
|
+
// src/main.ts
|
|
194
214
|
import { enableDynamicAPISwagger } from 'mongodb-dynamic-api';
|
|
195
215
|
|
|
196
216
|
async function bootstrap() {
|
|
@@ -212,7 +232,7 @@ Add the `@ApiProperty` | `@ApiPropertyOptional` decorators to your class propert
|
|
|
212
232
|
<br>Let's add an optional company field to the `User` class.
|
|
213
233
|
|
|
214
234
|
```typescript
|
|
215
|
-
// user.ts
|
|
235
|
+
// src/users/user.ts
|
|
216
236
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
217
237
|
|
|
218
238
|
@Schema({ collection: 'users' })
|
|
@@ -235,16 +255,25 @@ go to the swagger API path (default to `/dynamic-api`) and you will see the auto
|
|
|
235
255
|
|
|
236
256
|

|
|
237
257
|
|
|
238
|
-
<a href="https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README/swagger.md" target="_blank">See more User API screenshots</a>
|
|
258
|
+
<a href="https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README/swagger-user-api.md" target="_blank">See more User API screenshots</a>
|
|
259
|
+
|
|
260
|
+
___
|
|
261
|
+
|
|
262
|
+
- TOC > [Introduction](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#how-to-enjoy-it)
|
|
263
|
+
/ [Versioning](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#versioning-optional)
|
|
264
|
+
/ [Caching](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#caching-enabled-by-default)
|
|
265
|
+
/ [Authentication](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#authentication-optional)
|
|
266
|
+
/ [Casl](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#casl-only-with-authentication)
|
|
239
267
|
|
|
240
268
|
___
|
|
269
|
+
|
|
241
270
|
### [Validation](https://docs.nestjs.com/techniques/validation#using-the-built-in-validationpipe) (optional)
|
|
242
|
-
|
|
271
|
+
<br>`function enableDynamicAPIValidation(app: INestApplication, options?: ValidationPipeOptions): void`
|
|
243
272
|
|
|
244
273
|
**Configuration**
|
|
245
274
|
|
|
246
275
|
```typescript
|
|
247
|
-
// main.ts
|
|
276
|
+
// src/main.ts
|
|
248
277
|
import { enableDynamicAPIValidation } from 'mongodb-dynamic-api';
|
|
249
278
|
|
|
250
279
|
async function bootstrap() {
|
|
@@ -262,7 +291,7 @@ or in each route object defined in the routes property.
|
|
|
262
291
|
<br>*If the options are specified in 2, the options specified in the route will have priority.*
|
|
263
292
|
|
|
264
293
|
```typescript
|
|
265
|
-
// users.module.ts
|
|
294
|
+
// src/users/users.module.ts
|
|
266
295
|
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
267
296
|
import { User } from './user';
|
|
268
297
|
|
|
@@ -296,7 +325,7 @@ Use the `Class validator` <a href="https://github.com/typestack/class-validator?
|
|
|
296
325
|
<br>Let's add `IsEmail` decorator to the `email` field.
|
|
297
326
|
|
|
298
327
|
```typescript
|
|
299
|
-
// user.ts
|
|
328
|
+
// src/users/user.ts
|
|
300
329
|
import { IsEmail } from 'class-validator';
|
|
301
330
|
|
|
302
331
|
@Schema({ collection: 'users' })
|
|
@@ -320,8 +349,16 @@ Ok, now if you try to create a new user with an invalid email, you will get a `4
|
|
|
320
349
|
|
|
321
350
|

|
|
322
351
|
|
|
352
|
+
___
|
|
353
|
+
|
|
354
|
+
- TOC > [Introduction](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#how-to-enjoy-it)
|
|
355
|
+
/ [Swagger UI](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#swagger-ui-optional-but-strongly-recommended)
|
|
356
|
+
/ [Caching](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#caching-enabled-by-default)
|
|
357
|
+
/ [Authentication](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#authentication-optional)
|
|
358
|
+
/ [Casl](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#casl-only-with-authentication)
|
|
323
359
|
|
|
324
360
|
___
|
|
361
|
+
|
|
325
362
|
### [Versioning](https://docs.nestjs.com/techniques/versioning) (optional)
|
|
326
363
|
`function enableDynamicAPIVersioning(app: INestApplication, options?: VersioningOptions): void`
|
|
327
364
|
|
|
@@ -333,7 +370,7 @@ The `enableDynamicAPIVersioning` function will automatically add versioning to t
|
|
|
333
370
|
**Configuration**
|
|
334
371
|
|
|
335
372
|
```typescript
|
|
336
|
-
// main.ts
|
|
373
|
+
// src/main.ts
|
|
337
374
|
import { enableDynamicAPIVersioning } from 'mongodb-dynamic-api';
|
|
338
375
|
|
|
339
376
|
async function bootstrap() {
|
|
@@ -353,7 +390,7 @@ Pass the `version` property to the `controllerOptions` object or to the `route`
|
|
|
353
390
|
Let's add a new version to the `User` content.
|
|
354
391
|
|
|
355
392
|
```typescript
|
|
356
|
-
// create-one-user-v2.dto.ts
|
|
393
|
+
// src/users/create-one-user-v2.dto.ts
|
|
357
394
|
import { ApiProperty, ApiPropertyOptional, PickType } from '@nestjs/swagger';
|
|
358
395
|
import { IsOptional, IsString } from 'class-validator';
|
|
359
396
|
import { User } from './user';
|
|
@@ -375,7 +412,7 @@ export class CreateOneUserV2Dto extends PickType(User, ['email']) {
|
|
|
375
412
|
```
|
|
376
413
|
|
|
377
414
|
```typescript
|
|
378
|
-
// user-v2.presenter.ts
|
|
415
|
+
// src/users/user-v2.presenter.ts
|
|
379
416
|
import { ApiProperty, ApiPropertyOptional, PickType } from '@nestjs/swagger';
|
|
380
417
|
import { User } from './user';
|
|
381
418
|
|
|
@@ -392,7 +429,7 @@ export class UserV2Presenter extends PickType(User, ['email']) {
|
|
|
392
429
|
```
|
|
393
430
|
|
|
394
431
|
```typescript
|
|
395
|
-
// users.module.ts
|
|
432
|
+
// src/users/users.module.ts
|
|
396
433
|
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
397
434
|
import { User } from './user';
|
|
398
435
|
import { CreateOneUserV2Dto } from './create-one-user-v2.dto';
|
|
@@ -428,6 +465,13 @@ Great, now you have a versioned User API, and you can access it at the `/v1/user
|
|
|
428
465
|
|
|
429
466
|

|
|
430
467
|
|
|
468
|
+
___
|
|
469
|
+
|
|
470
|
+
- TOC > [Introduction](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#how-to-enjoy-it)
|
|
471
|
+
/ [Swagger UI](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#swagger-ui-optional-but-strongly-recommended)
|
|
472
|
+
/ [Validation](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#validation-optional)
|
|
473
|
+
/ [Authentication](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#authentication-optional)
|
|
474
|
+
/ [Casl](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#casl-only-with-authentication)
|
|
431
475
|
|
|
432
476
|
___
|
|
433
477
|
|
|
@@ -439,7 +483,7 @@ By default, the caching is activated globally for all the routes. It uses the ne
|
|
|
439
483
|
**Configuration**
|
|
440
484
|
|
|
441
485
|
```typescript
|
|
442
|
-
// app.module.ts
|
|
486
|
+
// src/app.module.ts
|
|
443
487
|
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
444
488
|
|
|
445
489
|
@Module({
|
|
@@ -463,7 +507,7 @@ export class AppModule {}
|
|
|
463
507
|
**[Not recommended]** The cache can also be disabled globally with the `useGlobalCache` property set to `false` in the `DynamicApiModule.forRoot` method.
|
|
464
508
|
|
|
465
509
|
```typescript
|
|
466
|
-
// app.module.ts
|
|
510
|
+
// src/app.module.ts
|
|
467
511
|
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
468
512
|
|
|
469
513
|
@Module({
|
|
@@ -505,6 +549,417 @@ When you request the `/users` route with the `GET` method, the response will be
|
|
|
505
549
|
```
|
|
506
550
|

|
|
507
551
|
|
|
552
|
+
___
|
|
553
|
+
|
|
554
|
+
- TOC > [Introduction](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#how-to-enjoy-it)
|
|
555
|
+
/ [Swagger UI](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#swagger-ui-optional-but-strongly-recommended)
|
|
556
|
+
/ [Validation](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#validation-optional)
|
|
557
|
+
/ [Versioning](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#versioning-optional)
|
|
558
|
+
/ [Casl](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#casl-only-with-authentication)
|
|
559
|
+
|
|
560
|
+
___
|
|
561
|
+
|
|
562
|
+
### [Authentication](https://docs.nestjs.com/security/authorization#integrating-casl) (optional)
|
|
563
|
+
|
|
564
|
+
An authentication strategy like <a href="https://docs.nestjs.com/security/authentication#jwt-token" target="_blank">JWT</a> is already implemented in the Dynamic API.
|
|
565
|
+
All you have to do is to pass the User object and some options to the `useAuth` property of the `DynamicApiModule.forRoot` method.
|
|
566
|
+
|
|
567
|
+
**Configuration**
|
|
568
|
+
|
|
569
|
+
Ok, let's update our `User` class to add a `password` field.
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
// src/users/user.ts
|
|
573
|
+
import { IsEmail } from 'class-validator';
|
|
574
|
+
|
|
575
|
+
@Schema({ collection: 'users' })
|
|
576
|
+
export class User extends BaseEntity {
|
|
577
|
+
@ApiProperty()
|
|
578
|
+
@IsNotEmpty()
|
|
579
|
+
@IsString()
|
|
580
|
+
@Prop({ type: String, required: true })
|
|
581
|
+
email: string;
|
|
582
|
+
|
|
583
|
+
@Exclude()
|
|
584
|
+
@IsNotEmpty()
|
|
585
|
+
@IsString()
|
|
586
|
+
@Prop({ type: String, required: true })
|
|
587
|
+
password: string;
|
|
588
|
+
|
|
589
|
+
@ApiPropertyOptional({ type: Boolean, default: false })
|
|
590
|
+
@IsBoolean()
|
|
591
|
+
@IsOptional()
|
|
592
|
+
@Prop({ type: Boolean, default: false })
|
|
593
|
+
isAdmin: boolean;
|
|
594
|
+
|
|
595
|
+
@ApiPropertyOptional()
|
|
596
|
+
@IsNotEmpty()
|
|
597
|
+
@IsString()
|
|
598
|
+
@IsOptional()
|
|
599
|
+
@Prop({ type: String })
|
|
600
|
+
company?: string;
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Now, we are going to add the `useAuth` property to the `DynamicApiModule.forRoot` method and pass the `User` object and some options.
|
|
605
|
+
<br>By default, the login field is `email` and the password field is `password`. Your User class must have these fields.
|
|
606
|
+
<br>If you want to use other fields, you can specify them in the `user` property by passing the `loginField` and / or `passwordField` properties.
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
// src/app.module.ts
|
|
610
|
+
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
611
|
+
import { User } from './users/user';
|
|
612
|
+
import { UsersModule } from './users/users.module';
|
|
613
|
+
|
|
614
|
+
@Module({
|
|
615
|
+
imports: [
|
|
616
|
+
DynamicApiModule.forRoot('...', {
|
|
617
|
+
// ...,
|
|
618
|
+
useAuth: { // <- add this
|
|
619
|
+
user: {
|
|
620
|
+
entity: User, // <- put here the entity which will represent a User of your API
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
}),
|
|
624
|
+
UsersModule,
|
|
625
|
+
],
|
|
626
|
+
controllers: [AppController],
|
|
627
|
+
providers: [AppService],
|
|
628
|
+
})
|
|
629
|
+
export class AppModule {}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
By setting the `useAuth` property, the Dynamic API will automatically add the authentication API.
|
|
633
|
+
<br>It will add the `/auth/register`, `/auth/login`, and `/auth/account` routes to the API.
|
|
634
|
+
|
|
635
|
+
By default, only the `/auth/register` and `/auth/login` routes are public.
|
|
636
|
+
All other routes are protected and require a valid `JWT token` to access them.
|
|
637
|
+
|
|
638
|
+
**Swagger Configuration**
|
|
639
|
+
|
|
640
|
+
For Swagger users, you must enable the bearer Auth option by setting the `bearerAuth` property to `true` in the enableDynamicAPISwagger method.
|
|
641
|
+
This will add the Authorize button in the Swagger UI. This button will allow you to pass the `JWT Token` and unlock the protected routes.
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
// src/main.ts
|
|
645
|
+
import { enableDynamicAPISwagger } from 'mongodb-dynamic-api';
|
|
646
|
+
|
|
647
|
+
async function bootstrap() {
|
|
648
|
+
const app = await NestFactory.create(AppModule);
|
|
649
|
+
// ...
|
|
650
|
+
enableDynamicAPISwagger(app, {
|
|
651
|
+
// ...,
|
|
652
|
+
swaggerExtraConfig: { // <- add this line in your main.ts file
|
|
653
|
+
bearerAuth: true,
|
|
654
|
+
},
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
await app.listen(3000);
|
|
658
|
+
}
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+

|
|
662
|
+
|
|
663
|
+
<a href="https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README/swagger-authentication-api.md" target="_blank">See more Authentication API screenshots</a>
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
**Usage**
|
|
667
|
+
|
|
668
|
+
Ok let's add a new user with the `POST` method on the `/auth/register` route.
|
|
669
|
+
<br>You will receive a valid `JWT token` in the response.
|
|
670
|
+
|
|
671
|
+
```text
|
|
672
|
+
POST /auth/register
|
|
673
|
+
|
|
674
|
+
curl -X 'POST' \
|
|
675
|
+
'<your-host>/auth/register' \
|
|
676
|
+
-H 'accept: application/json' \
|
|
677
|
+
-H 'Content-Type: application/json' \
|
|
678
|
+
-d '{
|
|
679
|
+
"email": "<your-email>",
|
|
680
|
+
"password": "<your-password>" // <- the password will be hashed automatically before saving in the database
|
|
681
|
+
}'
|
|
682
|
+
```
|
|
683
|
+
```json
|
|
684
|
+
# Server response
|
|
685
|
+
{"accessToken":"<your-jwt-token>"}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
If you go to `/auth/login` and request the route with the `POST` method passing the `email` and `password` fields in the body.
|
|
689
|
+
<br>You will also receive a valid `JWT token` in the response.
|
|
690
|
+
|
|
691
|
+
```text
|
|
692
|
+
POST /auth/login
|
|
693
|
+
|
|
694
|
+
curl -X 'POST' \
|
|
695
|
+
'<your-host>/auth/login' \
|
|
696
|
+
-H 'accept: application/json' \
|
|
697
|
+
-H 'Content-Type: application/json' \
|
|
698
|
+
-d '{
|
|
699
|
+
"email": "<your-email>",
|
|
700
|
+
"password": "<your-password>"
|
|
701
|
+
}'
|
|
702
|
+
```
|
|
703
|
+
```json
|
|
704
|
+
# Server response
|
|
705
|
+
{"accessToken":"<your-jwt-token>"}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
Now let's request the `/auth/account` protected route with the `GET` method and pass our valid JWT token in the `Authorization` header.
|
|
709
|
+
|
|
710
|
+
```text
|
|
711
|
+
GET /auth/account
|
|
712
|
+
|
|
713
|
+
curl -X 'GET' \
|
|
714
|
+
'<your-host>/auth/account' \
|
|
715
|
+
-H 'accept: application/json' \
|
|
716
|
+
-H 'Authorization: Bearer <your-jwt-token>'
|
|
717
|
+
```
|
|
718
|
+
```json
|
|
719
|
+
# Server response
|
|
720
|
+
{"id":"65edc717c1ec...","email":"<your-email>"}
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
Great, now you have a fully functional authentication API.
|
|
724
|
+
|
|
725
|
+
All other routes are protected and require a valid JWT token to be accessed. You can easily make it public by adding the `isPublic` property to the `controllerOptions` object or to the `route` object in the `DynamicApiModule.forFeature` method.
|
|
726
|
+
|
|
727
|
+
```typescript
|
|
728
|
+
// src/users/users.module.ts
|
|
729
|
+
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
730
|
+
import { User } from './user';
|
|
731
|
+
|
|
732
|
+
@Module({
|
|
733
|
+
imports: [
|
|
734
|
+
DynamicApiModule.forFeature({
|
|
735
|
+
entity: User,
|
|
736
|
+
controllerOptions: {
|
|
737
|
+
path: 'users',
|
|
738
|
+
isPublic: true, // <- add this to make all user API routes public
|
|
739
|
+
},
|
|
740
|
+
// ...
|
|
741
|
+
}),
|
|
742
|
+
],
|
|
743
|
+
})
|
|
744
|
+
export class UsersModule {}
|
|
745
|
+
```
|
|
746
|
+
```typescript
|
|
747
|
+
// src/users/users.module.ts
|
|
748
|
+
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
749
|
+
import { User } from './user';
|
|
750
|
+
|
|
751
|
+
@Module({
|
|
752
|
+
imports: [
|
|
753
|
+
DynamicApiModule.forFeature({
|
|
754
|
+
entity: User,
|
|
755
|
+
controllerOptions: {
|
|
756
|
+
path: 'users',
|
|
757
|
+
},
|
|
758
|
+
routes: [
|
|
759
|
+
{ type: 'GetMany' }, // <- protected route
|
|
760
|
+
{ type: 'GetOne', isPublic: true }, // <- public route
|
|
761
|
+
{ type: 'UpdateOne' }, // <- protected route
|
|
762
|
+
{ type: 'DeleteOne' }, // <- protected route
|
|
763
|
+
],
|
|
764
|
+
}),
|
|
765
|
+
],
|
|
766
|
+
})
|
|
767
|
+
export class UsersModule {}
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
___
|
|
771
|
+
|
|
772
|
+
- TOC > [Introduction](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#how-to-enjoy-it)
|
|
773
|
+
/ [Swagger UI](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#swagger-ui-optional-but-strongly-recommended)
|
|
774
|
+
/ [Validation](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#validation-optional)
|
|
775
|
+
/ [Versioning](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#versioning-optional)
|
|
776
|
+
/ [Caching](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/develop/README.md#caching-enabled-by-default)
|
|
777
|
+
|
|
778
|
+
___
|
|
779
|
+
|
|
780
|
+
### [Casl](https://docs.nestjs.com/security/authorization#integrating-casl) (only with authentication)
|
|
781
|
+
|
|
782
|
+
Casl will allow you to condition the actions of your users for each protected route of your APIs.
|
|
783
|
+
<br>Authentication is required, you need to enable it or implement your own strategy that adds the User object in the request.
|
|
784
|
+
|
|
785
|
+
**MongoDB dynamic API** uses the `User` object in the requests to apply the ability predicates defined in the `DynamicApiModule.forFeature`.
|
|
786
|
+
<br>You can define them either **in the controller options**,
|
|
787
|
+
or **in each route object** declared in the routes property.
|
|
788
|
+
<br>*If the ability predicates are specified in 2, those defined in the route will have priority.*
|
|
789
|
+
|
|
790
|
+
**An ability predicate is an arrow function that takes a subject and the User object (optional) as arguments and returns a boolean.**
|
|
791
|
+
|
|
792
|
+
Let's create a new Article content and set the ability predicates to the `UpdateOne`, `DeleteOne` and `DeleteMany` routes.
|
|
793
|
+
|
|
794
|
+
**Configuration**
|
|
795
|
+
|
|
796
|
+
```typescript
|
|
797
|
+
// src/articles/article.ts
|
|
798
|
+
import { Prop } from '@nestjs/mongoose';
|
|
799
|
+
import { ApiProperty } from '@nestjs/swagger';
|
|
800
|
+
import { BaseEntity } from 'mongodb-dynamic-api';
|
|
801
|
+
|
|
802
|
+
export class Article extends BaseEntity {
|
|
803
|
+
@ApiProperty({ type: Boolean, default: false })
|
|
804
|
+
@Prop({ type: Boolean, default: false })
|
|
805
|
+
isPublished: boolean;
|
|
806
|
+
|
|
807
|
+
@ApiProperty()
|
|
808
|
+
@Prop({ type: String })
|
|
809
|
+
authorId: string;
|
|
810
|
+
}
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
```typescript
|
|
814
|
+
// src/articles/articles.module.ts
|
|
815
|
+
import { Module } from '@nestjs/common';
|
|
816
|
+
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
817
|
+
import { User } from '../users/user';
|
|
818
|
+
import { Article } from './article';
|
|
819
|
+
|
|
820
|
+
@Module({
|
|
821
|
+
imports: [
|
|
822
|
+
DynamicApiModule.forFeature({
|
|
823
|
+
entity: Article,
|
|
824
|
+
controllerOptions: {
|
|
825
|
+
path: 'articles',
|
|
826
|
+
abilityPredicates: [ // <- declare the ability predicates in the controller options
|
|
827
|
+
{
|
|
828
|
+
targets: ['DeleteMany', 'DeleteOne'], // <- declare the targets
|
|
829
|
+
predicate: (_: Article, user: User) => user.isAdmin, // <- add the condition
|
|
830
|
+
},
|
|
831
|
+
],
|
|
832
|
+
},
|
|
833
|
+
routes: [
|
|
834
|
+
{ type: 'GetMany', isPublic: true },
|
|
835
|
+
{ type: 'GetOne', isPublic: true },
|
|
836
|
+
{ type: 'CreateOne' },
|
|
837
|
+
{
|
|
838
|
+
type: 'UpdateOne',
|
|
839
|
+
abilityPredicate: (article: Article, user: User) => // <- declare the ability predicate in the route object
|
|
840
|
+
article.authorId === user.id && !article.isPublished,
|
|
841
|
+
},
|
|
842
|
+
],
|
|
843
|
+
}),
|
|
844
|
+
],
|
|
845
|
+
})
|
|
846
|
+
export class ArticlesModule {}
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
```typescript
|
|
850
|
+
// src/app.module.ts
|
|
851
|
+
import { Module } from '@nestjs/common';
|
|
852
|
+
import { DynamicApiModule } from 'mongodb-dynamic-api';
|
|
853
|
+
import { AppController } from './app.controller';
|
|
854
|
+
import { AppService } from './app.service';
|
|
855
|
+
import { User } from './users/user';
|
|
856
|
+
import { ArticlesModule } from './articles/articles.module';
|
|
857
|
+
|
|
858
|
+
@Module({
|
|
859
|
+
imports: [
|
|
860
|
+
DynamicApiModule.forRoot(
|
|
861
|
+
'your-mongodb-uri',
|
|
862
|
+
{
|
|
863
|
+
useAuth: {
|
|
864
|
+
user: {
|
|
865
|
+
entity: User,
|
|
866
|
+
additionalFields: {
|
|
867
|
+
toRegister: ['isAdmin'], // <- here you can set additional fields to display in the register body
|
|
868
|
+
toRequest: ['isAdmin', 'company'], // <- here you can set additional fields to the User object in the request
|
|
869
|
+
},
|
|
870
|
+
},
|
|
871
|
+
},
|
|
872
|
+
},
|
|
873
|
+
),
|
|
874
|
+
ArticlesModule,
|
|
875
|
+
],
|
|
876
|
+
controllers: [AppController],
|
|
877
|
+
providers: [AppService],
|
|
878
|
+
})
|
|
879
|
+
export class AppModule {}
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
**Usage**
|
|
884
|
+
|
|
885
|
+
First, let's create an admin user with the `POST` method on the `/auth/register` public route.
|
|
886
|
+
```text
|
|
887
|
+
POST /auth/register
|
|
888
|
+
|
|
889
|
+
curl -X 'POST' \
|
|
890
|
+
'<your-host>/auth/register' \
|
|
891
|
+
-H 'accept: application/json' \
|
|
892
|
+
-H 'Content-Type: application/json' \
|
|
893
|
+
-d '{
|
|
894
|
+
"email": "admin@test.co",
|
|
895
|
+
"isAdmin": true,
|
|
896
|
+
"password": "admin"
|
|
897
|
+
}'
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
Then, we are going to protect the `/auth/register` route by setting the `protectRegister` property to `true` and add a **register ability predicate** in the useAuth Object of the `DynamicApiModule.forRoot` method.
|
|
901
|
+
```typescript
|
|
902
|
+
// src/app.module.ts
|
|
903
|
+
@Module({
|
|
904
|
+
imports: [
|
|
905
|
+
DynamicApiModule.forRoot(
|
|
906
|
+
'your-mongodb-uri',
|
|
907
|
+
{
|
|
908
|
+
useAuth: {
|
|
909
|
+
// ...,
|
|
910
|
+
protectRegister: true, // <- add this line
|
|
911
|
+
registerAbilityPredicate: (user: User) => user.isAdmin,
|
|
912
|
+
},
|
|
913
|
+
},
|
|
914
|
+
),
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
Ok, now let's create a non admin user with the `POST` method on the `/auth/register` route.
|
|
918
|
+
```text
|
|
919
|
+
POST /auth/register
|
|
920
|
+
|
|
921
|
+
curl -X 'POST' \
|
|
922
|
+
'<your-host>/auth/register' \
|
|
923
|
+
-H 'accept: application/json' \
|
|
924
|
+
-H 'Content-Type: application/json' \
|
|
925
|
+
-d '{
|
|
926
|
+
"email": "toto@test.co",
|
|
927
|
+
"password": "toto"
|
|
928
|
+
}'
|
|
929
|
+
```
|
|
930
|
+
```json
|
|
931
|
+
# Server response
|
|
932
|
+
{"accessToken":"<toto-jwt-token>"}
|
|
933
|
+
```
|
|
934
|
+
|
|
935
|
+
Next, under toto's account (not admin), we will try to register a new user with the `POST` method on the `/auth/register` route.
|
|
936
|
+
<br>The register ability predicate will return `false` and we will receive a `403 Forbidden` error.
|
|
937
|
+
|
|
938
|
+
```text
|
|
939
|
+
POST /auth/register
|
|
940
|
+
|
|
941
|
+
curl -X 'POST' \
|
|
942
|
+
'http://localhost:5000/auth/register' \
|
|
943
|
+
-H 'accept: application/json' \
|
|
944
|
+
-H 'Authorization: Bearer <toto-jwt-token>' \
|
|
945
|
+
-H 'Content-Type: application/json' \
|
|
946
|
+
-d '{
|
|
947
|
+
"email": "bill@test.co",
|
|
948
|
+
"password": "bill"
|
|
949
|
+
}'
|
|
950
|
+
```
|
|
951
|
+
```json
|
|
952
|
+
# Server response
|
|
953
|
+
{
|
|
954
|
+
"message": "Forbidden resource",
|
|
955
|
+
"error": "Forbidden",
|
|
956
|
+
"statusCode": 403
|
|
957
|
+
}
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
The register route is now well protected and only an admin user can create new users.
|
|
961
|
+
|
|
962
|
+
|
|
508
963
|
___
|
|
509
964
|
|
|
510
965
|
More coming soon...
|