arkos 1.3.1-beta → 1.3.2-beta
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/dist/cjs/app.js +139 -1
- package/dist/cjs/exports/auth/index.js +6 -1
- package/dist/cjs/exports/controllers/index.js +11 -1
- package/dist/cjs/exports/error-handler/index.js +11 -1
- package/dist/cjs/exports/index.js +12 -1
- package/dist/cjs/exports/middlewares/index.js +7 -1
- package/dist/cjs/exports/prisma/index.js +13 -1
- package/dist/cjs/exports/services/index.js +48 -1
- package/dist/cjs/exports/utils/index.js +44 -1
- package/dist/cjs/exports/validation/index.js +11 -1
- package/dist/cjs/modules/auth/auth.controller.js +229 -1
- package/dist/cjs/modules/auth/auth.controller.js.map +1 -1
- package/dist/cjs/modules/auth/auth.router.js +82 -1
- package/dist/cjs/modules/auth/auth.router.js.map +1 -1
- package/dist/cjs/modules/auth/auth.service.js +226 -1
- package/dist/cjs/modules/auth/utils/auth-error-objects.js +10 -1
- package/dist/cjs/modules/auth/utils/helpers/auth.controller.helpers.js +83 -1
- package/dist/cjs/modules/auth/utils/services/auth-action.service.js +92 -1
- package/dist/cjs/modules/auth/utils/services/auth-action.service.js.map +1 -1
- package/dist/cjs/modules/base/base.controller.js +172 -1
- package/dist/cjs/modules/base/base.middlewares.js +92 -1
- package/dist/cjs/modules/base/base.router.js +22 -1
- package/dist/cjs/modules/base/base.service.js +507 -1
- package/dist/cjs/modules/base/base.service.js.map +1 -1
- package/dist/cjs/modules/base/types/base.service.types.js +3 -1
- package/dist/cjs/modules/base/types/base.service.types.js.map +1 -1
- package/dist/cjs/modules/base/utils/helpers/base.controller.helpers.js +80 -1
- package/dist/cjs/modules/base/utils/helpers/base.middlewares.helpers.js +50 -1
- package/dist/cjs/modules/base/utils/helpers/base.router.helpers.js +104 -1
- package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js +208 -1
- package/dist/cjs/modules/base/utils/router-validator.js +16 -1
- package/dist/cjs/modules/base/utils/service-hooks-manager.js +19 -1
- package/dist/cjs/modules/email/email.service.js +104 -1
- package/dist/cjs/modules/error-handler/error-handler.controller.js +146 -4
- package/dist/cjs/modules/error-handler/utils/app-error.js +17 -1
- package/dist/cjs/modules/error-handler/utils/catch-async.js +21 -1
- package/dist/cjs/modules/error-handler/utils/error-handler.helpers.js +205 -3
- package/dist/cjs/modules/file-upload/file-upload.controller.js +233 -1
- package/dist/cjs/modules/file-upload/file-upload.router.js +60 -1
- package/dist/cjs/modules/file-upload/file-upload.service.js +322 -1
- package/dist/cjs/modules/file-upload/utils/helpers/file-upload.helpers.js +97 -1
- package/dist/cjs/modules/swagger/swagger.router.js +38 -1
- package/dist/cjs/modules/swagger/utils/helpers/get-authentication-json-schema-paths.js +338 -1
- package/dist/cjs/modules/swagger/utils/helpers/get-swagger-default-configs.js +64 -1
- package/dist/cjs/modules/swagger/utils/helpers/get-system-json-schema-paths.js +37 -1
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/generate-class-validator-json-schemas.js +48 -1
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/generate-prisma-json-schemas.js +32 -1
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/generate-system-json-schemas.js +49 -1
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/generate-zod-json-schemas.js +34 -1
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.js +471 -1
- package/dist/cjs/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-parent-routes-paths.js +572 -1
- package/dist/cjs/modules/swagger/utils/helpers/missing-json-schemas-generator.js +260 -1
- package/dist/cjs/modules/swagger/utils/helpers/swagger.router.helpers.js +112 -1
- package/dist/cjs/paths.js +9 -1
- package/dist/cjs/server.js +94 -5
- package/dist/cjs/types/arkos-config.js +3 -1
- package/dist/cjs/types/arkos-config.js.map +1 -1
- package/dist/cjs/types/auth.js +3 -1
- package/dist/cjs/types/index.js +11 -1
- package/dist/cjs/types/router-config.js +3 -1
- package/dist/cjs/utils/arkos-env.js +9 -1
- package/dist/cjs/utils/cli/build.js +214 -5
- package/dist/cjs/utils/cli/dev.js +154 -3
- package/dist/cjs/utils/cli/generate.js +109 -1
- package/dist/cjs/utils/cli/index.js +104 -1
- package/dist/cjs/utils/cli/index.js.map +1 -1
- package/dist/cjs/utils/cli/prisma-generate.js +120 -0
- package/dist/cjs/utils/cli/prisma-generate.js.map +1 -0
- package/dist/cjs/utils/cli/start.js +103 -1
- package/dist/cjs/utils/cli/utils/cli.helpers.js +24 -1
- package/dist/cjs/utils/cli/utils/smart-fs-watcher.js +73 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/auth-configs-template.js +36 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/auth-configs-template.js.map +1 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/controller-template.js +21 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/controller-template.js.map +1 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/hooks-template.js +201 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/hooks-template.js.map +1 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/middlewares-template.js +288 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/{generate-middlewares.js.map → middlewares-template.js.map} +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/query-options-template.js +64 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/query-options-template.js.map +1 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/router-template.js +45 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/router-template.js.map +1 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/service-template.js +29 -0
- package/dist/cjs/utils/cli/utils/template-generator/templates/service-template.js.map +1 -0
- package/dist/cjs/utils/cli/utils/template-generators.js +34 -2
- package/dist/cjs/utils/cli/utils/template-generators.js.map +1 -1
- package/dist/cjs/utils/cli/utils/watermark-stamper.js +17 -3
- package/dist/cjs/utils/dotenv.helpers.js +43 -1
- package/dist/cjs/utils/dynamic-loader.js +270 -9
- package/dist/cjs/utils/features/api.features.js +169 -1
- package/dist/cjs/utils/features/change-case.features.js +67 -1
- package/dist/cjs/utils/features/port-and-host-allocator.js +105 -1
- package/dist/cjs/utils/helpers/api.features.helpers.js +112 -1
- package/dist/cjs/utils/helpers/change-case.helpers.js +177 -1
- package/dist/cjs/utils/helpers/deepmerge.helper.js +115 -1
- package/dist/cjs/utils/helpers/dynamic-loader.helpers.js +76 -1
- package/dist/cjs/utils/helpers/fs.helpers.js +57 -1
- package/dist/cjs/utils/helpers/global.helpers.js +94 -1
- package/dist/cjs/utils/helpers/prisma.helpers.js +40 -1
- package/dist/cjs/utils/helpers/query-parser.helpers.js +45 -1
- package/dist/cjs/utils/helpers/routers.helpers.js +37 -1
- package/dist/cjs/utils/helpers/text.helpers.js +28 -1
- package/dist/cjs/utils/prisma/prisma-json-schema-generator.js +455 -1
- package/dist/cjs/utils/prisma/prisma-schema-parser.js +216 -4
- package/dist/cjs/utils/prisma/types.js +3 -1
- package/dist/cjs/utils/sheu.js +120 -1
- package/dist/cjs/utils/validate-dto.js +17 -1
- package/dist/cjs/utils/validate-schema.js +15 -1
- package/dist/esm/app.js +132 -1
- package/dist/esm/exports/auth/index.js +2 -1
- package/dist/esm/exports/controllers/index.js +4 -1
- package/dist/esm/exports/error-handler/index.js +4 -1
- package/dist/esm/exports/index.js +8 -1
- package/dist/esm/exports/middlewares/index.js +2 -1
- package/dist/esm/exports/prisma/index.js +6 -1
- package/dist/esm/exports/services/index.js +9 -1
- package/dist/esm/exports/utils/index.js +4 -1
- package/dist/esm/exports/validation/index.js +4 -1
- package/dist/esm/modules/auth/auth.controller.js +222 -1
- package/dist/esm/modules/auth/auth.controller.js.map +1 -1
- package/dist/esm/modules/auth/auth.router.js +76 -1
- package/dist/esm/modules/auth/auth.router.js.map +1 -1
- package/dist/esm/modules/auth/auth.service.js +219 -1
- package/dist/esm/modules/auth/utils/auth-error-objects.js +4 -1
- package/dist/esm/modules/auth/utils/helpers/auth.controller.helpers.js +73 -1
- package/dist/esm/modules/auth/utils/services/auth-action.service.js +90 -1
- package/dist/esm/modules/auth/utils/services/auth-action.service.js.map +1 -1
- package/dist/esm/modules/base/base.controller.js +165 -1
- package/dist/esm/modules/base/base.middlewares.js +81 -1
- package/dist/esm/modules/base/base.router.js +15 -1
- package/dist/esm/modules/base/base.service.js +500 -1
- package/dist/esm/modules/base/base.service.js.map +1 -1
- package/dist/esm/modules/base/types/base.service.types.js +2 -1
- package/dist/esm/modules/base/types/base.service.types.js.map +1 -1
- package/dist/esm/modules/base/utils/helpers/base.controller.helpers.js +76 -1
- package/dist/esm/modules/base/utils/helpers/base.middlewares.helpers.js +44 -1
- package/dist/esm/modules/base/utils/helpers/base.router.helpers.js +96 -1
- package/dist/esm/modules/base/utils/helpers/base.service.helpers.js +198 -1
- package/dist/esm/modules/base/utils/router-validator.js +14 -1
- package/dist/esm/modules/base/utils/service-hooks-manager.js +17 -1
- package/dist/esm/modules/email/email.service.js +97 -1
- package/dist/esm/modules/error-handler/error-handler.controller.js +107 -4
- package/dist/esm/modules/error-handler/utils/app-error.js +15 -1
- package/dist/esm/modules/error-handler/utils/catch-async.js +19 -1
- package/dist/esm/modules/error-handler/utils/error-handler.helpers.js +163 -3
- package/dist/esm/modules/file-upload/file-upload.controller.js +228 -1
- package/dist/esm/modules/file-upload/file-upload.router.js +54 -1
- package/dist/esm/modules/file-upload/file-upload.service.js +314 -1
- package/dist/esm/modules/file-upload/utils/helpers/file-upload.helpers.js +87 -1
- package/dist/esm/modules/swagger/swagger.router.js +32 -1
- package/dist/esm/modules/swagger/utils/helpers/get-authentication-json-schema-paths.js +333 -1
- package/dist/esm/modules/swagger/utils/helpers/get-swagger-default-configs.js +58 -1
- package/dist/esm/modules/swagger/utils/helpers/get-system-json-schema-paths.js +34 -1
- package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/generate-class-validator-json-schemas.js +42 -1
- package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/generate-prisma-json-schemas.js +26 -1
- package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/generate-system-json-schemas.js +46 -1
- package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/generate-zod-json-schemas.js +28 -1
- package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-main-routes-paths.js +465 -1
- package/dist/esm/modules/swagger/utils/helpers/json-schema-generators/prisma-models/generate-prisma-model-parent-routes-paths.js +566 -1
- package/dist/esm/modules/swagger/utils/helpers/missing-json-schemas-generator.js +255 -1
- package/dist/esm/modules/swagger/utils/helpers/swagger.router.helpers.js +101 -1
- package/dist/esm/paths.js +3 -1
- package/dist/esm/server.js +85 -5
- package/dist/esm/types/arkos-config.js +2 -1
- package/dist/esm/types/arkos-config.js.map +1 -1
- package/dist/esm/types/auth.js +2 -1
- package/dist/esm/types/index.js +8 -1
- package/dist/esm/types/router-config.js +2 -1
- package/dist/esm/utils/arkos-env.js +7 -1
- package/dist/esm/utils/cli/build.js +208 -5
- package/dist/esm/utils/cli/dev.js +147 -3
- package/dist/esm/utils/cli/generate.js +103 -1
- package/dist/esm/utils/cli/index.js +94 -1
- package/dist/esm/utils/cli/index.js.map +1 -1
- package/dist/esm/utils/cli/prisma-generate.js +114 -0
- package/dist/esm/utils/cli/prisma-generate.js.map +1 -0
- package/dist/esm/utils/cli/start.js +96 -1
- package/dist/esm/utils/cli/utils/cli.helpers.js +16 -1
- package/dist/esm/utils/cli/utils/smart-fs-watcher.js +68 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/auth-configs-template.js +33 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/auth-configs-template.js.map +1 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/controller-template.js +18 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/controller-template.js.map +1 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/hooks-template.js +198 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/hooks-template.js.map +1 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/middlewares-template.js +285 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/{generate-middlewares.js.map → middlewares-template.js.map} +1 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/query-options-template.js +61 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/query-options-template.js.map +1 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/router-template.js +39 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/router-template.js.map +1 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/service-template.js +26 -0
- package/dist/esm/utils/cli/utils/template-generator/templates/service-template.js.map +1 -0
- package/dist/esm/utils/cli/utils/template-generators.js +28 -2
- package/dist/esm/utils/cli/utils/template-generators.js.map +1 -1
- package/dist/esm/utils/cli/utils/watermark-stamper.js +15 -3
- package/dist/esm/utils/dotenv.helpers.js +37 -1
- package/dist/esm/utils/dynamic-loader.js +254 -9
- package/dist/esm/utils/features/api.features.js +162 -1
- package/dist/esm/utils/features/change-case.features.js +31 -1
- package/dist/esm/utils/features/port-and-host-allocator.js +67 -1
- package/dist/esm/utils/helpers/api.features.helpers.js +106 -1
- package/dist/esm/utils/helpers/change-case.helpers.js +161 -1
- package/dist/esm/utils/helpers/deepmerge.helper.js +113 -1
- package/dist/esm/utils/helpers/dynamic-loader.helpers.js +69 -1
- package/dist/esm/utils/helpers/fs.helpers.js +48 -1
- package/dist/esm/utils/helpers/global.helpers.js +51 -1
- package/dist/esm/utils/helpers/prisma.helpers.js +32 -1
- package/dist/esm/utils/helpers/query-parser.helpers.js +40 -1
- package/dist/esm/utils/helpers/routers.helpers.js +29 -1
- package/dist/esm/utils/helpers/text.helpers.js +22 -1
- package/dist/esm/utils/prisma/prisma-json-schema-generator.js +448 -1
- package/dist/esm/utils/prisma/prisma-schema-parser.js +209 -4
- package/dist/esm/utils/prisma/types.js +2 -1
- package/dist/esm/utils/sheu.js +118 -1
- package/dist/esm/utils/validate-dto.js +11 -1
- package/dist/esm/utils/validate-schema.js +9 -1
- package/dist/types/modules/auth/utils/services/auth-action.service.d.ts +1 -1
- package/dist/types/modules/base/types/base.service.types.d.ts +12 -9
- package/dist/types/types/arkos-config.d.ts +3 -2
- package/dist/types/utils/cli/prisma-generate.d.ts +1 -0
- package/package.json +2 -2
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-auth-configs-template.js +0 -21
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-auth-configs-template.js.map +0 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-controller-template.js +0 -12
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-controller-template.js.map +0 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-hooks-template.js +0 -144
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-hooks-template.js.map +0 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-middlewares.js +0 -256
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-prisma-query-options.js +0 -36
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-prisma-query-options.js.map +0 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-router-template.js +0 -18
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-router-template.js.map +0 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-service-template.js +0 -9
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-service-template.js.map +0 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-auth-configs-template.js +0 -21
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-auth-configs-template.js.map +0 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-controller-template.js +0 -12
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-controller-template.js.map +0 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-hooks-template.js +0 -144
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-hooks-template.js.map +0 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-middlewares.js +0 -256
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-prisma-query-options.js +0 -36
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-prisma-query-options.js.map +0 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-router-template.js +0 -18
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-router-template.js.map +0 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-service-template.js +0 -9
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-service-template.js.map +0 -1
- /package/dist/types/utils/cli/utils/template-generator/templates/{generate-auth-configs-template.d.ts → auth-configs-template.d.ts} +0 -0
- /package/dist/types/utils/cli/utils/template-generator/templates/{generate-controller-template.d.ts → controller-template.d.ts} +0 -0
- /package/dist/types/utils/cli/utils/template-generator/templates/{generate-hooks-template.d.ts → hooks-template.d.ts} +0 -0
- /package/dist/types/utils/cli/utils/template-generator/templates/{generate-middlewares.d.ts → middlewares-template.d.ts} +0 -0
- /package/dist/types/utils/cli/utils/template-generator/templates/{generate-prisma-query-options.d.ts → query-options-template.d.ts} +0 -0
- /package/dist/types/utils/cli/utils/template-generator/templates/{generate-router-template.d.ts → router-template.d.ts} +0 -0
- /package/dist/types/utils/cli/utils/template-generator/templates/{generate-service-template.d.ts → service-template.d.ts} +0 -0
|
@@ -1 +1,219 @@
|
|
|
1
|
-
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
import bcrypt from "bcryptjs";
|
|
3
|
+
import catchAsync from "../error-handler/utils/catch-async.js";
|
|
4
|
+
import AppError from "../error-handler/utils/app-error.js";
|
|
5
|
+
import { callNext } from "../base/base.middlewares.js";
|
|
6
|
+
import { getArkosConfig } from "../../server.js";
|
|
7
|
+
import arkosEnv from "../../utils/arkos-env.js";
|
|
8
|
+
import { getPrismaInstance } from "../../utils/helpers/prisma.helpers.js";
|
|
9
|
+
import { appModules, getModuleComponents } from "../../utils/dynamic-loader.js";
|
|
10
|
+
import { kebabCase } from "../../exports/utils/index.js";
|
|
11
|
+
import { invaliAuthTokenError, loginRequiredError, } from "./utils/auth-error-objects.js";
|
|
12
|
+
import authActionService from "./utils/services/auth-action.service.js";
|
|
13
|
+
export class AuthService {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.actionsPerResource = {};
|
|
16
|
+
this.authenticate = catchAsync(async (req, _, next) => {
|
|
17
|
+
const arkosConfig = getArkosConfig();
|
|
18
|
+
if (!arkosConfig?.authentication) {
|
|
19
|
+
next();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
req.user = (await this.getAuthenticatedUser(req));
|
|
23
|
+
next();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
signJwtToken(id, expiresIn, secret) {
|
|
27
|
+
const { authentication: configs } = getArkosConfig();
|
|
28
|
+
if (process.env.NODE_ENV === "production" &&
|
|
29
|
+
!process.env.JWT_SECRET &&
|
|
30
|
+
!configs?.jwt?.secret)
|
|
31
|
+
throw new AppError("Missing JWT secret on production!", 500, {}, "MissingJWTOnProduction");
|
|
32
|
+
secret =
|
|
33
|
+
secret ||
|
|
34
|
+
configs?.jwt?.secret ||
|
|
35
|
+
process.env.JWT_SECRET ||
|
|
36
|
+
arkosEnv.JWT_SECRET;
|
|
37
|
+
expiresIn = (expiresIn ||
|
|
38
|
+
configs?.jwt?.expiresIn ||
|
|
39
|
+
process.env.JWT_EXPIRES_IN ||
|
|
40
|
+
arkosEnv.JWT_EXPIRES_IN);
|
|
41
|
+
return jwt.sign({ id }, secret, {
|
|
42
|
+
expiresIn: expiresIn,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
isPasswordHashed(password) {
|
|
46
|
+
return !Number.isNaN(bcrypt.getRounds(password) * 1);
|
|
47
|
+
}
|
|
48
|
+
async isCorrectPassword(candidatePassword, userPassword) {
|
|
49
|
+
return await bcrypt.compare(candidatePassword, userPassword);
|
|
50
|
+
}
|
|
51
|
+
async hashPassword(password) {
|
|
52
|
+
return await bcrypt.hash(password, 12);
|
|
53
|
+
}
|
|
54
|
+
isPasswordStrong(password) {
|
|
55
|
+
const initAuthConfigs = getArkosConfig()?.authentication;
|
|
56
|
+
const strongPasswordRegex = initAuthConfigs?.passwordValidation?.regex ||
|
|
57
|
+
/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).+$/;
|
|
58
|
+
return strongPasswordRegex.test(password);
|
|
59
|
+
}
|
|
60
|
+
userChangedPasswordAfter(user, JWTTimestamp) {
|
|
61
|
+
if (user.passwordChangedAt) {
|
|
62
|
+
const convertedTimestamp = parseInt(String(user.passwordChangedAt.getTime() / 1000), 10);
|
|
63
|
+
return JWTTimestamp < convertedTimestamp;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
async verifyJwtToken(token, secret) {
|
|
68
|
+
const { authentication: configs } = getArkosConfig();
|
|
69
|
+
if (process.env.NODE_ENV === "production" &&
|
|
70
|
+
!process.env.JWT_SECRET &&
|
|
71
|
+
!configs?.jwt?.secret)
|
|
72
|
+
throw new AppError("Missing JWT secret!", 500);
|
|
73
|
+
secret =
|
|
74
|
+
secret ||
|
|
75
|
+
configs?.jwt?.secret ||
|
|
76
|
+
process.env.JWT_SECRET ||
|
|
77
|
+
arkosEnv.JWT_SECRET;
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
jwt.verify(token, secret, (err, decoded) => {
|
|
80
|
+
if (err)
|
|
81
|
+
reject(err);
|
|
82
|
+
else
|
|
83
|
+
resolve(decoded);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
checkStaticAccessControl(user, action, accessControl) {
|
|
88
|
+
if (!user?.role && !user.roles)
|
|
89
|
+
throw Error("Validation Error: In order to use static authentication user needs at least role field or roles for multiple roles.");
|
|
90
|
+
let authorizedRoles = [];
|
|
91
|
+
if (Array.isArray(accessControl))
|
|
92
|
+
authorizedRoles = accessControl;
|
|
93
|
+
else if (accessControl[action])
|
|
94
|
+
authorizedRoles = Array.isArray(accessControl[action])
|
|
95
|
+
? accessControl[action]
|
|
96
|
+
: accessControl[action].roles;
|
|
97
|
+
const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];
|
|
98
|
+
return !!userRoles.some((role) => authorizedRoles.includes(role));
|
|
99
|
+
}
|
|
100
|
+
async checkDynamicAccessControl(userId, action, resource) {
|
|
101
|
+
const prisma = getPrismaInstance();
|
|
102
|
+
return !!(await prisma.userRole.findFirst({
|
|
103
|
+
where: {
|
|
104
|
+
userId,
|
|
105
|
+
role: {
|
|
106
|
+
permissions: {
|
|
107
|
+
some: {
|
|
108
|
+
resource,
|
|
109
|
+
action,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
select: { id: true },
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
handleAccessControl(action, resource, accessControl) {
|
|
118
|
+
authActionService.add(action, resource, accessControl);
|
|
119
|
+
return catchAsync(async (req, _, next) => {
|
|
120
|
+
if (req.user) {
|
|
121
|
+
const user = req.user;
|
|
122
|
+
const configs = getArkosConfig();
|
|
123
|
+
if (user.isSuperUser) {
|
|
124
|
+
next();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const notEnoughPermissionsError = new AppError("You do not have permission to perfom this action", 403, {}, "NotEnoughPermissions");
|
|
128
|
+
if (configs?.authentication?.mode === "dynamic") {
|
|
129
|
+
const hasPermission = await this.checkDynamicAccessControl(user.id, action, resource);
|
|
130
|
+
if (!hasPermission)
|
|
131
|
+
return next(notEnoughPermissionsError);
|
|
132
|
+
}
|
|
133
|
+
else if (configs?.authentication?.mode === "static") {
|
|
134
|
+
if (!accessControl)
|
|
135
|
+
return next(notEnoughPermissionsError);
|
|
136
|
+
const hasPermission = this.checkStaticAccessControl(user, action, accessControl);
|
|
137
|
+
if (!hasPermission)
|
|
138
|
+
return next(notEnoughPermissionsError);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
next();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
async getAuthenticatedUser(req) {
|
|
145
|
+
const arkosConfig = getArkosConfig();
|
|
146
|
+
if (!arkosConfig?.authentication)
|
|
147
|
+
return null;
|
|
148
|
+
const prisma = getPrismaInstance();
|
|
149
|
+
let token;
|
|
150
|
+
if (req?.headers?.authorization &&
|
|
151
|
+
req?.headers?.authorization.startsWith("Bearer")) {
|
|
152
|
+
token = req?.headers?.authorization.split(" ")[1];
|
|
153
|
+
}
|
|
154
|
+
else if (req?.cookies?.arkos_access_token !== "no-token" && req.cookies) {
|
|
155
|
+
token = req?.cookies?.arkos_access_token;
|
|
156
|
+
}
|
|
157
|
+
if (!token)
|
|
158
|
+
throw loginRequiredError;
|
|
159
|
+
let decoded;
|
|
160
|
+
try {
|
|
161
|
+
decoded = await this.verifyJwtToken(token);
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
throw invaliAuthTokenError;
|
|
165
|
+
}
|
|
166
|
+
if (!decoded?.id)
|
|
167
|
+
throw invaliAuthTokenError;
|
|
168
|
+
const user = await prisma.user.findUnique({
|
|
169
|
+
where: { id: String(decoded.id) },
|
|
170
|
+
});
|
|
171
|
+
if (!user)
|
|
172
|
+
throw new AppError("The user belonging to this token does no longer exists", 401, {}, "UserNoLongerExists");
|
|
173
|
+
if (this.userChangedPasswordAfter(user, decoded.iat) &&
|
|
174
|
+
!req.path?.includes?.("logout"))
|
|
175
|
+
throw new AppError("User recently changed password! Please log in again.", 401, {}, "PasswordChanged");
|
|
176
|
+
req.accessToken = token;
|
|
177
|
+
return user;
|
|
178
|
+
}
|
|
179
|
+
handleAuthenticationControl(action, authenticationControl) {
|
|
180
|
+
if (authenticationControl && typeof authenticationControl === "object") {
|
|
181
|
+
if (authenticationControl[action] === false)
|
|
182
|
+
return callNext;
|
|
183
|
+
else if (authenticationControl[action] === true)
|
|
184
|
+
return this.authenticate;
|
|
185
|
+
}
|
|
186
|
+
else
|
|
187
|
+
return this.authenticate;
|
|
188
|
+
return this.authenticate;
|
|
189
|
+
}
|
|
190
|
+
permission(action, resource, accessControl) {
|
|
191
|
+
const stack = new Error().stack;
|
|
192
|
+
if (stack?.includes("node_modules/express/lib/router/index.js"))
|
|
193
|
+
throw new Error("authService.permission() should be called during application initialization level.");
|
|
194
|
+
authActionService.add(action, resource, accessControl);
|
|
195
|
+
return async (user) => {
|
|
196
|
+
const configs = getArkosConfig();
|
|
197
|
+
if (!configs?.authentication)
|
|
198
|
+
throw Error("Validation Error: Trying to use authService.permission without setting up authentication.");
|
|
199
|
+
if (!user)
|
|
200
|
+
throw loginRequiredError;
|
|
201
|
+
if (user.isSuperUser)
|
|
202
|
+
return true;
|
|
203
|
+
if (configs?.authentication?.mode === "dynamic") {
|
|
204
|
+
return await this.checkDynamicAccessControl(user?.id, action, resource);
|
|
205
|
+
}
|
|
206
|
+
else if (configs?.authentication?.mode === "static") {
|
|
207
|
+
if (!accessControl && appModules.includes(kebabCase(resource)))
|
|
208
|
+
accessControl = getModuleComponents(kebabCase(resource))?.authConfigs
|
|
209
|
+
?.accessControl;
|
|
210
|
+
return (!!accessControl &&
|
|
211
|
+
this.checkStaticAccessControl(user, action, accessControl));
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const authService = new AuthService();
|
|
218
|
+
export default authService;
|
|
219
|
+
//# sourceMappingURL=auth.service.js.map
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import AppError from "../../error-handler/utils/app-error.js";
|
|
2
|
+
export const loginRequiredError = new AppError("You are not logged in! please log in to get access", 401, {}, "LoginRequired");
|
|
3
|
+
export const invaliAuthTokenError = new AppError("Your auth token is invalid, please login again.", 401, {}, "InvalidAuthToken");
|
|
4
|
+
//# sourceMappingURL=auth-error-objects.js.map
|
|
@@ -1 +1,73 @@
|
|
|
1
|
-
|
|
1
|
+
import { getArkosConfig } from "../../../../server.js";
|
|
2
|
+
import AppError from "../../../error-handler/utils/app-error.js";
|
|
3
|
+
export const determineUsernameField = (req) => {
|
|
4
|
+
const authConfigs = getArkosConfig()?.authentication;
|
|
5
|
+
if (req.query?.usernameField &&
|
|
6
|
+
typeof req.query?.usernameField === "string" &&
|
|
7
|
+
authConfigs?.login?.allowedUsernames?.includes?.(req.query.usernameField))
|
|
8
|
+
return req.query.usernameField;
|
|
9
|
+
else if (req.query?.usernameField)
|
|
10
|
+
throw new AppError("Invalid usernameField parameter, it is not allowed!", 400);
|
|
11
|
+
return authConfigs?.login?.allowedUsernames?.[0] || "username";
|
|
12
|
+
};
|
|
13
|
+
export const createPrismaWhereClause = (path, value) => {
|
|
14
|
+
if (!path)
|
|
15
|
+
return {};
|
|
16
|
+
const parts = path.split(".");
|
|
17
|
+
const whereClause = {};
|
|
18
|
+
if (parts.length === 1) {
|
|
19
|
+
whereClause[parts[0]] = value;
|
|
20
|
+
return whereClause;
|
|
21
|
+
}
|
|
22
|
+
let current = whereClause;
|
|
23
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
24
|
+
const part = parts[i];
|
|
25
|
+
current[part] = {};
|
|
26
|
+
current = current[part];
|
|
27
|
+
}
|
|
28
|
+
current[parts[parts.length - 1]] = value;
|
|
29
|
+
return whereClause;
|
|
30
|
+
};
|
|
31
|
+
export const getNestedValue = (obj, path) => {
|
|
32
|
+
if (!obj || !path)
|
|
33
|
+
return undefined;
|
|
34
|
+
const properties = path.split(".");
|
|
35
|
+
const lastProperty = properties[properties.length - 1];
|
|
36
|
+
if (lastProperty in obj) {
|
|
37
|
+
return obj[lastProperty];
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
};
|
|
41
|
+
function normalizeDuration(input) {
|
|
42
|
+
return input
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.replace(/years?|yr|year/g, "y")
|
|
45
|
+
.replace(/minutes?|min/g, "m")
|
|
46
|
+
.replace(/seconds?|sec|secs/g, "s")
|
|
47
|
+
.replace(/hours?|hr/g, "h")
|
|
48
|
+
.replace(/days?/g, "d")
|
|
49
|
+
.replace(/weeks?/g, "w")
|
|
50
|
+
.replace(/milliseconds?/g, "ms");
|
|
51
|
+
}
|
|
52
|
+
export function toMs(input) {
|
|
53
|
+
if (typeof input === "number")
|
|
54
|
+
return input * 1000;
|
|
55
|
+
const normalizedInput = normalizeDuration(input.trim());
|
|
56
|
+
const regex = /^(\d+(?:\.\d+)?)(ms|s|m|h|d|w|y)$/i;
|
|
57
|
+
const match = normalizedInput.match(regex);
|
|
58
|
+
if (!match)
|
|
59
|
+
throw new Error(`Invalid time format: ${input}`);
|
|
60
|
+
const value = parseFloat(match[1]);
|
|
61
|
+
const unit = match[2].toLowerCase();
|
|
62
|
+
const multipliers = {
|
|
63
|
+
ms: 1,
|
|
64
|
+
s: 1000,
|
|
65
|
+
m: 60000,
|
|
66
|
+
h: 3600000,
|
|
67
|
+
d: 86400000,
|
|
68
|
+
w: 604800000,
|
|
69
|
+
y: 31557600000,
|
|
70
|
+
};
|
|
71
|
+
return value * multipliers[unit];
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=auth.controller.helpers.js.map
|
|
@@ -1 +1,90 @@
|
|
|
1
|
-
|
|
1
|
+
import { kebabCase } from "../../../../exports/utils/index.js";
|
|
2
|
+
import { capitalize } from "../../../../utils/helpers/text.helpers.js";
|
|
3
|
+
class AuthActionService {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.authActions = [
|
|
6
|
+
{
|
|
7
|
+
roles: [],
|
|
8
|
+
action: "View",
|
|
9
|
+
resource: "auth-action",
|
|
10
|
+
name: "View auth action",
|
|
11
|
+
description: "Viewm an auth action",
|
|
12
|
+
errorMessage: "You do not have permission to perform this operation",
|
|
13
|
+
},
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
add(action, resource, accessControl) {
|
|
17
|
+
if (!this.getOne(action, resource)) {
|
|
18
|
+
const transformedAction = this.transformAccessControlToValidAuthAction(action, resource, accessControl);
|
|
19
|
+
this.authActions.push(transformedAction);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
getAll() {
|
|
23
|
+
return this.authActions;
|
|
24
|
+
}
|
|
25
|
+
getOne(action, resource) {
|
|
26
|
+
return this.authActions.find((authAction) => authAction.action === action && authAction.resource === resource);
|
|
27
|
+
}
|
|
28
|
+
transformAccessControlToValidAuthAction(action, resource, accessControl) {
|
|
29
|
+
const baseAuthAction = {
|
|
30
|
+
roles: (accessControl &&
|
|
31
|
+
(Array.isArray(accessControl)
|
|
32
|
+
? accessControl
|
|
33
|
+
: typeof accessControl === "string"
|
|
34
|
+
? [accessControl]
|
|
35
|
+
: Array.isArray(accessControl?.[action] || {})
|
|
36
|
+
? accessControl[action]
|
|
37
|
+
: accessControl[action]
|
|
38
|
+
?.roles)) ||
|
|
39
|
+
[],
|
|
40
|
+
action,
|
|
41
|
+
resource,
|
|
42
|
+
name: `${capitalize(kebabCase(action).replace(/-/g, " "))} ${capitalize(kebabCase(resource).replace(/-/g, " "))}`,
|
|
43
|
+
description: `${capitalize(kebabCase(action).replace(/-/g, " "))} ${capitalize(kebabCase(resource).replace(/-/g, " "))}`,
|
|
44
|
+
errorMessage: `You do not have permission to perform this operation`,
|
|
45
|
+
};
|
|
46
|
+
if (!accessControl) {
|
|
47
|
+
return baseAuthAction;
|
|
48
|
+
}
|
|
49
|
+
if (Array.isArray(accessControl)) {
|
|
50
|
+
return baseAuthAction;
|
|
51
|
+
}
|
|
52
|
+
const actionRule = accessControl[action];
|
|
53
|
+
if (actionRule) {
|
|
54
|
+
if (Array.isArray(actionRule)) {
|
|
55
|
+
return baseAuthAction;
|
|
56
|
+
}
|
|
57
|
+
else if (typeof actionRule === "object") {
|
|
58
|
+
return {
|
|
59
|
+
...baseAuthAction,
|
|
60
|
+
name: actionRule.name || baseAuthAction.name,
|
|
61
|
+
description: actionRule?.description || baseAuthAction.description,
|
|
62
|
+
errorMessage: actionRule?.errorMessage || baseAuthAction.errorMessage,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return baseAuthAction;
|
|
67
|
+
}
|
|
68
|
+
getUniqueActions() {
|
|
69
|
+
return [
|
|
70
|
+
...new Set(this.authActions.map((authAction) => authAction.action)),
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
getUniqueResources() {
|
|
74
|
+
return [
|
|
75
|
+
...new Set(this.authActions.map((authAction) => authAction.resource)),
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
getByResource(resource) {
|
|
79
|
+
return this.authActions.filter((authAction) => authAction.resource === resource);
|
|
80
|
+
}
|
|
81
|
+
getByAction(action) {
|
|
82
|
+
return this.authActions.filter((authAction) => authAction.action === action);
|
|
83
|
+
}
|
|
84
|
+
exists(action, resource) {
|
|
85
|
+
return !!this.getOne(action, resource);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const authActionService = new AuthActionService();
|
|
89
|
+
export default authActionService;
|
|
90
|
+
//# sourceMappingURL=auth-action.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-action.service.js","sourceRoot":"","sources":["../../../../../../src/modules/auth/utils/services/auth-action.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAKtD,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAoBpE,MAAM,iBAAiB;IAAvB;QACE,gBAAW,GAAiB;YAC1B;gBACE,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,MAAM;gBACd,QAAQ,EAAE,aAAa;gBACvB,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE,sBAAsB;gBACnC,YAAY,EAAE,sDAAsD;aACrE;SACF,CAAC;IAyHJ,CAAC;IAvHC,GAAG,CAAC,MAAc,EAAE,QAAgB,EAAE,aAAmC;QACvE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;YACnC,MAAM,iBAAiB,GAAG,IAAI,CAAC,uCAAuC,CACpE,MAAM,EACN,QAAQ,EACR,aAAa,CACd,CAAC;YACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,QAAgB;QACrC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAC1B,CAAC,UAAU,EAAE,EAAE,CACb,UAAU,CAAC,MAAM,KAAK,MAAM,IAAI,UAAU,CAAC,QAAQ,KAAK,QAAQ,CACnE,CAAC;IACJ,CAAC;IAEO,uCAAuC,CAC7C,MAAc,EACd,QAAgB,EAChB,aAAmC;QAEnC,MAAM,cAAc,GAAe;YACjC,KAAK,EACH,CAAC,aAAa;gBACZ,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC;oBAC3B,CAAC,CAAC,aAAa;oBACf,CAAC,CAAC,OAAO,aAAa,KAAK,QAAQ;wBACjC,CAAC,CAAC,CAAC,aAAa,CAAC;wBACjB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;4BAC5C,CAAC,CAAE,aAAa,CAAC,MAAM,CAAc;4BACrC,CAAC,CAAE,aAAa,CAAC,MAAM,CAA+B;gCAClD,EAAE,KAAK,CAAC,CAAC;gBACrB,EAAE;YACJ,MAAM;YACN,QAAQ;YACR,IAAI,EAAE,GAAG,MAAM,IAAI,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"auth-action.service.js","sourceRoot":"","sources":["../../../../../../src/modules/auth/utils/services/auth-action.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { kebabCase } from \"../../../../exports/utils\";\nimport {\n AccessControlConfig,\n DetailedAccessControlRule,\n} from \"../../../../types/auth\";\nimport { capitalize } from \"../../../../utils/helpers/text.helpers\";\n\ninterface AuthAction {\n /** role name, e.g Admin, Manager */\n roles: string[];\n /** action name, e.g Create, View, Update, Download, Cancel */\n action: string;\n /** resource name, e.g user, user-role, product, author */\n resource: string;\n /** Human-readable name for this permission (optional) */\n name?: string;\n /** Detailed description of what this permission allows (optional) */\n description?: string;\n /** Detailed error message of what must be returned on forbidden response (optional)\n *\n * Note: not yet implemented\n */\n errorMessage?: string;\n}\n\nclass AuthActionService {\n authActions: AuthAction[] = [\n {\n roles: [],\n action: \"View\",\n resource: \"auth-action\",\n name: \"View auth action\",\n description: \"Viewm an auth action\",\n errorMessage: \"You do not have permission to perform this operation\",\n },\n ];\n\n add(action: string, resource: string, accessControl?: AccessControlConfig) {\n if (!this.getOne(action, resource)) {\n const transformedAction = this.transformAccessControlToValidAuthAction(\n action,\n resource,\n accessControl\n );\n this.authActions.push(transformedAction);\n }\n }\n\n getAll(): AuthAction[] {\n return this.authActions;\n }\n\n getOne(action: string, resource: string): AuthAction | undefined {\n return this.authActions.find(\n (authAction) =>\n authAction.action === action && authAction.resource === resource\n );\n }\n\n private transformAccessControlToValidAuthAction(\n action: string,\n resource: string,\n accessControl?: AccessControlConfig\n ): AuthAction {\n const baseAuthAction: AuthAction = {\n roles:\n (accessControl &&\n (Array.isArray(accessControl)\n ? accessControl\n : typeof accessControl === \"string\"\n ? [accessControl]\n : Array.isArray(accessControl?.[action] || {})\n ? (accessControl[action] as string[])\n : (accessControl[action] as DetailedAccessControlRule)\n ?.roles)) ||\n [],\n action,\n resource,\n name: `${capitalize(kebabCase(action).replace(/-/g, \" \"))} ${capitalize(kebabCase(resource).replace(/-/g, \" \"))}`,\n description: `${capitalize(kebabCase(action).replace(/-/g, \" \"))} ${capitalize(kebabCase(resource).replace(/-/g, \" \"))}`,\n errorMessage: `You do not have permission to perform this operation`,\n };\n\n // If accessControl is not provided, return the base action\n if (!accessControl) {\n return baseAuthAction;\n }\n\n // If accessControl is an array of roles, just return the base action\n if (Array.isArray(accessControl)) {\n return baseAuthAction;\n }\n\n // If accessControl is an object with specific rules\n const actionRule = accessControl[action];\n\n if (actionRule) {\n if (Array.isArray(actionRule)) {\n // If it's just an array of roles, keep the base action\n return baseAuthAction;\n } else if (typeof actionRule === \"object\") {\n // If it's a detailed rule object, use its metadata\n return {\n ...baseAuthAction,\n name: actionRule.name || baseAuthAction.name,\n description: actionRule?.description || baseAuthAction.description,\n errorMessage: actionRule?.errorMessage || baseAuthAction.errorMessage,\n };\n }\n }\n\n return baseAuthAction;\n }\n\n /**\n * Get all unique actions across all auth actions\n */\n getUniqueActions(): string[] {\n return [\n ...new Set(this.authActions.map((authAction) => authAction.action)),\n ];\n }\n\n /**\n * Get all unique resources across all auth actions\n */\n getUniqueResources(): string[] {\n return [\n ...new Set(this.authActions.map((authAction) => authAction.resource)),\n ];\n }\n\n /**\n * Get all auth actions for a specific resource\n */\n getByResource(resource: string): AuthAction[] | undefined {\n return this.authActions.filter(\n (authAction) => authAction.resource === resource\n );\n }\n\n /**\n * Get all auth actions for a specific action\n */\n getByAction(action: string): AuthAction[] {\n return this.authActions.filter(\n (authAction) => authAction.action === action\n );\n }\n\n /**\n * Check if an auth action exists\n */\n exists(action: string, resource: string): boolean {\n return !!this.getOne(action, resource);\n }\n}\n\nconst authActionService = new AuthActionService();\n\nexport default authActionService;\n"]}
|
|
@@ -1 +1,165 @@
|
|
|
1
|
-
|
|
1
|
+
import catchAsync from "../error-handler/utils/catch-async.js";
|
|
2
|
+
import APIFeatures from "../../utils/features/api.features.js";
|
|
3
|
+
import { BaseService } from "./base.service.js";
|
|
4
|
+
import AppError from "../error-handler/utils/app-error.js";
|
|
5
|
+
import { kebabCase, pascalCase } from "../../utils/helpers/change-case.helpers.js";
|
|
6
|
+
import { getModuleComponents } from "../../utils/dynamic-loader.js";
|
|
7
|
+
import pluralize from "pluralize";
|
|
8
|
+
import sheu from "../../utils/sheu.js";
|
|
9
|
+
import prismaSchemaParser from "../../utils/prisma/prisma-schema-parser.js";
|
|
10
|
+
export class BaseController {
|
|
11
|
+
constructor(modelName) {
|
|
12
|
+
this.createOne = catchAsync(async (req, res, next) => {
|
|
13
|
+
const data = await this.service.createOne(req.body, req.prismaQueryOptions, { user: req?.user, accessToken: req?.accessToken });
|
|
14
|
+
if (this.interceptors.afterCreateOne) {
|
|
15
|
+
req.responseData = { data };
|
|
16
|
+
req.responseStatus = 201;
|
|
17
|
+
return next();
|
|
18
|
+
}
|
|
19
|
+
res.status(201).json({ data });
|
|
20
|
+
});
|
|
21
|
+
this.createMany = catchAsync(async (req, res, next) => {
|
|
22
|
+
const data = await this.service.createMany(req.body, req.prismaQueryOptions, { user: req?.user, accessToken: req?.accessToken });
|
|
23
|
+
if (!data)
|
|
24
|
+
return next(new AppError("Failed to create the resources. Please check your input.", 400, {}, "MissingRequestBody"));
|
|
25
|
+
if (this.interceptors.afterCreateMany) {
|
|
26
|
+
req.responseData = { data };
|
|
27
|
+
req.responseStatus = 201;
|
|
28
|
+
return next();
|
|
29
|
+
}
|
|
30
|
+
res.status(201).json({ data });
|
|
31
|
+
});
|
|
32
|
+
this.findMany = catchAsync(async (req, res, next) => {
|
|
33
|
+
const { filters: { where, ...queryOptions }, } = new APIFeatures(req, this.modelName)
|
|
34
|
+
.filter()
|
|
35
|
+
.sort()
|
|
36
|
+
.limitFields()
|
|
37
|
+
.paginate();
|
|
38
|
+
const [data, total] = (await Promise.all([
|
|
39
|
+
this.service.findMany(where, queryOptions, {
|
|
40
|
+
user: req?.user,
|
|
41
|
+
accessToken: req?.accessToken,
|
|
42
|
+
}),
|
|
43
|
+
this.service.count(where, {
|
|
44
|
+
user: req?.user,
|
|
45
|
+
accessToken: req?.accessToken,
|
|
46
|
+
}),
|
|
47
|
+
]));
|
|
48
|
+
if (this.interceptors.afterFindMany) {
|
|
49
|
+
req.responseData = { total, results: data.length, data };
|
|
50
|
+
req.responseStatus = 200;
|
|
51
|
+
return next();
|
|
52
|
+
}
|
|
53
|
+
res.status(200).json({ total, results: data.length, data });
|
|
54
|
+
});
|
|
55
|
+
this.findOne = catchAsync(async (req, res, next) => {
|
|
56
|
+
const data = await this.service.findOne(req.params, req.prismaQueryOptions, { user: req?.user, accessToken: req?.accessToken });
|
|
57
|
+
if (!data) {
|
|
58
|
+
if (Object.keys(req.params).length === 1 &&
|
|
59
|
+
"id" in req.params &&
|
|
60
|
+
req.params.id !== "me") {
|
|
61
|
+
return next(new AppError(`${pascalCase(String(this.modelName))} with ID ${req.params?.id} not found`, 404, {}, "NotFound"));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return next(new AppError(`${pascalCase(String(this.modelName))} not found`, 404, {}, "NotFound"));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (this.interceptors.afterFindOne) {
|
|
68
|
+
req.responseData = { data };
|
|
69
|
+
req.responseStatus = 200;
|
|
70
|
+
return next();
|
|
71
|
+
}
|
|
72
|
+
res.status(200).json({ data });
|
|
73
|
+
});
|
|
74
|
+
this.updateOne = catchAsync(async (req, res, next) => {
|
|
75
|
+
const data = await this.service.updateOne(req.params, req.body, req.prismaQueryOptions, { user: req?.user, accessToken: req?.accessToken });
|
|
76
|
+
if (!data) {
|
|
77
|
+
if (Object.keys(req.params).length === 1 && "id" in req.params) {
|
|
78
|
+
return next(new AppError(`${pascalCase(String(this.modelName))} with ID ${req.params?.id} not found`, 404, {}, "NotFound"));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return next(new AppError(`${pascalCase(String(this.modelName))} not found`, 404, {}, "NotFound"));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (this.interceptors.afterUpdateOne) {
|
|
85
|
+
req.responseData = { data };
|
|
86
|
+
req.responseStatus = 200;
|
|
87
|
+
return next();
|
|
88
|
+
}
|
|
89
|
+
res.status(200).json({ data });
|
|
90
|
+
});
|
|
91
|
+
this.updateMany = catchAsync(async (req, res, next) => {
|
|
92
|
+
if (!Object.keys(req.query).some((key) => key !== "prismaQueryOptions")) {
|
|
93
|
+
return next(new AppError("Filter criteria not provided for bulk update.", 400, {}, "MissingRequestQueryParameters"));
|
|
94
|
+
}
|
|
95
|
+
req.query.filterMode = req.query?.filterMode || "AND";
|
|
96
|
+
const { filters: { where, ...queryOptions }, } = new APIFeatures(req, this.modelName).filter().sort();
|
|
97
|
+
delete queryOptions.include;
|
|
98
|
+
const data = (await this.service.updateMany(where, req.body, queryOptions, { user: req?.user, accessToken: req?.accessToken }));
|
|
99
|
+
if (!data || data.count === 0)
|
|
100
|
+
return next(new AppError(`${pluralize(pascalCase(String(this.modelName)))} not found`, 404));
|
|
101
|
+
if (this.interceptors.afterUpdateMany) {
|
|
102
|
+
req.responseData = { results: data.count, data };
|
|
103
|
+
req.responseStatus = 200;
|
|
104
|
+
return next();
|
|
105
|
+
}
|
|
106
|
+
res.status(200).json({ results: data.count, data });
|
|
107
|
+
});
|
|
108
|
+
this.deleteOne = catchAsync(async (req, res, next) => {
|
|
109
|
+
const data = await this.service.deleteOne(req.params, {
|
|
110
|
+
user: req?.user,
|
|
111
|
+
accessToken: req?.accessToken,
|
|
112
|
+
});
|
|
113
|
+
if (!data) {
|
|
114
|
+
if (Object.keys(req.params).length === 1 && "id" in req.params) {
|
|
115
|
+
return next(new AppError(`${pascalCase(String(this.modelName))} with ID ${req.params?.id} not found`, 404, {}, "NotFound"));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
return next(new AppError(`${pascalCase(String(this.modelName))} not found`, 404, {}, "NotFound"));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (this.interceptors.afterDeleteOne) {
|
|
122
|
+
req.additionalData = { data };
|
|
123
|
+
req.responseStatus = 204;
|
|
124
|
+
return next();
|
|
125
|
+
}
|
|
126
|
+
res.status(204).send();
|
|
127
|
+
});
|
|
128
|
+
this.deleteMany = catchAsync(async (req, res, next) => {
|
|
129
|
+
if (!Object.keys(req.query).some((key) => key !== "prismaQueryOptions")) {
|
|
130
|
+
return next(new AppError("Filter criteria not provided for bulk deletion.", 400, {}, "MissingRequestQueryParameters"));
|
|
131
|
+
}
|
|
132
|
+
req.query.filterMode = req.query?.filterMode || "AND";
|
|
133
|
+
const { filters: { where }, } = new APIFeatures(req, this.modelName).filter().sort();
|
|
134
|
+
const data = await this.service.deleteMany(where, {
|
|
135
|
+
user: req?.user,
|
|
136
|
+
accessToken: req?.accessToken,
|
|
137
|
+
});
|
|
138
|
+
if (!data || data.count === 0) {
|
|
139
|
+
return next(new AppError(`No records found to delete`, 404, {}, "NotFound"));
|
|
140
|
+
}
|
|
141
|
+
if (this.interceptors.afterDeleteMany) {
|
|
142
|
+
req.responseData = { results: data.count, data };
|
|
143
|
+
req.responseStatus = 200;
|
|
144
|
+
return next();
|
|
145
|
+
}
|
|
146
|
+
res.status(200).json({ results: data.count, data });
|
|
147
|
+
});
|
|
148
|
+
const components = getModuleComponents(modelName);
|
|
149
|
+
this.modelName = modelName;
|
|
150
|
+
this.service = new BaseService(modelName);
|
|
151
|
+
this.interceptors = components?.interceptors || {};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export const getAvailableResources = catchAsync(async (_, res) => {
|
|
155
|
+
sheu.warn("This route `/api/available-routes` will be deprecated from 1.4.0-beta, consider using /api/auth-actions instead.");
|
|
156
|
+
res.status(200).json({
|
|
157
|
+
data: [
|
|
158
|
+
...prismaSchemaParser
|
|
159
|
+
.getModelsAsArrayOfStrings()
|
|
160
|
+
.map((model) => kebabCase(model)),
|
|
161
|
+
"file-upload",
|
|
162
|
+
],
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=base.controller.js.map
|