arkos 2.0.0-next.16 → 2.0.0-next.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -31
- package/dist/cjs/app.js +3 -10
- package/dist/cjs/app.js.map +1 -1
- package/dist/cjs/components/arkos-gateway/arkos-gateway.js +344 -0
- package/dist/cjs/components/arkos-gateway/arkos-gateway.js.map +1 -0
- package/dist/cjs/components/arkos-gateway/socket-extensions.js +166 -0
- package/dist/cjs/components/arkos-gateway/socket-extensions.js.map +1 -0
- package/dist/cjs/components/arkos-gateway/types.js +7 -0
- package/dist/cjs/components/arkos-gateway/types.js.map +1 -0
- package/dist/cjs/components/arkos-gateway/utils/helpers.js +111 -0
- package/dist/cjs/components/arkos-gateway/utils/helpers.js.map +1 -0
- package/dist/cjs/components/arkos-gateway/utils/memory-gateway-store.js +51 -0
- package/dist/cjs/components/arkos-gateway/utils/memory-gateway-store.js.map +1 -0
- package/dist/cjs/components/arkos-gateway/utils/multi-tier-arkos-gateway-store.js +43 -0
- package/dist/cjs/components/arkos-gateway/utils/multi-tier-arkos-gateway-store.js.map +1 -0
- package/dist/cjs/components/arkos-gateway/utils/rate-limiter.js +17 -0
- package/dist/cjs/components/arkos-gateway/utils/rate-limiter.js.map +1 -0
- package/dist/cjs/components/arkos-policy/index.js.map +1 -1
- package/dist/cjs/components/arkos-route-hook/index.js.map +1 -1
- package/dist/cjs/components/arkos-route-hook/reader.js.map +1 -1
- package/dist/cjs/components/arkos-route-hook/types.js.map +1 -1
- package/dist/cjs/components/arkos-service-hook/index.js.map +1 -1
- package/dist/cjs/components/arkos-service-hook/types.js.map +1 -1
- package/dist/cjs/exports/index.js +3 -1
- package/dist/cjs/exports/index.js.map +1 -1
- package/dist/cjs/exports/services/index.js +2 -2
- package/dist/cjs/exports/services/index.js.map +1 -1
- package/dist/cjs/exports/websockets.js +13 -0
- package/dist/cjs/exports/websockets.js.map +1 -0
- package/dist/cjs/generated.js.map +1 -1
- package/dist/cjs/modules/auth/auth.controller.js +1 -1
- package/dist/cjs/modules/auth/auth.controller.js.map +1 -1
- package/dist/cjs/modules/auth/auth.service.js +88 -209
- package/dist/cjs/modules/auth/auth.service.js.map +1 -1
- package/dist/cjs/modules/auth/utils/auth-error-objects.js +2 -2
- package/dist/cjs/modules/auth/utils/auth-error-objects.js.map +1 -1
- package/dist/cjs/modules/auth/utils/auth-hooks-manager.js +153 -0
- package/dist/cjs/modules/auth/utils/auth-hooks-manager.js.map +1 -0
- package/dist/cjs/modules/auth/utils/docs-links.js +9 -0
- package/dist/cjs/modules/auth/utils/docs-links.js.map +1 -0
- package/dist/cjs/modules/auth/utils/services/auth-action.service.js +5 -3
- package/dist/cjs/modules/auth/utils/services/auth-action.service.js.map +1 -1
- package/dist/cjs/modules/base/base.controller.js +10 -4
- package/dist/cjs/modules/base/base.controller.js.map +1 -1
- package/dist/cjs/modules/base/base.middlewares.js +11 -20
- package/dist/cjs/modules/base/base.middlewares.js.map +1 -1
- package/dist/cjs/modules/base/base.service.js +29 -94
- package/dist/cjs/modules/base/base.service.js.map +1 -1
- package/dist/cjs/modules/email/email.service.js +14 -7
- package/dist/cjs/modules/email/email.service.js.map +1 -1
- package/dist/cjs/modules/error-handler/error-handler.controller.js +6 -102
- package/dist/cjs/modules/error-handler/error-handler.controller.js.map +1 -1
- package/dist/cjs/modules/error-handler/utils/catch-async.js.map +1 -1
- package/dist/cjs/modules/error-handler/utils/get-handled-error.js +107 -0
- package/dist/cjs/modules/error-handler/utils/get-handled-error.js.map +1 -0
- package/dist/cjs/modules/file-upload/file-upload.router.js +9 -2
- package/dist/cjs/modules/file-upload/file-upload.router.js.map +1 -1
- package/dist/cjs/modules/file-upload/file-upload.service.js +1 -1
- package/dist/cjs/modules/file-upload/file-upload.service.js.map +1 -1
- package/dist/cjs/modules/swagger/swagger.router.js +44 -10
- package/dist/cjs/modules/swagger/swagger.router.js.map +1 -1
- package/dist/cjs/modules/swagger/utils/get-open-api-login-html.js +3 -1
- package/dist/cjs/modules/swagger/utils/get-open-api-login-html.js.map +1 -1
- package/dist/cjs/modules/swagger/utils/helpers/class-validator-to-json-schema.js.map +1 -1
- package/dist/cjs/modules/swagger/utils/helpers/openapi-schema-converter.js +4 -2
- package/dist/cjs/modules/swagger/utils/helpers/openapi-schema-converter.js.map +1 -1
- package/dist/cjs/server.js +1 -1
- package/dist/cjs/server.js.map +1 -1
- package/dist/cjs/types/arkos.js.map +1 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/new-arkos-config.js.map +1 -1
- package/dist/cjs/types/upload.js +3 -0
- package/dist/cjs/types/upload.js.map +1 -0
- package/dist/cjs/types/validation/validation-manager.js +55 -0
- package/dist/cjs/types/validation/validation-manager.js.map +1 -0
- package/dist/cjs/types/validation/validator.js +3 -0
- package/dist/cjs/types/validation/validator.js.map +1 -0
- package/dist/cjs/utils/arkos-router/arkos-router-openapi-manager.js +9 -33
- package/dist/cjs/utils/arkos-router/arkos-router-openapi-manager.js.map +1 -1
- package/dist/cjs/utils/arkos-router/index.js +15 -3
- package/dist/cjs/utils/arkos-router/index.js.map +1 -1
- package/dist/cjs/utils/arkos-router/types/index.js.map +1 -1
- package/dist/cjs/utils/arkos-router/types/upload-config.js.map +1 -1
- package/dist/cjs/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js +41 -9
- package/dist/cjs/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js.map +1 -1
- package/dist/cjs/utils/arkos-router/utils/helpers/upload-manager.js +26 -6
- package/dist/cjs/utils/arkos-router/utils/helpers/upload-manager.js.map +1 -1
- package/dist/cjs/utils/cli/build.js +11 -2
- package/dist/cjs/utils/cli/build.js.map +1 -1
- package/dist/cjs/utils/cli/dev.js +4 -6
- package/dist/cjs/utils/cli/dev.js.map +1 -1
- package/dist/cjs/utils/cli/index.js +1 -1
- package/dist/cjs/utils/cli/index.js.map +1 -1
- package/dist/cjs/utils/cli/start.js +20 -11
- package/dist/cjs/utils/cli/start.js.map +1 -1
- package/dist/cjs/utils/cli/utils/cli.helpers.js +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator-dto-generator.js +53 -17
- package/dist/cjs/utils/cli/utils/template-generator/templates/class-validator-dto-generator.js.map +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-multiple-components.js +3 -3
- package/dist/cjs/utils/cli/utils/template-generator/templates/generate-multiple-components.js.map +1 -1
- package/dist/cjs/utils/cli/utils/template-generator/templates/zod-schema-generator.js +18 -18
- package/dist/cjs/utils/cli/utils/template-generator/templates/zod-schema-generator.js.map +1 -1
- package/dist/cjs/utils/docs-links.js +5 -0
- package/dist/cjs/utils/docs-links.js.map +1 -0
- package/dist/cjs/utils/features/api.features.js.map +1 -1
- package/dist/cjs/utils/helpers/arkos-config.helpers.js.map +1 -1
- package/dist/cjs/utils/helpers/exit-error.js +1 -1
- package/dist/cjs/utils/helpers/exit-error.js.map +1 -1
- package/dist/cjs/utils/initialize-app.js +3 -3
- package/dist/cjs/utils/initialize-app.js.map +1 -1
- package/dist/cjs/utils/remove-dir.js +1 -1
- package/dist/cjs/utils/remove-dir.js.map +1 -1
- package/dist/cjs/utils/setup-app.js.map +1 -1
- package/dist/esm/app.js +3 -10
- package/dist/esm/app.js.map +1 -1
- package/dist/esm/components/arkos-gateway/arkos-gateway.js +337 -0
- package/dist/esm/components/arkos-gateway/arkos-gateway.js.map +1 -0
- package/dist/esm/components/arkos-gateway/socket-extensions.js +161 -0
- package/dist/esm/components/arkos-gateway/socket-extensions.js.map +1 -0
- package/dist/esm/components/arkos-gateway/types.js +3 -0
- package/dist/esm/components/arkos-gateway/types.js.map +1 -0
- package/dist/esm/components/arkos-gateway/utils/helpers.js +105 -0
- package/dist/esm/components/arkos-gateway/utils/helpers.js.map +1 -0
- package/dist/esm/components/arkos-gateway/utils/memory-gateway-store.js +47 -0
- package/dist/esm/components/arkos-gateway/utils/memory-gateway-store.js.map +1 -0
- package/dist/esm/components/arkos-gateway/utils/multi-tier-arkos-gateway-store.js +39 -0
- package/dist/esm/components/arkos-gateway/utils/multi-tier-arkos-gateway-store.js.map +1 -0
- package/dist/esm/components/arkos-gateway/utils/rate-limiter.js +13 -0
- package/dist/esm/components/arkos-gateway/utils/rate-limiter.js.map +1 -0
- package/dist/esm/components/arkos-policy/index.js.map +1 -1
- package/dist/esm/components/arkos-route-hook/index.js.map +1 -1
- package/dist/esm/components/arkos-route-hook/reader.js.map +1 -1
- package/dist/esm/components/arkos-route-hook/types.js.map +1 -1
- package/dist/esm/components/arkos-service-hook/index.js.map +1 -1
- package/dist/esm/components/arkos-service-hook/types.js.map +1 -1
- package/dist/esm/exports/index.js +2 -1
- package/dist/esm/exports/index.js.map +1 -1
- package/dist/esm/exports/services/index.js +2 -2
- package/dist/esm/exports/services/index.js.map +1 -1
- package/dist/esm/exports/websockets.js +5 -0
- package/dist/esm/exports/websockets.js.map +1 -0
- package/dist/esm/generated.js.map +1 -1
- package/dist/esm/modules/auth/auth.controller.js +2 -2
- package/dist/esm/modules/auth/auth.controller.js.map +1 -1
- package/dist/esm/modules/auth/auth.service.js +83 -204
- package/dist/esm/modules/auth/auth.service.js.map +1 -1
- package/dist/esm/modules/auth/utils/auth-error-objects.js +2 -2
- package/dist/esm/modules/auth/utils/auth-error-objects.js.map +1 -1
- package/dist/esm/modules/auth/utils/auth-hooks-manager.js +148 -0
- package/dist/esm/modules/auth/utils/auth-hooks-manager.js.map +1 -0
- package/dist/esm/modules/auth/utils/docs-links.js +6 -0
- package/dist/esm/modules/auth/utils/docs-links.js.map +1 -0
- package/dist/esm/modules/auth/utils/services/auth-action.service.js +6 -4
- package/dist/esm/modules/auth/utils/services/auth-action.service.js.map +1 -1
- package/dist/esm/modules/base/base.controller.js +11 -5
- package/dist/esm/modules/base/base.controller.js.map +1 -1
- package/dist/esm/modules/base/base.middlewares.js +12 -21
- package/dist/esm/modules/base/base.middlewares.js.map +1 -1
- package/dist/esm/modules/base/base.service.js +27 -92
- package/dist/esm/modules/base/base.service.js.map +1 -1
- package/dist/esm/modules/email/email.service.js +14 -7
- package/dist/esm/modules/email/email.service.js.map +1 -1
- package/dist/esm/modules/error-handler/error-handler.controller.js +6 -66
- package/dist/esm/modules/error-handler/error-handler.controller.js.map +1 -1
- package/dist/esm/modules/error-handler/utils/catch-async.js.map +1 -1
- package/dist/esm/modules/error-handler/utils/get-handled-error.js +68 -0
- package/dist/esm/modules/error-handler/utils/get-handled-error.js.map +1 -0
- package/dist/esm/modules/file-upload/file-upload.router.js +9 -2
- package/dist/esm/modules/file-upload/file-upload.router.js.map +1 -1
- package/dist/esm/modules/file-upload/file-upload.service.js +1 -1
- package/dist/esm/modules/file-upload/file-upload.service.js.map +1 -1
- package/dist/esm/modules/swagger/swagger.router.js +11 -10
- package/dist/esm/modules/swagger/swagger.router.js.map +1 -1
- package/dist/esm/modules/swagger/utils/get-open-api-login-html.js +3 -1
- package/dist/esm/modules/swagger/utils/get-open-api-login-html.js.map +1 -1
- package/dist/esm/modules/swagger/utils/helpers/class-validator-to-json-schema.js.map +1 -1
- package/dist/esm/modules/swagger/utils/helpers/openapi-schema-converter.js +4 -2
- package/dist/esm/modules/swagger/utils/helpers/openapi-schema-converter.js.map +1 -1
- package/dist/esm/server.js +1 -1
- package/dist/esm/server.js.map +1 -1
- package/dist/esm/types/arkos.js.map +1 -1
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/types/new-arkos-config.js.map +1 -1
- package/dist/esm/types/upload.js +2 -0
- package/dist/esm/types/upload.js.map +1 -0
- package/dist/esm/types/validation/validation-manager.js +50 -0
- package/dist/esm/types/validation/validation-manager.js.map +1 -0
- package/dist/esm/types/validation/validator.js +2 -0
- package/dist/esm/types/validation/validator.js.map +1 -0
- package/dist/esm/utils/arkos-router/arkos-router-openapi-manager.js +9 -33
- package/dist/esm/utils/arkos-router/arkos-router-openapi-manager.js.map +1 -1
- package/dist/esm/utils/arkos-router/index.js +15 -3
- package/dist/esm/utils/arkos-router/index.js.map +1 -1
- package/dist/esm/utils/arkos-router/types/index.js.map +1 -1
- package/dist/esm/utils/arkos-router/types/upload-config.js.map +1 -1
- package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js +41 -9
- package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js.map +1 -1
- package/dist/esm/utils/arkos-router/utils/helpers/upload-manager.js +26 -6
- package/dist/esm/utils/arkos-router/utils/helpers/upload-manager.js.map +1 -1
- package/dist/esm/utils/cli/build.js +11 -2
- package/dist/esm/utils/cli/build.js.map +1 -1
- package/dist/esm/utils/cli/dev.js +4 -6
- package/dist/esm/utils/cli/dev.js.map +1 -1
- package/dist/esm/utils/cli/index.js +1 -1
- package/dist/esm/utils/cli/index.js.map +1 -1
- package/dist/esm/utils/cli/start.js +20 -11
- package/dist/esm/utils/cli/start.js.map +1 -1
- package/dist/esm/utils/cli/utils/cli.helpers.js +1 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/class-validator-dto-generator.js +53 -17
- package/dist/esm/utils/cli/utils/template-generator/templates/class-validator-dto-generator.js.map +1 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-multiple-components.js +3 -3
- package/dist/esm/utils/cli/utils/template-generator/templates/generate-multiple-components.js.map +1 -1
- package/dist/esm/utils/cli/utils/template-generator/templates/zod-schema-generator.js +18 -18
- package/dist/esm/utils/cli/utils/template-generator/templates/zod-schema-generator.js.map +1 -1
- package/dist/esm/utils/docs-links.js +2 -0
- package/dist/esm/utils/docs-links.js.map +1 -0
- package/dist/esm/utils/features/api.features.js.map +1 -1
- package/dist/esm/utils/helpers/arkos-config.helpers.js.map +1 -1
- package/dist/esm/utils/helpers/exit-error.js +1 -1
- package/dist/esm/utils/helpers/exit-error.js.map +1 -1
- package/dist/esm/utils/initialize-app.js +3 -3
- package/dist/esm/utils/initialize-app.js.map +1 -1
- package/dist/esm/utils/remove-dir.js +1 -1
- package/dist/esm/utils/remove-dir.js.map +1 -1
- package/dist/esm/utils/setup-app.js.map +1 -1
- package/dist/types/components/arkos-gateway/arkos-gateway.d.ts +121 -0
- package/dist/types/components/arkos-gateway/socket-extensions.d.ts +79 -0
- package/dist/types/components/arkos-gateway/types.d.ts +364 -0
- package/dist/types/components/arkos-gateway/utils/helpers.d.ts +9 -0
- package/dist/types/components/arkos-gateway/utils/memory-gateway-store.d.ts +14 -0
- package/dist/types/components/arkos-gateway/utils/multi-tier-arkos-gateway-store.d.ts +20 -0
- package/dist/types/components/arkos-gateway/utils/rate-limiter.d.ts +11 -0
- package/dist/types/components/arkos-route-hook/index.d.ts +4 -4
- package/dist/types/components/arkos-route-hook/reader.d.ts +2 -2
- package/dist/types/components/arkos-route-hook/types.d.ts +6 -0
- package/dist/types/components/arkos-service-hook/index.d.ts +1 -1
- package/dist/types/components/arkos-service-hook/types.d.ts +0 -21
- package/dist/types/exports/index.d.ts +3 -1
- package/dist/types/exports/services/index.d.ts +2 -2
- package/dist/types/exports/websockets.d.ts +5 -0
- package/dist/types/modules/auth/auth.service.d.ts +12 -36
- package/dist/types/modules/auth/utils/auth-hooks-manager.d.ts +63 -0
- package/dist/types/modules/auth/utils/docs-links.d.ts +3 -0
- package/dist/types/modules/auth/utils/services/auth-action.service.d.ts +2 -2
- package/dist/types/modules/base/base.controller.d.ts +2 -2
- package/dist/types/modules/base/base.service.d.ts +4 -7
- package/dist/types/modules/error-handler/utils/catch-async.d.ts +2 -2
- package/dist/types/modules/error-handler/utils/get-handled-error.d.ts +1 -0
- package/dist/types/modules/swagger/utils/helpers/openapi-schema-converter.d.ts +6 -1
- package/dist/types/types/arkos.d.ts +1 -13
- package/dist/types/types/index.d.ts +6 -5
- package/dist/types/types/new-arkos-config.d.ts +1 -1
- package/dist/types/types/upload.d.ts +10 -0
- package/dist/types/types/validation/validation-manager.d.ts +27 -0
- package/dist/types/types/validation/validator.d.ts +2 -0
- package/dist/types/utils/arkos-router/index.d.ts +7 -0
- package/dist/types/utils/arkos-router/types/index.d.ts +35 -21
- package/dist/types/utils/arkos-router/types/upload-config.d.ts +2 -1
- package/dist/types/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.d.ts +6 -7
- package/dist/types/utils/arkos-router/utils/helpers/upload-manager.d.ts +1 -0
- package/dist/types/utils/cli/build.d.ts +1 -1
- package/dist/types/utils/cli/start.d.ts +2 -0
- package/dist/types/utils/cli/utils/template-generator/templates/class-validator-dto-generator.d.ts +7 -0
- package/dist/types/utils/docs-links.d.ts +1 -0
- package/dist/types/utils/features/api.features.d.ts +1 -2
- package/dist/types/utils/helpers/arkos-config.helpers.d.ts +5 -0
- package/package.json +48 -15
|
@@ -9,114 +9,31 @@ const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
|
9
9
|
const catch_async_1 = __importDefault(require("../error-handler/utils/catch-async.js"));
|
|
10
10
|
const app_error_1 = __importDefault(require("../error-handler/utils/app-error.js"));
|
|
11
11
|
const base_middlewares_1 = require("../base/base.middlewares.js");
|
|
12
|
-
const server_1 = require("../../server.js");
|
|
13
12
|
const arkos_env_1 = __importDefault(require("../../utils/arkos-env.js"));
|
|
14
13
|
const prisma_helpers_1 = require("../../utils/helpers/prisma.helpers.js");
|
|
15
14
|
const auth_controller_helpers_1 = require("./utils/helpers/auth.controller.helpers.js");
|
|
16
15
|
const auth_error_objects_1 = require("./utils/auth-error-objects.js");
|
|
17
16
|
const auth_action_service_1 = __importDefault(require("./utils/services/auth-action.service.js"));
|
|
18
17
|
const arkos_config_helpers_1 = require("../../utils/helpers/arkos-config.helpers.js");
|
|
18
|
+
const fs_helpers_1 = require("../../utils/helpers/fs.helpers.js");
|
|
19
|
+
const docs_links_1 = require("./utils/docs-links.js");
|
|
20
|
+
const auth_hooks_manager_1 = __importDefault(require("./utils/auth-hooks-manager.js"));
|
|
19
21
|
class AuthService {
|
|
20
22
|
constructor() {
|
|
21
23
|
this.actionsPerResource = {};
|
|
22
24
|
this.authenticate = (0, catch_async_1.default)(async (req, _, next) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return next(onError.error);
|
|
32
|
-
}
|
|
33
|
-
if (!before.skipped) {
|
|
34
|
-
try {
|
|
35
|
-
if ((0, arkos_config_helpers_1.isAuthenticationEnabled)()) {
|
|
36
|
-
const user = (await this.getAuthenticatedUser(req));
|
|
37
|
-
if (!user)
|
|
38
|
-
throw auth_error_objects_1.loginRequiredError;
|
|
39
|
-
req.user = user;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
catch (err) {
|
|
43
|
-
const onError = await this.runErrorHooks(hooks?.onError, err, req);
|
|
44
|
-
if (onError.skipped) {
|
|
45
|
-
const after = await this.runAfterHooks(hooks?.after, req);
|
|
46
|
-
return after.error ? next(after.error) : next();
|
|
47
|
-
}
|
|
48
|
-
return next(onError.error);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const after = await this.runAfterHooks(hooks?.after, req);
|
|
52
|
-
if (after.error)
|
|
53
|
-
return next(after.error);
|
|
54
|
-
next();
|
|
25
|
+
await auth_hooks_manager_1.default.runAuthenticate({ context: req, done: next }, async (req) => {
|
|
26
|
+
if (!(0, arkos_config_helpers_1.isAuthenticationEnabled)())
|
|
27
|
+
return null;
|
|
28
|
+
const user = (await this.getAuthenticatedUser(req, req.path.includes("logout") ? "logout" : "default"));
|
|
29
|
+
if (!user)
|
|
30
|
+
throw auth_error_objects_1.loginRequiredError;
|
|
31
|
+
return user;
|
|
32
|
+
});
|
|
55
33
|
});
|
|
56
34
|
}
|
|
57
|
-
async runHooks(hooks, req, ctx) {
|
|
58
|
-
if (!hooks)
|
|
59
|
-
return { skipped: false };
|
|
60
|
-
const hookArray = Array.isArray(hooks) ? hooks : [hooks];
|
|
61
|
-
for (const hook of hookArray) {
|
|
62
|
-
let skipCalled = false;
|
|
63
|
-
try {
|
|
64
|
-
await hook({
|
|
65
|
-
req,
|
|
66
|
-
skip: () => {
|
|
67
|
-
skipCalled = true;
|
|
68
|
-
},
|
|
69
|
-
...ctx,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
return { skipped: false, error: err };
|
|
74
|
-
}
|
|
75
|
-
if (skipCalled)
|
|
76
|
-
return { skipped: true };
|
|
77
|
-
}
|
|
78
|
-
return { skipped: false };
|
|
79
|
-
}
|
|
80
|
-
async runAfterHooks(hooks, req, ctx) {
|
|
81
|
-
if (!hooks)
|
|
82
|
-
return {};
|
|
83
|
-
const hookArray = Array.isArray(hooks) ? hooks : [hooks];
|
|
84
|
-
for (const hook of hookArray) {
|
|
85
|
-
try {
|
|
86
|
-
await hook({ req, ...ctx });
|
|
87
|
-
}
|
|
88
|
-
catch (err) {
|
|
89
|
-
return { error: err };
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return {};
|
|
93
|
-
}
|
|
94
|
-
async runErrorHooks(hooks, error, req, ctx) {
|
|
95
|
-
if (!hooks)
|
|
96
|
-
return { skipped: false, error };
|
|
97
|
-
const hookArray = Array.isArray(hooks) ? hooks : [hooks];
|
|
98
|
-
for (const hook of hookArray) {
|
|
99
|
-
let skipCalled = false;
|
|
100
|
-
try {
|
|
101
|
-
await hook({
|
|
102
|
-
req,
|
|
103
|
-
error,
|
|
104
|
-
skip: () => {
|
|
105
|
-
skipCalled = true;
|
|
106
|
-
},
|
|
107
|
-
...ctx,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
return { skipped: false, error: err };
|
|
112
|
-
}
|
|
113
|
-
if (skipCalled)
|
|
114
|
-
return { skipped: true };
|
|
115
|
-
}
|
|
116
|
-
return { skipped: false, error };
|
|
117
|
-
}
|
|
118
35
|
signJwtToken(id, expiresIn, secret) {
|
|
119
|
-
const { authentication: configs } = (0,
|
|
36
|
+
const { authentication: configs } = (0, arkos_config_helpers_1.getArkosConfig)();
|
|
120
37
|
if (process.env.ARKOS_BUILD === "true" &&
|
|
121
38
|
!process.env.JWT_SECRET &&
|
|
122
39
|
!configs?.jwt?.secret)
|
|
@@ -135,7 +52,7 @@ class AuthService {
|
|
|
135
52
|
});
|
|
136
53
|
}
|
|
137
54
|
getJwtCookieOptions(req) {
|
|
138
|
-
const arkosConfig = (0,
|
|
55
|
+
const arkosConfig = (0, arkos_config_helpers_1.getArkosConfig)();
|
|
139
56
|
const authConfigs = arkosConfig?.authentication;
|
|
140
57
|
if (!req)
|
|
141
58
|
throw new Error("Missing req object in order get jwt cookie options");
|
|
@@ -175,7 +92,7 @@ class AuthService {
|
|
|
175
92
|
return await bcryptjs_1.default.hash(password, 12);
|
|
176
93
|
}
|
|
177
94
|
isPasswordStrong(password) {
|
|
178
|
-
const initAuthConfigs = (0,
|
|
95
|
+
const initAuthConfigs = (0, arkos_config_helpers_1.getArkosConfig)()?.authentication;
|
|
179
96
|
const strongPasswordRegex = initAuthConfigs?.passwordValidation?.regex ||
|
|
180
97
|
/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).+$/;
|
|
181
98
|
return strongPasswordRegex.test(password);
|
|
@@ -188,7 +105,7 @@ class AuthService {
|
|
|
188
105
|
return false;
|
|
189
106
|
}
|
|
190
107
|
async verifyJwtToken(token, secret) {
|
|
191
|
-
const { authentication: configs } = (0,
|
|
108
|
+
const { authentication: configs } = (0, arkos_config_helpers_1.getArkosConfig)();
|
|
192
109
|
if (process.env.ARKOS_BUILD === "true" &&
|
|
193
110
|
!process.env.JWT_SECRET &&
|
|
194
111
|
!configs?.jwt?.secret)
|
|
@@ -198,14 +115,22 @@ class AuthService {
|
|
|
198
115
|
configs?.jwt?.secret ||
|
|
199
116
|
process.env.JWT_SECRET ||
|
|
200
117
|
arkos_env_1.default.JWT_SECRET;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
118
|
+
try {
|
|
119
|
+
const decoded = (await new Promise((resolve, reject) => {
|
|
120
|
+
jsonwebtoken_1.default.verify(token, secret, (err, decoded) => {
|
|
121
|
+
if (err)
|
|
122
|
+
reject(err);
|
|
123
|
+
else
|
|
124
|
+
resolve(decoded);
|
|
125
|
+
});
|
|
126
|
+
}));
|
|
127
|
+
if (!decoded?.id)
|
|
128
|
+
throw auth_error_objects_1.invaliAuthTokenError;
|
|
129
|
+
return decoded;
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
throw auth_error_objects_1.invaliAuthTokenError;
|
|
133
|
+
}
|
|
209
134
|
}
|
|
210
135
|
isWildcardAccess(config) {
|
|
211
136
|
return config === "*";
|
|
@@ -244,32 +169,40 @@ class AuthService {
|
|
|
244
169
|
}
|
|
245
170
|
async checkDynamicAccessControl(userId, action, resource) {
|
|
246
171
|
const prisma = (0, prisma_helpers_1.getPrismaInstance)();
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
172
|
+
const [userPermission, hasRolePermission] = await Promise.all([
|
|
173
|
+
prisma.userPermission
|
|
174
|
+
? prisma.userPermission.findFirst({
|
|
175
|
+
where: { userId, permission: { resource, action } },
|
|
176
|
+
select: { effect: true },
|
|
177
|
+
})
|
|
178
|
+
: Promise.resolve(null),
|
|
179
|
+
prisma.userRole.findFirst({
|
|
180
|
+
where: {
|
|
181
|
+
userId,
|
|
182
|
+
role: {
|
|
183
|
+
permissions: {
|
|
184
|
+
some: { resource, action },
|
|
255
185
|
},
|
|
256
186
|
},
|
|
257
187
|
},
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
188
|
+
select: { id: true },
|
|
189
|
+
}),
|
|
190
|
+
]);
|
|
191
|
+
if (userPermission)
|
|
192
|
+
return userPermission.effect === "Allow";
|
|
193
|
+
return !!hasRolePermission;
|
|
261
194
|
}
|
|
262
195
|
handleAccessControl(action, resource, accessControl) {
|
|
263
|
-
auth_action_service_1.default.add(action, resource, accessControl);
|
|
196
|
+
const authAction = auth_action_service_1.default.add(action, resource, accessControl);
|
|
264
197
|
return (0, catch_async_1.default)(async (req, _, next) => {
|
|
265
198
|
if (req.user) {
|
|
266
199
|
const user = req.user;
|
|
267
|
-
const configs = (0,
|
|
200
|
+
const configs = (0, arkos_config_helpers_1.getArkosConfig)();
|
|
268
201
|
if (user.isSuperUser) {
|
|
269
202
|
next();
|
|
270
203
|
return;
|
|
271
204
|
}
|
|
272
|
-
const notEnoughPermissionsError = new app_error_1.default(
|
|
205
|
+
const notEnoughPermissionsError = new app_error_1.default(authAction.errorMessage, 403, "NotEnoughPermissions");
|
|
273
206
|
if (configs?.authentication?.mode === "dynamic") {
|
|
274
207
|
const hasPermission = await this.checkDynamicAccessControl(user.id, action, resource);
|
|
275
208
|
if (!hasPermission)
|
|
@@ -286,108 +219,54 @@ class AuthService {
|
|
|
286
219
|
next();
|
|
287
220
|
});
|
|
288
221
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
throw Error("ValidationError: Trying to call AuthService.getAuthenticatedUser without setting up authentication");
|
|
292
|
-
const prisma = (0, prisma_helpers_1.getPrismaInstance)();
|
|
293
|
-
let token;
|
|
222
|
+
extractRequestToken(req, cookie = "arkos_access_token") {
|
|
223
|
+
let token = null;
|
|
294
224
|
if (req?.headers?.authorization &&
|
|
295
225
|
req?.headers?.authorization.startsWith("Bearer") &&
|
|
296
226
|
req?.headers?.authorization.split?.(" ")?.[1])
|
|
297
227
|
token = req?.headers?.authorization.split(" ")[1];
|
|
298
228
|
if (!token &&
|
|
299
229
|
req?.cookies?.arkos_access_token !== "no-token" &&
|
|
300
|
-
req.cookies)
|
|
301
|
-
token = req?.cookies?.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
throw auth_error_objects_1.invaliAuthTokenError;
|
|
311
|
-
}
|
|
312
|
-
if (!decoded?.id)
|
|
313
|
-
throw auth_error_objects_1.invaliAuthTokenError;
|
|
230
|
+
req.cookies)
|
|
231
|
+
token = req?.cookies?.[cookie];
|
|
232
|
+
return token;
|
|
233
|
+
}
|
|
234
|
+
extractSocketToken(socket, key = "token") {
|
|
235
|
+
return (socket.handshake.auth?.[key] ||
|
|
236
|
+
socket.handshake.headers?.authorization?.replace("Bearer ", ""));
|
|
237
|
+
}
|
|
238
|
+
async validateDecodedUser(decoded, action = "default") {
|
|
239
|
+
const prisma = (0, prisma_helpers_1.getPrismaInstance)();
|
|
314
240
|
const user = await prisma.user.findUnique({
|
|
315
|
-
where: { id:
|
|
241
|
+
where: { id: decoded.id },
|
|
316
242
|
});
|
|
317
243
|
if (!user)
|
|
318
|
-
throw new app_error_1.default("The user belonging to this token
|
|
319
|
-
if (
|
|
320
|
-
|
|
244
|
+
throw new app_error_1.default("The user belonging to this token no longer exists", 401, "UserNoLongerExists");
|
|
245
|
+
if (action !== "logout" &&
|
|
246
|
+
this.userChangedPasswordAfter(user, decoded.iat))
|
|
321
247
|
throw new app_error_1.default("User recently changed password! Please log in again.", 401, "PasswordChanged");
|
|
322
|
-
req.accessToken = token;
|
|
323
248
|
return user;
|
|
324
249
|
}
|
|
250
|
+
async getAuthenticatedUser(ctx, action = "default") {
|
|
251
|
+
if (!(0, arkos_config_helpers_1.isAuthenticationEnabled)())
|
|
252
|
+
throw Error(`Trying to call authService.getAuthenticatedUser without setting up authentication in arkos.config.${(0, fs_helpers_1.getUserFileExtension)()}, see ${docs_links_1.authenticationDocsLinks.setup}`);
|
|
253
|
+
let token = null;
|
|
254
|
+
if ("headers" in ctx)
|
|
255
|
+
token = this.extractRequestToken(ctx);
|
|
256
|
+
else if ("join" in ctx)
|
|
257
|
+
token = this.extractSocketToken(ctx);
|
|
258
|
+
if (!token)
|
|
259
|
+
return null;
|
|
260
|
+
const decoded = await this.verifyJwtToken(token);
|
|
261
|
+
ctx.accessToken = token;
|
|
262
|
+
return this.validateDecodedUser(decoded, action);
|
|
263
|
+
}
|
|
325
264
|
authorize(action, resource, rule) {
|
|
326
|
-
auth_action_service_1.default.add(action, resource, {
|
|
265
|
+
const authAction = auth_action_service_1.default.add(action, resource, {
|
|
266
|
+
[action]: rule,
|
|
267
|
+
});
|
|
327
268
|
return (0, catch_async_1.default)(async (req, _, next) => {
|
|
328
|
-
|
|
329
|
-
const before = await this.runHooks(hooks?.before, req, {
|
|
330
|
-
action,
|
|
331
|
-
resource,
|
|
332
|
-
rule,
|
|
333
|
-
});
|
|
334
|
-
if (before.error) {
|
|
335
|
-
const onError = await this.runErrorHooks(hooks?.onError, before.error, req, { action, resource, rule });
|
|
336
|
-
if (onError.skipped) {
|
|
337
|
-
const after = await this.runAfterHooks(hooks?.after, req, {
|
|
338
|
-
action,
|
|
339
|
-
resource,
|
|
340
|
-
rule,
|
|
341
|
-
});
|
|
342
|
-
return after.error ? next(after.error) : next();
|
|
343
|
-
}
|
|
344
|
-
return next(onError.error);
|
|
345
|
-
}
|
|
346
|
-
if (!before.skipped) {
|
|
347
|
-
try {
|
|
348
|
-
if (req.user) {
|
|
349
|
-
const user = req.user;
|
|
350
|
-
const configs = (0, server_1.getArkosConfig)();
|
|
351
|
-
if (!user.isSuperUser) {
|
|
352
|
-
const notEnoughPermissionsError = new app_error_1.default("You do not have permission to perform this action", 403, "NotEnoughPermissions");
|
|
353
|
-
if (configs?.authentication?.mode === "dynamic") {
|
|
354
|
-
const hasPermission = await this.checkDynamicAccessControl(user.id, action, resource);
|
|
355
|
-
if (!hasPermission)
|
|
356
|
-
throw notEnoughPermissionsError;
|
|
357
|
-
}
|
|
358
|
-
else if (configs?.authentication?.mode === "static") {
|
|
359
|
-
const hasPermission = this.checkStaticAccessControl(user, action, { [action]: rule });
|
|
360
|
-
if (!hasPermission)
|
|
361
|
-
throw notEnoughPermissionsError;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
catch (err) {
|
|
367
|
-
const onError = await this.runErrorHooks(hooks?.onError, err, req, {
|
|
368
|
-
action,
|
|
369
|
-
resource,
|
|
370
|
-
rule,
|
|
371
|
-
});
|
|
372
|
-
if (onError.skipped) {
|
|
373
|
-
const after = await this.runAfterHooks(hooks?.after, req, {
|
|
374
|
-
action,
|
|
375
|
-
resource,
|
|
376
|
-
rule,
|
|
377
|
-
});
|
|
378
|
-
return after.error ? next(after.error) : next();
|
|
379
|
-
}
|
|
380
|
-
return next(onError.error);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
const after = await this.runAfterHooks(hooks?.after, req, {
|
|
384
|
-
action,
|
|
385
|
-
resource,
|
|
386
|
-
rule,
|
|
387
|
-
});
|
|
388
|
-
if (after.error)
|
|
389
|
-
return next(after.error);
|
|
390
|
-
next();
|
|
269
|
+
await auth_hooks_manager_1.default.runAuthorize({ context: req, done: next }, authAction);
|
|
391
270
|
});
|
|
392
271
|
}
|
|
393
272
|
handleAuthenticationControl(action, authenticationControl) {
|
|
@@ -407,7 +286,7 @@ class AuthService {
|
|
|
407
286
|
throw new Error("authService.permission() should be called during application initialization level.");
|
|
408
287
|
auth_action_service_1.default.add(action, resource, accessControl);
|
|
409
288
|
return async (user) => {
|
|
410
|
-
const configs = (0,
|
|
289
|
+
const configs = (0, arkos_config_helpers_1.getArkosConfig)();
|
|
411
290
|
if (!(0, arkos_config_helpers_1.isUsingAuthentication)())
|
|
412
291
|
throw Error("Validation Error: Trying to use authService.permission without setting up authentication.");
|
|
413
292
|
if (!(0, arkos_config_helpers_1.isAuthenticationEnabled)())
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../../../src/modules/auth/auth.service.ts"],"names":[],"mappings":"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","sourcesContent":["import jwt, { SignOptions } from \"jsonwebtoken\";\nimport bcrypt from \"bcryptjs\";\nimport { User } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { callNext } from \"../base/base.middlewares\";\nimport { getArkosConfig } from \"../../server\";\nimport arkosEnv from \"../../utils/arkos-env\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport {\n ArkosRequest,\n ArkosResponse,\n ArkosNextFunction,\n ArkosRequestHandler,\n} from \"../../types\";\nimport {\n AuthJwtPayload,\n AccessAction,\n AccessControlConfig,\n AuthenticationControlConfig,\n AccessControlRules,\n DetailedAccessControlRule,\n} from \"../../types/auth\";\nimport { MsDuration, toMs } from \"./utils/helpers/auth.controller.helpers\";\nimport {\n invaliAuthTokenError,\n loginRequiredError,\n} from \"./utils/auth-error-objects\";\nimport authActionService from \"./utils/services/auth-action.service\";\nimport {\n isAuthenticationEnabled,\n isUsingAuthentication,\n} from \"../../utils/helpers/arkos-config.helpers\";\nimport {\n AuthenticateHookHandler,\n AuthenticateAfterHookHandler,\n AuthenticateErrorHookHandler,\n AuthorizeHookHandler,\n AuthorizeAfterHookHandler,\n AuthorizeErrorHookHandler,\n} from \"../../types/arkos-config/utils\";\nimport { CookieOptions } from \"express\";\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nexport class AuthService {\n /**\n * Object containing a combination of actions per resource, tracked by each set of calls of `authService.handleAccessControl`, this can be accessed through the `authService` object or through the endpoint\n */\n actionsPerResource: Record<string, Set<string>> = {};\n\n /**\n * Runs a chain of `before` hooks in sequence.\n *\n * - If a hook throws — chain aborts, error is forwarded to `onError` hooks.\n * - If a hook calls `skip()` — chain stops, core logic is bypassed, jumps to `after` hooks.\n * - If a hook returns — next hook in chain runs.\n *\n * @returns Promise resolving to `{ skipped, error? }`\n */\n private async runHooks(\n hooks:\n | AuthenticateHookHandler\n | AuthenticateHookHandler[]\n | AuthorizeHookHandler\n | AuthorizeHookHandler[]\n | undefined,\n req: ArkosRequest,\n ctx?: {\n action?: AccessAction;\n resource?: string;\n rule?: string[] | DetailedAccessControlRule | \"*\";\n }\n ): Promise<{ skipped: boolean; error?: unknown }> {\n if (!hooks) return { skipped: false };\n\n const hookArray = Array.isArray(hooks) ? hooks : [hooks];\n\n for (const hook of hookArray) {\n let skipCalled = false;\n\n try {\n await (hook as any)({\n req,\n skip: () => {\n skipCalled = true;\n },\n ...ctx,\n });\n } catch (err) {\n return { skipped: false, error: err };\n }\n\n if (skipCalled) return { skipped: true };\n }\n\n return { skipped: false };\n }\n\n /**\n * Runs a chain of `after` hooks in sequence.\n *\n * - If a hook throws — chain aborts, error is forwarded to the global error handler.\n * - If a hook returns — next hook in chain runs.\n *\n * @returns Promise resolving to `{ error? }`\n */\n private async runAfterHooks(\n hooks:\n | AuthenticateAfterHookHandler\n | AuthenticateAfterHookHandler[]\n | AuthorizeAfterHookHandler\n | AuthorizeAfterHookHandler[]\n | undefined,\n req: ArkosRequest,\n ctx?: {\n action?: AccessAction;\n resource?: string;\n rule?: string[] | DetailedAccessControlRule | \"*\";\n }\n ): Promise<{ error?: unknown }> {\n if (!hooks) return {};\n\n const hookArray = Array.isArray(hooks) ? hooks : [hooks];\n\n for (const hook of hookArray) {\n try {\n await (hook as any)({ req, ...ctx });\n } catch (err) {\n return { error: err };\n }\n }\n\n return {};\n }\n\n /**\n * Runs a chain of `onError` hooks in sequence.\n *\n * - If a hook throws — chain aborts, error is forwarded to the global error handler.\n * - If a hook calls `skip()` — suppresses the error and jumps to `after` hooks.\n * - If a hook returns — next hook in chain runs.\n *\n * @returns Promise resolving to `{ skipped, error? }`\n */\n private async runErrorHooks(\n hooks:\n | AuthenticateErrorHookHandler\n | AuthenticateErrorHookHandler[]\n | AuthorizeErrorHookHandler\n | AuthorizeErrorHookHandler[]\n | undefined,\n error: unknown,\n req: ArkosRequest,\n ctx?: {\n action?: AccessAction;\n resource?: string;\n rule?: string[] | DetailedAccessControlRule | \"*\";\n }\n ): Promise<{ skipped: boolean; error?: unknown }> {\n if (!hooks) return { skipped: false, error };\n\n const hookArray = Array.isArray(hooks) ? hooks : [hooks];\n\n for (const hook of hookArray) {\n let skipCalled = false;\n\n try {\n await (hook as any)({\n req,\n error,\n skip: () => {\n skipCalled = true;\n },\n ...ctx,\n });\n } catch (err) {\n return { skipped: false, error: err };\n }\n\n if (skipCalled) return { skipped: true };\n }\n\n return { skipped: false, error };\n }\n /**\n * Signs a JWT token for the user.\n *\n * @param {number | string} id - The unique identifier of the user to generate the token for.\n * @param {string | number} [expiresIn] - The expiration time for the token. Defaults to environment variable `JWT_EXPIRES_IN`.\n * @param {string} [secret] - The secret key used to sign the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {string} The signed JWT token.\n */\n signJwtToken(\n id: number | string,\n expiresIn?: MsDuration | number,\n secret?: string\n ): string {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.ARKOS_BUILD === \"true\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\n \"Missing JWT secret on production!\",\n 500,\n \"MissingJWTOnProduction\"\n );\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n expiresIn = (expiresIn ||\n configs?.jwt?.expiresIn ||\n process.env.JWT_EXPIRES_IN ||\n arkosEnv.JWT_EXPIRES_IN) as keyof SignOptions[\"expiresIn\"];\n\n return jwt.sign({ id }, secret, {\n expiresIn: expiresIn as MsDuration,\n });\n }\n\n /**\n * Retrieves cookie configuration options for JWT authentication.\n *\n * Merges configuration from multiple sources in order of precedence:\n * 1. Arkos configuration file\n * 2. Environment variables\n * 3. Request properties (for secure flag)\n * 4. Default fallback values\n *\n * @param req - ArkosRequest object used to determine if the connection is secure\n * @returns Cookie options object with expires, httpOnly, secure, and sameSite properties\n *\n * @example\n * ```typescript\n * const cookieOptions = authService.getJwtCookieOptions(req);\n * res.cookie('jwt', token, cookieOptions);\n * ```\n */\n getJwtCookieOptions(req: ArkosRequest) {\n const arkosConfig = getArkosConfig();\n const authConfigs = arkosConfig?.authentication;\n\n if (!req)\n throw new Error(\"Missing req object in order get jwt cookie options\");\n\n const sameSite =\n authConfigs?.jwt?.cookie?.sameSite ||\n (process.env.JWT_COOKIE_SAME_SITE as\n | \"none\"\n | \"lax\"\n | \"strict\"\n | undefined) ||\n \"lax\";\n\n return {\n expires: new Date(\n Date.now() +\n Number(\n toMs(\n authConfigs?.jwt?.expiresIn ||\n (process.env.JWT_EXPIRES_IN as MsDuration) ||\n (arkosEnv.JWT_EXPIRES_IN as MsDuration)\n )\n )\n ),\n httpOnly:\n authConfigs?.jwt?.cookie?.httpOnly ??\n (process.env.JWT_COOKIE_HTTP_ONLY !== undefined\n ? process.env.JWT_COOKIE_HTTP_ONLY === \"true\"\n : undefined) ??\n true,\n secure: (() => {\n if (authConfigs?.jwt?.cookie?.secure !== undefined)\n return authConfigs?.jwt?.cookie?.secure;\n else if (process.env.JWT_COOKIE_SECURE !== undefined)\n return process.env.JWT_COOKIE_SECURE === \"true\";\n else return req.secure || req.headers[\"x-forwarded-proto\"] === \"https\";\n })(),\n sameSite,\n domain: authConfigs?.jwt?.cookie?.domain || process.env.JWT_COOKIE_DOMAIN,\n ...arkosConfig?.authentication?.jwt?.cookie,\n } as CookieOptions;\n }\n\n /**\n * Is used by default internally by Arkos under `BaseService` class to check if the password is already hashed.\n *\n * This was just added to prevent unwanted errors when someone just forgets that the `BaseService` class will automatically hash the password field using `authService.hashPassword` by default.\n *\n * So now before `BaseService` hashes it will test it.\n *\n *\n * @param password The password to be tested if is hashed\n * @returns\n */\n isPasswordHashed(password: string) {\n return !Number.isNaN(bcrypt.getRounds(password) * 1);\n }\n\n /**\n * Compares a candidate password with the stored user password to check if they match.\n *\n * @param {string} candidatePassword - The password provided by the user during login.\n * @param {string} userPassword - The password stored in the database.\n * @returns {Promise<boolean>} Returns true if the passwords match, otherwise false.\n */\n async isCorrectPassword(\n candidatePassword: string,\n userPassword: string\n ): Promise<boolean> {\n return await bcrypt.compare(candidatePassword, userPassword);\n }\n\n /**\n * Hashes a plain text password using bcrypt.\n *\n * @param {string} password - The password to be hashed.\n * @returns {Promise<string>} Returns the hashed password.\n */\n async hashPassword(password: string): Promise<string> {\n return await bcrypt.hash(password, 12);\n }\n\n /**\n * Checks if a password is strong, requiring uppercase, lowercase, and numeric characters as the default.\n *\n * **NB**: You must pay attention when using custom validation with zod or class-validator, try to use the same regex always.\n *\n * **Note**: You can define it when calling arkos.init()\n * ```ts\n * arkos.init({\n * authentication: {\n * passwordValidation:{ regex: /your-desired-regex/, message: 'password must contain...'}\n * }\n * })\n * ```\n *\n * @param {string} password - The password to check.\n * @returns {boolean} Returns true if the password meets the strength criteria, otherwise false.\n */\n public isPasswordStrong(password: string): boolean {\n const initAuthConfigs = getArkosConfig()?.authentication;\n\n const strongPasswordRegex =\n initAuthConfigs?.passwordValidation?.regex ||\n /^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).+$/;\n return strongPasswordRegex.test(password);\n }\n\n /**\n * Checks if a user has changed their password after the JWT was issued.\n *\n * @param {User} user - The user object containing the passwordChangedAt field.\n * @param {number} JWTTimestamp - The timestamp when the JWT was issued.\n * @returns {boolean} Returns true if the user changed their password after the JWT was issued, otherwise false.\n */\n userChangedPasswordAfter(user: User, JWTTimestamp: number): boolean {\n if (user.passwordChangedAt) {\n const convertedTimestamp = parseInt(\n String(new Date(user.passwordChangedAt).getTime() / 1000),\n 10\n );\n\n return JWTTimestamp < convertedTimestamp;\n }\n return false;\n }\n\n /**\n * Verifies the authenticity of a JWT token.\n *\n * @param {string} token - The JWT token to verify.\n * @param {string} [secret] - The secret key used to verify the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {Promise<AuthJwtPayload>} Returns the decoded JWT payload if the token is valid.\n * @throws {Error} Throws an error if the token is invalid or expired.\n */\n async verifyJwtToken(\n token: string,\n secret?: string\n ): Promise<AuthJwtPayload> {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.ARKOS_BUILD === \"true\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\n \"Missing JWT secret in production\",\n 500,\n \"MissingJWTSecretInProduction\"\n );\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n return new Promise((resolve, reject) => {\n jwt.verify(token, secret, (err, decoded) => {\n if (err) reject(err);\n else resolve(decoded as AuthJwtPayload);\n });\n });\n }\n\n private isWildcardAccess(config: AccessControlConfig): config is \"*\" {\n return config === \"*\";\n }\n\n private isRoleList(config: AccessControlConfig): config is string[] {\n return Array.isArray(config);\n }\n\n private isAccessRules(\n config: AccessControlConfig\n ): config is Partial<AccessControlRules> {\n return (\n typeof config === \"object\" && config !== null && !Array.isArray(config)\n );\n }\n\n private normalizeRuleToRoles(\n rule: string[] | DetailedAccessControlRule | \"*\" | undefined\n ): string[] {\n if (!rule) return [];\n if (rule === \"*\") return [\"*\"];\n if (Array.isArray(rule)) return rule;\n return rule.roles === \"*\" ? [\"*\"] : (rule.roles ?? []);\n }\n\n private resolveAuthorizedRoles(\n action: AccessAction,\n accessControl: AccessControlConfig\n ): string[] {\n if (this.isWildcardAccess(accessControl)) return [\"*\"];\n if (this.isRoleList(accessControl)) return accessControl;\n if (this.isAccessRules(accessControl))\n return this.normalizeRuleToRoles(accessControl[action]);\n return [];\n }\n\n /**\n * Checks if a user has permission for a specific action using static access control rules.\n * Validates user roles against predefined access control configuration.\n *\n * @param user - The user object containing role or roles field\n * @param action - The action being performed\n * @param accessControl - Access control configuration (array of roles or object with action-role mappings)\n * @returns True if user has permission, false otherwise\n * @throws Error if user doesn't have role/roles field\n */\n protected checkStaticAccessControl(\n user: User,\n action: string,\n accessControl: AccessControlConfig\n ) {\n if (!user?.role && !user.roles)\n throw Error(\n \"Validation Error: In order to use static authentication user needs at least role field or roles for multiple roles.\"\n );\n\n let authorizedRoles = this.resolveAuthorizedRoles(action, accessControl);\n\n const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];\n\n return (\n authorizedRoles?.[0] === \"*\" ||\n !!userRoles.some((role: string) => authorizedRoles.includes(role))\n );\n }\n\n /**\n * Checks if a user has permission for a specific action and resource using dynamic access control.\n * Queries the database to verify user's role permissions.\n *\n * @param userId - The unique identifier of the user\n * @param action - The action being performed\n * @param resource - The resource being accessed\n * @returns Promise resolving to true if user has permission, false otherwise\n */\n protected async checkDynamicAccessControl(\n userId: string,\n action: string,\n resource: string\n ) {\n const prisma = getPrismaInstance();\n return !!(await prisma.userRole.findFirst({\n where: {\n userId,\n role: {\n permissions: {\n some: {\n resource,\n action,\n },\n },\n },\n },\n select: { id: true },\n }));\n }\n\n /**\n * Middleware function to handle access control based on user roles and permissions.\n *\n * @param {AccessAction} action - The action being performed (e.g., create, update, delete, view).\n * @param {string} resource - The resource name that the action is being performed on (e.g., \"User\", \"Post\").\n * @param {AccessControlConfig} accessControl - The access control configuration.\n * @returns {ArkosRequestHandler} The middleware function that checks if the user has permission to perform the action.\n *\n * @deprecated Will be removed on v2.0, use AuthService.authorize instead\n */\n handleAccessControl(\n action: AccessAction,\n resource: string,\n accessControl?: AccessControlConfig\n ): ArkosRequestHandler {\n authActionService.add(action, resource, accessControl);\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n if (req.user) {\n const user = req.user as User;\n const configs = getArkosConfig();\n\n if (user.isSuperUser) {\n next();\n return;\n }\n\n const notEnoughPermissionsError = new AppError(\n \"You do not have permission to perfom this action\",\n 403,\n \"NotEnoughPermissions\"\n );\n\n if (configs?.authentication?.mode === \"dynamic\") {\n const hasPermission = await this.checkDynamicAccessControl(\n user.id,\n action,\n resource\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n } else if (configs?.authentication?.mode === \"static\") {\n if (!accessControl) return next(notEnoughPermissionsError);\n\n const hasPermission = this.checkStaticAccessControl(\n user,\n action,\n accessControl\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n }\n }\n\n next();\n }\n );\n }\n\n /**\n * Processes the cookies or authoriation token and returns the user.\n * @param req\n * @returns {Promise<User | null>} - if authentication is turned off in arkosConfig it returns null\n * @throws {AppError} Throws an error if the token is invalid or the user is not logged in.\n */\n async getAuthenticatedUser(req: ArkosRequest): Promise<User | null> {\n if (!isAuthenticationEnabled())\n throw Error(\n \"ValidationError: Trying to call AuthService.getAuthenticatedUser without setting up authentication\"\n );\n\n const prisma = getPrismaInstance();\n\n let token: string | undefined;\n\n if (\n req?.headers?.authorization &&\n req?.headers?.authorization.startsWith(\"Bearer\") &&\n req?.headers?.authorization.split?.(\" \")?.[1]\n )\n token = req?.headers?.authorization.split(\" \")[1];\n\n if (\n !token &&\n req?.cookies?.arkos_access_token !== \"no-token\" &&\n req.cookies\n ) {\n token = req?.cookies?.arkos_access_token;\n }\n\n if (!token) return null;\n\n let decoded: AuthJwtPayload | undefined;\n\n try {\n decoded = await this.verifyJwtToken(token);\n } catch (err) {\n throw invaliAuthTokenError;\n }\n\n if (!decoded?.id) throw invaliAuthTokenError;\n const user: any | null = await (prisma as any).user.findUnique({\n where: { id: String(decoded.id) },\n });\n\n if (!user)\n throw new AppError(\n \"The user belonging to this token does no longer exists\",\n 401,\n \"UserNoLongerExists\"\n );\n\n if (\n this.userChangedPasswordAfter(user, decoded.iat!) &&\n !req.path?.includes?.(\"logout\")\n )\n throw new AppError(\n \"User recently changed password! Please log in again.\",\n 401,\n \"PasswordChanged\"\n );\n\n req.accessToken = token;\n return user;\n }\n\n /**\n * Middleware to authenticate the request by extracting and verifying the JWT token and setting `req.user`.\n *\n * Runs `authentication.hooks.authenticate` before/after the authentication logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — extracts and verifies the JWT token, sets `req.user`.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if core logic throws — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * On custom routes, hooks defined in `arkosConfig` still apply since they are baked into this method.\n *\n * @example\n * ```ts\n * // custom route - hooks still run\n * router.get(\"/custom\", authService.authenticate, handler);\n * ```\n *\n * @example\n * ```ts\n * // skip built-in auth from a before hook\n * before: (ctx) => {\n * ctx.req.user = myCustomAuth(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks}\n */\n authenticate = catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n const hooks = getArkosConfig()?.authentication?.hooks?.authenticate;\n\n const before = await this.runHooks(hooks?.before, req);\n if (before.error) {\n const onError = await this.runErrorHooks(\n hooks?.onError,\n before.error,\n req\n );\n if (onError.skipped) {\n const after = await this.runAfterHooks(hooks?.after, req);\n return after.error ? next(after.error) : next();\n }\n return next(onError.error);\n }\n\n if (!before.skipped) {\n try {\n if (isAuthenticationEnabled()) {\n const user = (await this.getAuthenticatedUser(req)) as User;\n if (!user) throw loginRequiredError;\n req.user = user;\n }\n } catch (err) {\n const onError = await this.runErrorHooks(hooks?.onError, err, req);\n if (onError.skipped) {\n const after = await this.runAfterHooks(hooks?.after, req);\n return after.error ? next(after.error) : next();\n }\n return next(onError.error);\n }\n }\n\n const after = await this.runAfterHooks(hooks?.after, req);\n if (after.error) return next(after.error);\n\n next();\n }\n );\n\n /**\n * Middleware to authorize the authenticated user for a given action on a resource.\n *\n * Runs `authentication.hooks.authorize` before/after the authorization logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — checks user role/permissions against the access control rules.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if authorization fails — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * @param resource - The resource being accessed, in kebabCase (e.g. `\"product\"`, `\"cart-item\"`)\n * @param action - The action being performed (e.g. `\"View\"`, `\"Create\"`, `\"Delete\"`)\n * @param rule - Access control rules for this action. Accepts a role list, a wildcard, or a `DetailedAccessControlRule`.\n *\n * @example\n * ```ts\n * router.delete(\"/products/:id\",\n * authService.authenticate,\n * authService.authorize(\"product\", \"Delete\", [\"admin\"]),\n * handler\n * );\n * ```\n *\n * @example\n * ```ts\n * // skip built-in authorization from a before hook\n * before: (ctx) => {\n * ctx.req.user.role = myCustomRoleResolver(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks#authorize}\n * @since v1.6.0-beta\n */\n authorize(\n action: AccessAction,\n resource: string,\n rule?: string[] | DetailedAccessControlRule | \"*\"\n ): ArkosRequestHandler {\n authActionService.add(action, resource, { [action]: rule });\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n const hooks = getArkosConfig()?.authentication?.hooks?.authorize;\n\n const before = await this.runHooks(hooks?.before, req, {\n action,\n resource,\n rule,\n });\n if (before.error) {\n const onError = await this.runErrorHooks(\n hooks?.onError,\n before.error,\n req,\n { action, resource, rule }\n );\n if (onError.skipped) {\n const after = await this.runAfterHooks(hooks?.after, req, {\n action,\n resource,\n rule,\n });\n return after.error ? next(after.error) : next();\n }\n return next(onError.error);\n }\n\n if (!before.skipped) {\n try {\n if (req.user) {\n const user = req.user as User;\n const configs = getArkosConfig();\n\n if (!user.isSuperUser) {\n const notEnoughPermissionsError = new AppError(\n \"You do not have permission to perform this action\",\n 403,\n \"NotEnoughPermissions\"\n );\n\n if (configs?.authentication?.mode === \"dynamic\") {\n const hasPermission = await this.checkDynamicAccessControl(\n user.id,\n action,\n resource\n );\n if (!hasPermission) throw notEnoughPermissionsError;\n } else if (configs?.authentication?.mode === \"static\") {\n const hasPermission = this.checkStaticAccessControl(\n user,\n action,\n { [action]: rule }\n );\n if (!hasPermission) throw notEnoughPermissionsError;\n }\n }\n }\n } catch (err) {\n const onError = await this.runErrorHooks(hooks?.onError, err, req, {\n action,\n resource,\n rule,\n });\n if (onError.skipped) {\n const after = await this.runAfterHooks(hooks?.after, req, {\n action,\n resource,\n rule,\n });\n return after.error ? next(after.error) : next();\n }\n return next(onError.error);\n }\n }\n\n const after = await this.runAfterHooks(hooks?.after, req, {\n action,\n resource,\n rule,\n });\n if (after.error) return next(after.error);\n\n next();\n }\n );\n }\n\n /**\n * Handles authentication control by checking the `authenticationControl` configuration in the `authConfigs`.\n *\n * @param {ControllerActions} action - The action being performed (e.g., create, update, delete, view).\n * @param {AuthenticationControlConfig} authenticationControl - The authentication configuration object.\n * @returns {ArkosRequestHandler} The middleware function that checks if authentication is required.\n *\n * @deprecated Will be removed on v2.0, use AuthService.authenticate instead\n */\n handleAuthenticationControl(\n action: AccessAction,\n authenticationControl?: AuthenticationControlConfig | undefined\n ): ArkosRequestHandler {\n if (authenticationControl && typeof authenticationControl === \"object\") {\n if (authenticationControl[action] === false) return callNext;\n else if (authenticationControl[action] === true) return this.authenticate;\n } else return this.authenticate;\n\n return this.authenticate;\n }\n\n /**\n * Creates a permission checker function for a specific action and resource.\n *\n * PS: This method should be called during application initialization to build permission validators.\n *\n * @see {@link https://www.arkosjs.com/docs/advanced-guide/fine-grained-access-control}\n *\n * @param action - The action to check permission for (e.g., 'View', 'Create', 'Delete')\n * @param resource - The resource being accessed, must be in kebabCase (e.g., 'user', 'cart-item', 'order')\n * @param accessControl - Access control rules (required for static authentication mode), and it is automatically loaded for known modules such as all prisma models, auth and file-upload.\n * @returns A function that takes a user object and returns a boolean indicating permission status\n *\n * @example\n * ```typescript\n * const hasViewProductPermission = await authService.permission('View', 'product');\n *\n * // Later in handler:\n * const canAccess = await hasViewProductPermission(user);\n * if (canAccess) {\n * // User has permission\n * }\n * ```\n */\n permission(\n action: string,\n resource: string,\n accessControl?: AccessControlConfig\n ) {\n // Check if called during request handling (deep call stack indicates handler execution)\n const stack = new Error().stack;\n\n if (stack?.includes(\"node_modules/express/lib/router/index.js\"))\n throw new Error(\n \"authService.permission() should be called during application initialization level.\"\n );\n\n authActionService.add(action, resource, accessControl);\n\n return async (user: User | undefined): Promise<boolean> => {\n // getArkosConfig must not be called the same time as arkos.init()\n const configs = getArkosConfig();\n\n if (!isUsingAuthentication())\n throw Error(\n \"Validation Error: Trying to use authService.permission without setting up authentication.\"\n );\n\n if (!isAuthenticationEnabled()) return false;\n if (!user) throw loginRequiredError;\n if (user?.isSuperUser) return true;\n\n if (configs?.authentication?.mode === \"dynamic\") {\n return await this.checkDynamicAccessControl(user?.id, action, resource);\n } else if (configs?.authentication?.mode === \"static\") {\n return (\n !!accessControl &&\n this.checkStaticAccessControl(user as any, action, accessControl)\n );\n }\n return false;\n };\n }\n}\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nconst authService = new AuthService();\n\nexport default authService;\n"]}
|
|
1
|
+
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../../../src/modules/auth/auth.service.ts"],"names":[],"mappings":"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","sourcesContent":["import jwt, { SignOptions } from \"jsonwebtoken\";\nimport bcrypt from \"bcryptjs\";\nimport { User } from \"../../types\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { callNext } from \"../base/base.middlewares\";\nimport arkosEnv from \"../../utils/arkos-env\";\nimport { getPrismaInstance } from \"../../utils/helpers/prisma.helpers\";\nimport {\n ArkosRequest,\n ArkosResponse,\n ArkosNextFunction,\n ArkosRequestHandler,\n} from \"../../types\";\nimport {\n AuthJwtPayload,\n AccessAction,\n AccessControlConfig,\n AuthenticationControlConfig,\n AccessControlRules,\n DetailedAccessControlRule,\n} from \"../../types/auth\";\nimport { MsDuration, toMs } from \"./utils/helpers/auth.controller.helpers\";\nimport {\n invaliAuthTokenError,\n loginRequiredError,\n} from \"./utils/auth-error-objects\";\nimport authActionService from \"./utils/services/auth-action.service\";\nimport {\n getArkosConfig,\n isAuthenticationEnabled,\n isUsingAuthentication,\n} from \"../../utils/helpers/arkos-config.helpers\";\nimport { CookieOptions } from \"express\";\nimport { getUserFileExtension } from \"../../utils/helpers/fs.helpers\";\nimport { authenticationDocsLinks } from \"./utils/docs-links\";\nimport authHookManager from \"./utils/auth-hooks-manager\";\nimport { ArkosSocket } from \"../../components/arkos-gateway/types\";\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nexport class AuthService {\n /**\n * Object containing a combination of actions per resource, tracked by each set of calls of `authService.handleAccessControl`, this can be accessed through the `authService` object or through the endpoint\n */\n actionsPerResource: Record<string, Set<string>> = {};\n\n /**\n * Signs a JWT token for the user.\n *\n * @param {number | string} id - The unique identifier of the user to generate the token for.\n * @param {string | number} [expiresIn] - The expiration time for the token. Defaults to environment variable `JWT_EXPIRES_IN`.\n * @param {string} [secret] - The secret key used to sign the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {string} The signed JWT token.\n */\n signJwtToken(\n id: number | string,\n expiresIn?: MsDuration | number,\n secret?: string\n ): string {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.ARKOS_BUILD === \"true\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\n \"Missing JWT secret on production!\",\n 500,\n \"MissingJWTOnProduction\"\n );\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n expiresIn = (expiresIn ||\n configs?.jwt?.expiresIn ||\n process.env.JWT_EXPIRES_IN ||\n arkosEnv.JWT_EXPIRES_IN) as keyof SignOptions[\"expiresIn\"];\n\n return jwt.sign({ id }, secret, {\n expiresIn: expiresIn as MsDuration,\n });\n }\n\n /**\n * Retrieves cookie configuration options for JWT authentication.\n *\n * Merges configuration from multiple sources in order of precedence:\n * 1. Arkos configuration file\n * 2. Environment variables\n * 3. Request properties (for secure flag)\n * 4. Default fallback values\n *\n * @param req - ArkosRequest object used to determine if the connection is secure\n * @returns Cookie options object with expires, httpOnly, secure, and sameSite properties\n *\n * @example\n * ```typescript\n * const cookieOptions = authService.getJwtCookieOptions(req);\n * res.cookie('jwt', token, cookieOptions);\n * ```\n */\n getJwtCookieOptions(req: ArkosRequest) {\n const arkosConfig = getArkosConfig();\n const authConfigs = arkosConfig?.authentication;\n\n if (!req)\n throw new Error(\"Missing req object in order get jwt cookie options\");\n\n const sameSite =\n authConfigs?.jwt?.cookie?.sameSite ||\n (process.env.JWT_COOKIE_SAME_SITE as\n | \"none\"\n | \"lax\"\n | \"strict\"\n | undefined) ||\n \"lax\";\n\n return {\n expires: new Date(\n Date.now() +\n Number(\n toMs(\n authConfigs?.jwt?.expiresIn ||\n (process.env.JWT_EXPIRES_IN as MsDuration) ||\n (arkosEnv.JWT_EXPIRES_IN as MsDuration)\n )\n )\n ),\n httpOnly:\n authConfigs?.jwt?.cookie?.httpOnly ??\n (process.env.JWT_COOKIE_HTTP_ONLY !== undefined\n ? process.env.JWT_COOKIE_HTTP_ONLY === \"true\"\n : undefined) ??\n true,\n secure: (() => {\n if (authConfigs?.jwt?.cookie?.secure !== undefined)\n return authConfigs?.jwt?.cookie?.secure;\n else if (process.env.JWT_COOKIE_SECURE !== undefined)\n return process.env.JWT_COOKIE_SECURE === \"true\";\n else return req.secure || req.headers[\"x-forwarded-proto\"] === \"https\";\n })(),\n sameSite,\n domain: authConfigs?.jwt?.cookie?.domain || process.env.JWT_COOKIE_DOMAIN,\n ...arkosConfig?.authentication?.jwt?.cookie,\n } as CookieOptions;\n }\n\n /**\n * Is used by default internally by Arkos under `ArkosPrismaService` class to check if the password is already hashed.\n *\n * This was just added to prevent unwanted errors when someone just forgets that the `ArkosPrismaService` class will automatically hash the password field using `authService.hashPassword` by default.\n *\n * So now before `ArkosPrismaService` hashes it will test it.\n *\n *\n * @param password The password to be tested if is hashed\n * @returns\n */\n isPasswordHashed(password: string) {\n return !Number.isNaN(bcrypt.getRounds(password) * 1);\n }\n\n /**\n * Compares a candidate password with the stored user password to check if they match.\n *\n * @param {string} candidatePassword - The password provided by the user during login.\n * @param {string} userPassword - The password stored in the database.\n * @returns {Promise<boolean>} Returns true if the passwords match, otherwise false.\n */\n async isCorrectPassword(\n candidatePassword: string,\n userPassword: string\n ): Promise<boolean> {\n return await bcrypt.compare(candidatePassword, userPassword);\n }\n\n /**\n * Hashes a plain text password using bcrypt.\n *\n * @param {string} password - The password to be hashed.\n * @returns {Promise<string>} Returns the hashed password.\n */\n async hashPassword(password: string): Promise<string> {\n return await bcrypt.hash(password, 12);\n }\n\n /**\n * Checks if a password is strong, requiring uppercase, lowercase, and numeric characters as the default.\n *\n * **NB**: You must pay attention when using custom validation with zod or class-validator, try to use the same regex always.\n *\n * **Note**: You can define it when calling arkos.init()\n * ```ts\n * arkos.init({\n * authentication: {\n * passwordValidation:{ regex: /your-desired-regex/, message: 'password must contain...'}\n * }\n * })\n * ```\n *\n * @param {string} password - The password to check.\n * @returns {boolean} Returns true if the password meets the strength criteria, otherwise false.\n */\n public isPasswordStrong(password: string): boolean {\n const initAuthConfigs = getArkosConfig()?.authentication;\n\n const strongPasswordRegex =\n initAuthConfigs?.passwordValidation?.regex ||\n /^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).+$/;\n return strongPasswordRegex.test(password);\n }\n\n /**\n * Checks if a user has changed their password after the JWT was issued.\n *\n * @param {User} user - The user object containing the passwordChangedAt field.\n * @param {number} JWTTimestamp - The timestamp when the JWT was issued.\n * @returns {boolean} Returns true if the user changed their password after the JWT was issued, otherwise false.\n */\n userChangedPasswordAfter(user: User, JWTTimestamp: number): boolean {\n if (user.passwordChangedAt) {\n const convertedTimestamp = parseInt(\n String(new Date(user.passwordChangedAt).getTime() / 1000),\n 10\n );\n\n return JWTTimestamp < convertedTimestamp;\n }\n return false;\n }\n\n /**\n * Verifies the authenticity of a JWT token.\n *\n * @param {string} token - The JWT token to verify.\n * @param {string} [secret] - The secret key used to verify the token. Defaults to environment variable `JWT_SECRET`.\n * @returns {Promise<AuthJwtPayload>} Returns the decoded JWT payload if the token is valid.\n * @throws {Error} Throws an error if the token is invalid or expired.\n */\n async verifyJwtToken(\n token: string,\n secret?: string\n ): Promise<AuthJwtPayload> {\n const { authentication: configs } = getArkosConfig();\n\n if (\n process.env.ARKOS_BUILD === \"true\" &&\n !process.env.JWT_SECRET &&\n !configs?.jwt?.secret\n )\n throw new AppError(\n \"Missing JWT secret in production\",\n 500,\n \"MissingJWTSecretInProduction\"\n );\n\n secret =\n secret ||\n configs?.jwt?.secret ||\n process.env.JWT_SECRET ||\n arkosEnv.JWT_SECRET;\n\n try {\n const decoded = (await new Promise((resolve, reject) => {\n jwt.verify(token, secret, (err, decoded) => {\n if (err) reject(err);\n else resolve(decoded as AuthJwtPayload);\n });\n })) as AuthJwtPayload;\n\n if (!decoded?.id) throw invaliAuthTokenError;\n\n return decoded;\n } catch (err) {\n throw invaliAuthTokenError;\n }\n }\n\n private isWildcardAccess(config: AccessControlConfig): config is \"*\" {\n return config === \"*\";\n }\n\n private isRoleList(config: AccessControlConfig): config is string[] {\n return Array.isArray(config);\n }\n\n private isAccessRules(\n config: AccessControlConfig\n ): config is Partial<AccessControlRules> {\n return (\n typeof config === \"object\" && config !== null && !Array.isArray(config)\n );\n }\n\n private normalizeRuleToRoles(\n rule: string[] | DetailedAccessControlRule | \"*\" | undefined\n ): string[] {\n if (!rule) return [];\n if (rule === \"*\") return [\"*\"];\n if (Array.isArray(rule)) return rule;\n return rule.roles === \"*\" ? [\"*\"] : (rule.roles ?? []);\n }\n\n private resolveAuthorizedRoles(\n action: AccessAction,\n accessControl: AccessControlConfig\n ): string[] {\n if (this.isWildcardAccess(accessControl)) return [\"*\"];\n if (this.isRoleList(accessControl)) return accessControl;\n if (this.isAccessRules(accessControl))\n return this.normalizeRuleToRoles(accessControl[action]);\n return [];\n }\n\n /**\n * Checks if a user has permission for a specific action using static access control rules.\n * Validates user roles against predefined access control configuration.\n *\n * @param user - The user object containing role or roles field\n * @param action - The action being performed\n * @param accessControl - Access control configuration (array of roles or object with action-role mappings)\n * @returns True if user has permission, false otherwise\n * @throws Error if user doesn't have role/roles field\n */\n checkStaticAccessControl(\n user: User,\n action: string,\n accessControl: AccessControlConfig\n ) {\n if (!user?.role && !user.roles)\n throw Error(\n \"Validation Error: In order to use static authentication user needs at least role field or roles for multiple roles.\"\n );\n\n let authorizedRoles = this.resolveAuthorizedRoles(action, accessControl);\n\n const userRoles = Array.isArray(user?.roles) ? user.roles : [user.role];\n\n return (\n authorizedRoles?.[0] === \"*\" ||\n !!userRoles.some((role: string) => authorizedRoles.includes(role))\n );\n }\n\n /**\n * Checks if a user has permission for a specific action and resource using dynamic access control.\n * Queries the database to verify user's role permissions.\n *\n * @param userId - The unique identifier of the user\n * @param action - The action being performed\n * @param resource - The resource being accessed\n * @returns Promise resolving to true if user has permission, false otherwise\n */\n async checkDynamicAccessControl(\n userId: string,\n action: string,\n resource: string\n ) {\n const prisma = getPrismaInstance();\n\n const [userPermission, hasRolePermission] = await Promise.all([\n prisma.userPermission\n ? prisma.userPermission.findFirst({\n where: { userId, permission: { resource, action } },\n select: { effect: true },\n })\n : Promise.resolve(null),\n\n prisma.userRole.findFirst({\n where: {\n userId,\n role: {\n permissions: {\n some: { resource, action },\n },\n },\n },\n select: { id: true },\n }),\n ]);\n\n if (userPermission) return userPermission.effect === \"Allow\";\n return !!hasRolePermission;\n }\n\n /**\n * Middleware function to handle access control based on user roles and permissions.\n *\n * @param {AccessAction} action - The action being performed (e.g., create, update, delete, view).\n * @param {string} resource - The resource name that the action is being performed on (e.g., \"User\", \"Post\").\n * @param {AccessControlConfig} accessControl - The access control configuration.\n * @returns {ArkosRequestHandler} The middleware function that checks if the user has permission to perform the action.\n *\n * @deprecated Will be removed on v2.0, use AuthService.authorize instead\n */\n handleAccessControl(\n action: AccessAction,\n resource: string,\n accessControl?: AccessControlConfig\n ): ArkosRequestHandler {\n const authAction = authActionService.add(action, resource, accessControl);\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n if (req.user) {\n const user = req.user as User;\n const configs = getArkosConfig();\n\n if (user.isSuperUser) {\n next();\n return;\n }\n\n const notEnoughPermissionsError = new AppError(\n authAction.errorMessage,\n 403,\n \"NotEnoughPermissions\"\n );\n\n if (configs?.authentication?.mode === \"dynamic\") {\n const hasPermission = await this.checkDynamicAccessControl(\n user.id,\n action,\n resource\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n } else if (configs?.authentication?.mode === \"static\") {\n if (!accessControl) return next(notEnoughPermissionsError);\n\n const hasPermission = this.checkStaticAccessControl(\n user,\n action,\n accessControl\n );\n\n if (!hasPermission) return next(notEnoughPermissionsError);\n }\n }\n\n next();\n }\n );\n }\n\n private extractRequestToken(\n req: ArkosRequest,\n cookie: \"arkos_access_token\" = \"arkos_access_token\"\n ) {\n let token: string | null = null;\n\n if (\n req?.headers?.authorization &&\n req?.headers?.authorization.startsWith(\"Bearer\") &&\n req?.headers?.authorization.split?.(\" \")?.[1]\n )\n token = req?.headers?.authorization.split(\" \")[1];\n\n if (\n !token &&\n req?.cookies?.arkos_access_token !== \"no-token\" &&\n req.cookies\n )\n token = req?.cookies?.[cookie];\n\n return token;\n }\n\n private extractSocketToken(socket: ArkosSocket, key: \"token\" = \"token\") {\n return (\n socket.handshake.auth?.[key] ||\n socket.handshake.headers?.authorization?.replace(\"Bearer \", \"\")\n );\n }\n\n async validateDecodedUser(\n decoded: AuthJwtPayload,\n action: \"logout\" | \"default\" = \"default\"\n ): Promise<User> {\n const prisma = getPrismaInstance();\n const user = await (prisma as any).user.findUnique({\n where: { id: decoded.id },\n });\n\n if (!user)\n throw new AppError(\n \"The user belonging to this token no longer exists\",\n 401,\n \"UserNoLongerExists\"\n );\n\n if (\n action !== \"logout\" &&\n this.userChangedPasswordAfter(user, decoded.iat!)\n )\n throw new AppError(\n \"User recently changed password! Please log in again.\",\n 401,\n \"PasswordChanged\"\n );\n\n return user;\n }\n\n /**\n * Processes the cookies or authoriation token and returns the user.\n *\n * @param ctx | socket\n * @returns {Promise<User | null>} - if authentication is turned off in arkosConfig it returns null\n * @throws {AppError} Throws an error if the token is invalid or the user is not logged in.\n */\n async getAuthenticatedUser(\n ctx: ArkosRequest | ArkosSocket,\n action: \"logout\" | \"default\" = \"default\"\n ): Promise<User | null> {\n if (!isAuthenticationEnabled())\n throw Error(\n `Trying to call authService.getAuthenticatedUser without setting up authentication in arkos.config.${getUserFileExtension()}, see ${authenticationDocsLinks.setup}`\n );\n\n let token: string | null = null;\n\n if (\"headers\" in ctx) token = this.extractRequestToken(ctx);\n else if (\"join\" in ctx) token = this.extractSocketToken(ctx);\n\n if (!token) return null;\n\n const decoded = await this.verifyJwtToken(token);\n ctx.accessToken = token;\n\n return this.validateDecodedUser(decoded, action);\n }\n\n /**\n * Middleware to authenticate the request by extracting and verifying the JWT token and setting `req.user`.\n *\n * Runs `authentication.hooks.authenticate` before/after the authentication logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — extracts and verifies the JWT token, sets `req.user`.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if core logic throws — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * On custom routes, hooks defined in `arkosConfig` still apply since they are baked into this method.\n *\n * @example\n * ```ts\n * // custom route - hooks still run\n * router.get(\"/custom\", authService.authenticate, handler);\n * ```\n *\n * @example\n * ```ts\n * // skip built-in auth from a before hook\n * before: (ctx) => {\n * ctx.req.user = myCustomAuth(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks}\n */\n authenticate = catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n await authHookManager.runAuthenticate(\n { context: req, done: next },\n async (req): Promise<any> => {\n if (!isAuthenticationEnabled()) return null;\n const user = (await this.getAuthenticatedUser(\n req,\n req.path.includes(\"logout\") ? \"logout\" : \"default\"\n )) as User;\n if (!user) throw loginRequiredError;\n return user;\n }\n );\n }\n );\n\n /**\n * Middleware to authorize the authenticated user for a given action on a resource.\n *\n * Runs `authentication.hooks.authorize` before/after the authorization logic.\n *\n * Hook execution flow:\n * - `before` hooks run first — call `ctx.skip()` to bypass core logic and jump to `after` hooks,\n * call `ctx.next()` to stop the chain early, or return without calling anything to continue.\n * - Core logic runs — checks user role/permissions against the access control rules.\n * - `after` hooks run — call `ctx.next(err)` to abort or return without calling anything to continue.\n * - `onError` hooks run if authorization fails — call `ctx.skip()` to suppress the error and jump to\n * `after` hooks, or call `ctx.next(err)` to forward it to the global error handler.\n *\n * @param resource - The resource being accessed, in kebabCase (e.g. `\"product\"`, `\"cart-item\"`)\n * @param action - The action being performed (e.g. `\"View\"`, `\"Create\"`, `\"Delete\"`)\n * @param rule - Access control rules for this action. Accepts a role list, a wildcard, or a `DetailedAccessControlRule`.\n *\n * @example\n * ```ts\n * router.delete(\"/products/:id\",\n * authService.authenticate,\n * authService.authorize(\"product\", \"Delete\", [\"admin\"]),\n * handler\n * );\n * ```\n *\n * @example\n * ```ts\n * // skip built-in authorization from a before hook\n * before: (ctx) => {\n * ctx.req.user.role = myCustomRoleResolver(ctx.req);\n * ctx.skip();\n * }\n * ```\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks#authorize}\n * @since v1.6.0-beta\n */\n authorize(\n action: AccessAction,\n resource: string,\n rule?: string[] | DetailedAccessControlRule | \"*\"\n ): ArkosRequestHandler {\n const authAction = authActionService.add(action, resource, {\n [action]: rule,\n });\n\n return catchAsync(\n async (req: ArkosRequest, _: ArkosResponse, next: ArkosNextFunction) => {\n await authHookManager.runAuthorize(\n { context: req, done: next },\n authAction\n );\n }\n );\n }\n\n /**\n * Handles authentication control by checking the `authenticationControl` configuration in the `authConfigs`.\n *\n * @param {ControllerActions} action - The action being performed (e.g., create, update, delete, view).\n * @param {AuthenticationControlConfig} authenticationControl - The authentication configuration object.\n * @returns {ArkosRequestHandler} The middleware function that checks if authentication is required.\n *\n * @deprecated Will be removed on v2.0, use AuthService.authenticate instead\n */\n handleAuthenticationControl(\n action: AccessAction,\n authenticationControl?: AuthenticationControlConfig | undefined\n ): ArkosRequestHandler {\n if (authenticationControl && typeof authenticationControl === \"object\") {\n if (authenticationControl[action] === false) return callNext;\n else if (authenticationControl[action] === true) return this.authenticate;\n } else return this.authenticate;\n\n return this.authenticate;\n }\n\n /**\n * Creates a permission checker function for a specific action and resource.\n *\n * PS: This method should be called during application initialization to build permission validators.\n *\n * @see {@link https://www.arkosjs.com/docs/advanced-guide/fine-grained-access-control}\n *\n * @param action - The action to check permission for (e.g., 'View', 'Create', 'Delete')\n * @param resource - The resource being accessed, must be in kebabCase (e.g., 'user', 'cart-item', 'order')\n * @param accessControl - Access control rules (required for static authentication mode), and it is automatically loaded for known modules such as all prisma models, auth and file-upload.\n * @returns A function that takes a user object and returns a boolean indicating permission status\n *\n * @example\n * ```typescript\n * const hasViewProductPermission = await authService.permission('View', 'product');\n *\n * // Later in handler:\n * const canAccess = await hasViewProductPermission(user);\n * if (canAccess) {\n * // User has permission\n * }\n * ```\n */\n permission(\n action: string,\n resource: string,\n accessControl?: AccessControlConfig\n ) {\n // Check if called during request handling (deep call stack indicates handler execution)\n const stack = new Error().stack;\n\n if (stack?.includes(\"node_modules/express/lib/router/index.js\"))\n throw new Error(\n \"authService.permission() should be called during application initialization level.\"\n );\n\n authActionService.add(action, resource, accessControl);\n\n return async (user: User | undefined): Promise<boolean> => {\n // getArkosConfig must not be called the same time as arkos.init()\n const configs = getArkosConfig();\n\n if (!isUsingAuthentication())\n throw Error(\n \"Validation Error: Trying to use authService.permission without setting up authentication.\"\n );\n\n if (!isAuthenticationEnabled()) return false;\n if (!user) throw loginRequiredError;\n if (user?.isSuperUser) return true;\n\n if (configs?.authentication?.mode === \"dynamic\") {\n return await this.checkDynamicAccessControl(user?.id, action, resource);\n } else if (configs?.authentication?.mode === \"static\") {\n return (\n !!accessControl &&\n this.checkStaticAccessControl(user as any, action, accessControl)\n );\n }\n return false;\n };\n }\n}\n\n/**\n * Handles various authentication-related tasks such as JWT signing, password hashing, and verifying user credentials.\n */\nconst authService = new AuthService();\n\nexport default authService;\n"]}
|
|
@@ -5,6 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.invaliAuthTokenError = exports.loginRequiredError = void 0;
|
|
7
7
|
const app_error_1 = __importDefault(require("../../error-handler/utils/app-error.js"));
|
|
8
|
-
exports.loginRequiredError = new app_error_1.default("You are not logged in! please log in to get access", 401,
|
|
9
|
-
exports.invaliAuthTokenError = new app_error_1.default("Your auth token is invalid, please login again.", 401,
|
|
8
|
+
exports.loginRequiredError = new app_error_1.default("You are not logged in! please log in to get access", 401, "LoginRequired");
|
|
9
|
+
exports.invaliAuthTokenError = new app_error_1.default("Your auth token is invalid, please login again.", 401, "InvalidAuthToken");
|
|
10
10
|
//# sourceMappingURL=auth-error-objects.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-error-objects.js","sourceRoot":"","sources":["../../../../../src/modules/auth/utils/auth-error-objects.ts"],"names":[],"mappings":";;;;;;AAAA,oFAA2D;AAE9C,QAAA,kBAAkB,GAAG,IAAI,mBAAQ,CAC5C,oDAAoD,EACpD,GAAG,EACH,
|
|
1
|
+
{"version":3,"file":"auth-error-objects.js","sourceRoot":"","sources":["../../../../../src/modules/auth/utils/auth-error-objects.ts"],"names":[],"mappings":";;;;;;AAAA,oFAA2D;AAE9C,QAAA,kBAAkB,GAAG,IAAI,mBAAQ,CAC5C,oDAAoD,EACpD,GAAG,EACH,eAAe,CAChB,CAAC;AAEW,QAAA,oBAAoB,GAAG,IAAI,mBAAQ,CAC9C,iDAAiD,EACjD,GAAG,EACH,kBAAkB,CACnB,CAAC","sourcesContent":["import AppError from \"../../error-handler/utils/app-error\";\n\nexport const loginRequiredError = new AppError(\n \"You are not logged in! please log in to get access\",\n 401,\n \"LoginRequired\"\n);\n\nexport const invaliAuthTokenError = new AppError(\n \"Your auth token is invalid, please login again.\",\n 401,\n \"InvalidAuthToken\"\n);\n"]}
|