@techelusive/nest-auth 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/LICENSE +21 -0
- package/README.md +204 -2
- package/api/openapi.json +4399 -0
- package/api/techelusive-authentication.postman_collection.json +3178 -0
- package/dist/auth-options.d.ts +156 -0
- package/dist/auth-options.js +3 -0
- package/dist/auth-options.js.map +1 -0
- package/dist/auth-options.validation.d.ts +9 -0
- package/dist/auth-options.validation.js +74 -0
- package/dist/auth-options.validation.js.map +1 -0
- package/dist/auth.module.d.ts +38 -0
- package/dist/auth.module.js +173 -0
- package/dist/auth.module.js.map +1 -0
- package/dist/common/auth-error.d.ts +16 -0
- package/dist/common/auth-error.js +23 -0
- package/dist/common/auth-error.js.map +1 -0
- package/dist/common/auth-exception.filter.d.ts +24 -0
- package/dist/common/auth-exception.filter.js +66 -0
- package/dist/common/auth-exception.filter.js.map +1 -0
- package/dist/common/crypto/jwt.d.ts +89 -0
- package/dist/common/crypto/jwt.js +144 -0
- package/dist/common/crypto/jwt.js.map +1 -0
- package/dist/common/crypto/random-secrets.d.ts +78 -0
- package/dist/common/crypto/random-secrets.js +113 -0
- package/dist/common/crypto/random-secrets.js.map +1 -0
- package/dist/common/crypto/remote-public-keys.d.ts +49 -0
- package/dist/common/crypto/remote-public-keys.js +105 -0
- package/dist/common/crypto/remote-public-keys.js.map +1 -0
- package/dist/common/crypto/totp.d.ts +68 -0
- package/dist/common/crypto/totp.js +148 -0
- package/dist/common/crypto/totp.js.map +1 -0
- package/dist/common/encryption.service.d.ts +36 -0
- package/dist/common/encryption.service.js +111 -0
- package/dist/common/encryption.service.js.map +1 -0
- package/dist/common/identifiers.d.ts +48 -0
- package/dist/common/identifiers.js +89 -0
- package/dist/common/identifiers.js.map +1 -0
- package/dist/common/network-safety.d.ts +19 -0
- package/dist/common/network-safety.js +72 -0
- package/dist/common/network-safety.js.map +1 -0
- package/dist/common/rate-limiter.service.d.ts +63 -0
- package/dist/common/rate-limiter.service.js +158 -0
- package/dist/common/rate-limiter.service.js.map +1 -0
- package/dist/common/refresh-token-cookie.d.ts +78 -0
- package/dist/common/refresh-token-cookie.js +185 -0
- package/dist/common/refresh-token-cookie.js.map +1 -0
- package/dist/common/request-context.d.ts +14 -0
- package/dist/common/request-context.js +22 -0
- package/dist/common/request-context.js.map +1 -0
- package/dist/common/strict-validation.pipe.d.ts +8 -0
- package/dist/common/strict-validation.pipe.js +16 -0
- package/dist/common/strict-validation.pipe.js.map +1 -0
- package/dist/common/time.d.ts +15 -0
- package/dist/common/time.js +34 -0
- package/dist/common/time.js.map +1 -0
- package/dist/constants.d.ts +1326 -0
- package/dist/constants.js +1142 -0
- package/dist/constants.js.map +1 -0
- package/dist/database/create-auth-tables.migration.d.ts +26 -0
- package/dist/database/create-auth-tables.migration.js +291 -0
- package/dist/database/create-auth-tables.migration.js.map +1 -0
- package/dist/database/email-change-and-retention.migration.d.ts +25 -0
- package/dist/database/email-change-and-retention.migration.js +54 -0
- package/dist/database/email-change-and-retention.migration.js.map +1 -0
- package/dist/database/entities/api-key.entity.d.ts +17 -0
- package/dist/database/entities/api-key.entity.js +80 -0
- package/dist/database/entities/api-key.entity.js.map +1 -0
- package/dist/database/entities/audit-log.entity.d.ts +13 -0
- package/dist/database/entities/audit-log.entity.js +64 -0
- package/dist/database/entities/audit-log.entity.js.map +1 -0
- package/dist/database/entities/backup-code.entity.d.ts +9 -0
- package/dist/database/entities/backup-code.entity.js +52 -0
- package/dist/database/entities/backup-code.entity.js.map +1 -0
- package/dist/database/entities/index.d.ts +43 -0
- package/dist/database/entities/index.js +82 -0
- package/dist/database/entities/index.js.map +1 -0
- package/dist/database/entities/json-object.d.ts +12 -0
- package/dist/database/entities/json-object.js +3 -0
- package/dist/database/entities/json-object.js.map +1 -0
- package/dist/database/entities/link-token.entity.d.ts +15 -0
- package/dist/database/entities/link-token.entity.js +64 -0
- package/dist/database/entities/link-token.entity.js.map +1 -0
- package/dist/database/entities/one-time-code.entity.d.ts +16 -0
- package/dist/database/entities/one-time-code.entity.js +69 -0
- package/dist/database/entities/one-time-code.entity.js.map +1 -0
- package/dist/database/entities/organization-invitation.entity.d.ts +14 -0
- package/dist/database/entities/organization-invitation.entity.js +73 -0
- package/dist/database/entities/organization-invitation.entity.js.map +1 -0
- package/dist/database/entities/organization-member.entity.d.ts +9 -0
- package/dist/database/entities/organization-member.entity.js +48 -0
- package/dist/database/entities/organization-member.entity.js.map +1 -0
- package/dist/database/entities/organization.entity.d.ts +12 -0
- package/dist/database/entities/organization.entity.js +58 -0
- package/dist/database/entities/organization.entity.js.map +1 -0
- package/dist/database/entities/passkey.entity.d.ts +19 -0
- package/dist/database/entities/passkey.entity.js +78 -0
- package/dist/database/entities/passkey.entity.js.map +1 -0
- package/dist/database/entities/password.entity.d.ts +6 -0
- package/dist/database/entities/password.entity.js +36 -0
- package/dist/database/entities/password.entity.js.map +1 -0
- package/dist/database/entities/refresh-token.entity.d.ts +9 -0
- package/dist/database/entities/refresh-token.entity.js +53 -0
- package/dist/database/entities/refresh-token.entity.js.map +1 -0
- package/dist/database/entities/session.entity.d.ts +20 -0
- package/dist/database/entities/session.entity.js +87 -0
- package/dist/database/entities/session.entity.js.map +1 -0
- package/dist/database/entities/settings.entity.d.ts +7 -0
- package/dist/database/entities/settings.entity.js +41 -0
- package/dist/database/entities/settings.entity.js.map +1 -0
- package/dist/database/entities/sign-in-challenge.entity.d.ts +23 -0
- package/dist/database/entities/sign-in-challenge.entity.js +80 -0
- package/dist/database/entities/sign-in-challenge.entity.js.map +1 -0
- package/dist/database/entities/signing-key.entity.d.ts +11 -0
- package/dist/database/entities/signing-key.entity.js +54 -0
- package/dist/database/entities/signing-key.entity.js.map +1 -0
- package/dist/database/entities/social-account.entity.d.ts +13 -0
- package/dist/database/entities/social-account.entity.js +54 -0
- package/dist/database/entities/social-account.entity.js.map +1 -0
- package/dist/database/entities/two-factor-secret.entity.d.ts +10 -0
- package/dist/database/entities/two-factor-secret.entity.js +48 -0
- package/dist/database/entities/two-factor-secret.entity.js.map +1 -0
- package/dist/database/entities/user.entity.d.ts +34 -0
- package/dist/database/entities/user.entity.js +129 -0
- package/dist/database/entities/user.entity.js.map +1 -0
- package/dist/database/entities/webhook-delivery.entity.d.ts +17 -0
- package/dist/database/entities/webhook-delivery.entity.js +79 -0
- package/dist/database/entities/webhook-delivery.entity.js.map +1 -0
- package/dist/database/entities/webhook.entity.d.ts +12 -0
- package/dist/database/entities/webhook.entity.js +58 -0
- package/dist/database/entities/webhook.entity.js.map +1 -0
- package/dist/database/typeorm-row.d.ts +21 -0
- package/dist/database/typeorm-row.js +29 -0
- package/dist/database/typeorm-row.js.map +1 -0
- package/dist/features/account/account.controller.d.ts +259 -0
- package/dist/features/account/account.controller.js +372 -0
- package/dist/features/account/account.controller.js.map +1 -0
- package/dist/features/account/account.dto.d.ts +16 -0
- package/dist/features/account/account.dto.js +61 -0
- package/dist/features/account/account.dto.js.map +1 -0
- package/dist/features/account/data-export.service.d.ts +85 -0
- package/dist/features/account/data-export.service.js +125 -0
- package/dist/features/account/data-export.service.js.map +1 -0
- package/dist/features/account/health.service.d.ts +30 -0
- package/dist/features/account/health.service.js +59 -0
- package/dist/features/account/health.service.js.map +1 -0
- package/dist/features/admin/admin.controller.d.ts +382 -0
- package/dist/features/admin/admin.controller.js +623 -0
- package/dist/features/admin/admin.controller.js.map +1 -0
- package/dist/features/admin/admin.dto.d.ts +61 -0
- package/dist/features/admin/admin.dto.js +253 -0
- package/dist/features/admin/admin.dto.js.map +1 -0
- package/dist/features/admin/admin.service.d.ts +142 -0
- package/dist/features/admin/admin.service.js +227 -0
- package/dist/features/admin/admin.service.js.map +1 -0
- package/dist/features/api-keys/api-keys.service.d.ts +67 -0
- package/dist/features/api-keys/api-keys.service.js +144 -0
- package/dist/features/api-keys/api-keys.service.js.map +1 -0
- package/dist/features/email-change/email-change.controller.d.ts +38 -0
- package/dist/features/email-change/email-change.controller.js +85 -0
- package/dist/features/email-change/email-change.controller.js.map +1 -0
- package/dist/features/email-change/email-change.dto.d.ts +10 -0
- package/dist/features/email-change/email-change.dto.js +43 -0
- package/dist/features/email-change/email-change.dto.js.map +1 -0
- package/dist/features/email-change/email-change.service.d.ts +74 -0
- package/dist/features/email-change/email-change.service.js +179 -0
- package/dist/features/email-change/email-change.service.js.map +1 -0
- package/dist/features/email-links/email-verification.service.d.ts +46 -0
- package/dist/features/email-links/email-verification.service.js +94 -0
- package/dist/features/email-links/email-verification.service.js.map +1 -0
- package/dist/features/email-links/link-tokens.service.d.ts +44 -0
- package/dist/features/email-links/link-tokens.service.js +122 -0
- package/dist/features/email-links/link-tokens.service.js.map +1 -0
- package/dist/features/events/auth-events.service.d.ts +52 -0
- package/dist/features/events/auth-events.service.js +117 -0
- package/dist/features/events/auth-events.service.js.map +1 -0
- package/dist/features/maintenance/data-retention.service.d.ts +60 -0
- package/dist/features/maintenance/data-retention.service.js +182 -0
- package/dist/features/maintenance/data-retention.service.js.map +1 -0
- package/dist/features/notifications/notifications.service.d.ts +40 -0
- package/dist/features/notifications/notifications.service.js +94 -0
- package/dist/features/notifications/notifications.service.js.map +1 -0
- package/dist/features/one-time-codes/one-time-codes.service.d.ts +40 -0
- package/dist/features/one-time-codes/one-time-codes.service.js +102 -0
- package/dist/features/one-time-codes/one-time-codes.service.js.map +1 -0
- package/dist/features/organizations/organizations.controller.d.ts +220 -0
- package/dist/features/organizations/organizations.controller.js +337 -0
- package/dist/features/organizations/organizations.controller.js.map +1 -0
- package/dist/features/organizations/organizations.dto.d.ts +31 -0
- package/dist/features/organizations/organizations.dto.js +100 -0
- package/dist/features/organizations/organizations.dto.js.map +1 -0
- package/dist/features/organizations/organizations.service.d.ts +274 -0
- package/dist/features/organizations/organizations.service.js +481 -0
- package/dist/features/organizations/organizations.service.js.map +1 -0
- package/dist/features/passkeys/passkeys.controller.d.ts +92 -0
- package/dist/features/passkeys/passkeys.controller.js +183 -0
- package/dist/features/passkeys/passkeys.controller.js.map +1 -0
- package/dist/features/passkeys/passkeys.dto.d.ts +13 -0
- package/dist/features/passkeys/passkeys.dto.js +50 -0
- package/dist/features/passkeys/passkeys.dto.js.map +1 -0
- package/dist/features/passkeys/passkeys.service.d.ts +159 -0
- package/dist/features/passkeys/passkeys.service.js +350 -0
- package/dist/features/passkeys/passkeys.service.js.map +1 -0
- package/dist/features/passwordless/passwordless-auth.service.d.ts +152 -0
- package/dist/features/passwordless/passwordless-auth.service.js +304 -0
- package/dist/features/passwordless/passwordless-auth.service.js.map +1 -0
- package/dist/features/passwordless/passwordless.controller.d.ts +75 -0
- package/dist/features/passwordless/passwordless.controller.js +163 -0
- package/dist/features/passwordless/passwordless.controller.js.map +1 -0
- package/dist/features/passwordless/passwordless.dto.d.ts +29 -0
- package/dist/features/passwordless/passwordless.dto.js +101 -0
- package/dist/features/passwordless/passwordless.dto.js.map +1 -0
- package/dist/features/passwords/password-auth.service.d.ts +154 -0
- package/dist/features/passwords/password-auth.service.js +317 -0
- package/dist/features/passwords/password-auth.service.js.map +1 -0
- package/dist/features/passwords/password-policy.service.d.ts +63 -0
- package/dist/features/passwords/password-policy.service.js +175 -0
- package/dist/features/passwords/password-policy.service.js.map +1 -0
- package/dist/features/passwords/password.controller.d.ts +95 -0
- package/dist/features/passwords/password.controller.js +193 -0
- package/dist/features/passwords/password.controller.js.map +1 -0
- package/dist/features/passwords/password.dto.d.ts +36 -0
- package/dist/features/passwords/password.dto.js +140 -0
- package/dist/features/passwords/password.dto.js.map +1 -0
- package/dist/features/sessions/session.service.d.ts +132 -0
- package/dist/features/sessions/session.service.js +308 -0
- package/dist/features/sessions/session.service.js.map +1 -0
- package/dist/features/sessions/session.types.d.ts +34 -0
- package/dist/features/sessions/session.types.js +3 -0
- package/dist/features/sessions/session.types.js.map +1 -0
- package/dist/features/settings/settings.defaults.d.ts +2 -0
- package/dist/features/settings/settings.defaults.js +7 -0
- package/dist/features/settings/settings.defaults.js.map +1 -0
- package/dist/features/settings/settings.service.d.ts +44 -0
- package/dist/features/settings/settings.service.js +112 -0
- package/dist/features/settings/settings.service.js.map +1 -0
- package/dist/features/settings/settings.types.d.ts +133 -0
- package/dist/features/settings/settings.types.js +3 -0
- package/dist/features/settings/settings.types.js.map +1 -0
- package/dist/features/settings/settings.validation.d.ts +33 -0
- package/dist/features/settings/settings.validation.js +614 -0
- package/dist/features/settings/settings.validation.js.map +1 -0
- package/dist/features/sign-in/sign-in-challenges.service.d.ts +54 -0
- package/dist/features/sign-in/sign-in-challenges.service.js +104 -0
- package/dist/features/sign-in/sign-in-challenges.service.js.map +1 -0
- package/dist/features/sign-in/sign-in.service.d.ts +127 -0
- package/dist/features/sign-in/sign-in.service.js +248 -0
- package/dist/features/sign-in/sign-in.service.js.map +1 -0
- package/dist/features/sign-in/sign-in.types.d.ts +22 -0
- package/dist/features/sign-in/sign-in.types.js +3 -0
- package/dist/features/sign-in/sign-in.types.js.map +1 -0
- package/dist/features/signing-keys/jwks.controller.d.ts +17 -0
- package/dist/features/signing-keys/jwks.controller.js +51 -0
- package/dist/features/signing-keys/jwks.controller.js.map +1 -0
- package/dist/features/signing-keys/signing-keys.service.d.ts +67 -0
- package/dist/features/signing-keys/signing-keys.service.js +142 -0
- package/dist/features/signing-keys/signing-keys.service.js.map +1 -0
- package/dist/features/social/social-auth.service.d.ts +100 -0
- package/dist/features/social/social-auth.service.js +232 -0
- package/dist/features/social/social-auth.service.js.map +1 -0
- package/dist/features/social/social-providers.service.d.ts +97 -0
- package/dist/features/social/social-providers.service.js +214 -0
- package/dist/features/social/social-providers.service.js.map +1 -0
- package/dist/features/social/social.controller.d.ts +54 -0
- package/dist/features/social/social.controller.js +124 -0
- package/dist/features/social/social.controller.js.map +1 -0
- package/dist/features/social/social.dto.d.ts +11 -0
- package/dist/features/social/social.dto.js +38 -0
- package/dist/features/social/social.dto.js.map +1 -0
- package/dist/features/two-factor/two-factor.controller.d.ts +84 -0
- package/dist/features/two-factor/two-factor.controller.js +174 -0
- package/dist/features/two-factor/two-factor.controller.js.map +1 -0
- package/dist/features/two-factor/two-factor.dto.d.ts +10 -0
- package/dist/features/two-factor/two-factor.dto.js +37 -0
- package/dist/features/two-factor/two-factor.dto.js.map +1 -0
- package/dist/features/two-factor/two-factor.service.d.ts +171 -0
- package/dist/features/two-factor/two-factor.service.js +348 -0
- package/dist/features/two-factor/two-factor.service.js.map +1 -0
- package/dist/features/users/sign-in-methods.service.d.ts +40 -0
- package/dist/features/users/sign-in-methods.service.js +81 -0
- package/dist/features/users/sign-in-methods.service.js.map +1 -0
- package/dist/features/users/sign-up-rules.d.ts +12 -0
- package/dist/features/users/sign-up-rules.js +29 -0
- package/dist/features/users/sign-up-rules.js.map +1 -0
- package/dist/features/users/users.service.d.ts +246 -0
- package/dist/features/users/users.service.js +509 -0
- package/dist/features/users/users.service.js.map +1 -0
- package/dist/features/users/users.types.d.ts +24 -0
- package/dist/features/users/users.types.js +3 -0
- package/dist/features/users/users.types.js.map +1 -0
- package/dist/features/webhooks/webhook-delivery.worker.d.ts +55 -0
- package/dist/features/webhooks/webhook-delivery.worker.js +175 -0
- package/dist/features/webhooks/webhook-delivery.worker.js.map +1 -0
- package/dist/features/webhooks/webhook-signature.d.ts +28 -0
- package/dist/features/webhooks/webhook-signature.js +85 -0
- package/dist/features/webhooks/webhook-signature.js.map +1 -0
- package/dist/features/webhooks/webhooks.service.d.ts +144 -0
- package/dist/features/webhooks/webhooks.service.js +238 -0
- package/dist/features/webhooks/webhooks.service.js.map +1 -0
- package/dist/guards/auth.decorators.d.ts +65 -0
- package/dist/guards/auth.decorators.js +68 -0
- package/dist/guards/auth.decorators.js.map +1 -0
- package/dist/guards/auth.guard.d.ts +47 -0
- package/dist/guards/auth.guard.js +132 -0
- package/dist/guards/auth.guard.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/console-email-sender.d.ts +15 -0
- package/dist/integrations/console-email-sender.js +26 -0
- package/dist/integrations/console-email-sender.js.map +1 -0
- package/dist/integrations/msg91-sms-sender.d.ts +28 -0
- package/dist/integrations/msg91-sms-sender.js +46 -0
- package/dist/integrations/msg91-sms-sender.js.map +1 -0
- package/docs/README.md +39 -0
- package/docs/admin-api-keys-webhooks.md +147 -0
- package/docs/api-reference.md +175 -0
- package/docs/architecture.md +119 -0
- package/docs/client-integration.md +192 -0
- package/docs/code-walkthrough.md +273 -0
- package/docs/configuration.md +229 -0
- package/docs/endpoints/README.md +151 -0
- package/docs/endpoints/account.md +363 -0
- package/docs/endpoints/admin.md +422 -0
- package/docs/endpoints/email-password.md +261 -0
- package/docs/endpoints/organizations.md +192 -0
- package/docs/endpoints/passkeys.md +195 -0
- package/docs/endpoints/passwordless.md +214 -0
- package/docs/endpoints/social.md +116 -0
- package/docs/endpoints/two-factor.md +146 -0
- package/docs/error-codes.md +100 -0
- package/docs/events.md +83 -0
- package/docs/getting-started.md +139 -0
- package/docs/manual-testing.md +215 -0
- package/docs/organizations.md +86 -0
- package/docs/production-checklist.md +60 -0
- package/docs/protecting-routes.md +147 -0
- package/docs/security.md +61 -0
- package/docs/sign-in-flows.md +294 -0
- package/package.json +92 -4
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_SETTINGS = void 0;
|
|
4
|
+
/** The default settings live in constants.ts with every other fixed value. */
|
|
5
|
+
var constants_1 = require("../../constants.js");
|
|
6
|
+
Object.defineProperty(exports, "DEFAULT_SETTINGS", { enumerable: true, get: function () { return constants_1.DEFAULT_SETTINGS; } });
|
|
7
|
+
//# sourceMappingURL=settings.defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.defaults.js","sourceRoot":"","sources":["../../../src/features/settings/settings.defaults.ts"],"names":[],"mappings":";;;AAAA,8EAA8E;AAC9E,yCAA+C;AAAtC,6GAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AuthOptions } from '../../auth-options.js';
|
|
2
|
+
import { AuthSettings, SettingsChanges } from './settings.types';
|
|
3
|
+
/**
|
|
4
|
+
* Works out the settings in force:
|
|
5
|
+
* built-in defaults -> settings from your code -> changes an admin saved in the database
|
|
6
|
+
*
|
|
7
|
+
* Settings from code are checked when the app starts; a mistake stops the app with a clear message.
|
|
8
|
+
*/
|
|
9
|
+
export declare class SettingsService {
|
|
10
|
+
private readonly database;
|
|
11
|
+
private readonly settingsFromCode;
|
|
12
|
+
private cachedSettings?;
|
|
13
|
+
constructor(options: AuthOptions);
|
|
14
|
+
/**
|
|
15
|
+
* The settings in force right now: code settings with admin changes on top.
|
|
16
|
+
* Cached for a few seconds, so admin changes reach every server quickly without a query per request.
|
|
17
|
+
*
|
|
18
|
+
* @returns The full settings.
|
|
19
|
+
*/
|
|
20
|
+
getSettings(): Promise<AuthSettings>;
|
|
21
|
+
/**
|
|
22
|
+
* Saves an admin's changes. Settings not mentioned keep their current values.
|
|
23
|
+
*
|
|
24
|
+
* @param changes - Only the sections and fields to change.
|
|
25
|
+
* @param changedBy - Who made the change, e.g. "admin:<id>".
|
|
26
|
+
* @returns The settings now in force.
|
|
27
|
+
* @throws AuthError INVALID_SETTINGS (with `problems`) when a value is not allowed or the
|
|
28
|
+
* result would conflict (e.g. no sign-in method left on).
|
|
29
|
+
*/
|
|
30
|
+
saveAdminChanges(changes: SettingsChanges, changedBy: string): Promise<AuthSettings>;
|
|
31
|
+
/**
|
|
32
|
+
* Forgets every admin change; the settings from your code apply again.
|
|
33
|
+
*
|
|
34
|
+
* @returns The settings from code.
|
|
35
|
+
*/
|
|
36
|
+
discardAdminChanges(): Promise<AuthSettings>;
|
|
37
|
+
/**
|
|
38
|
+
* Reads the admin's saved changes. If a code update made them invalid, they are ignored
|
|
39
|
+
* (rather than breaking sign-in for everyone).
|
|
40
|
+
*
|
|
41
|
+
* @returns The saved changes, or {} when there are none or they are no longer valid.
|
|
42
|
+
*/
|
|
43
|
+
private loadAdminChanges;
|
|
44
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SettingsService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const auth_error_1 = require("../../common/auth-error.js");
|
|
18
|
+
const constants_1 = require("../../constants.js");
|
|
19
|
+
const entities_1 = require("../../database/entities/index.js");
|
|
20
|
+
const settings_defaults_1 = require("./settings.defaults");
|
|
21
|
+
const settings_validation_1 = require("./settings.validation");
|
|
22
|
+
/**
|
|
23
|
+
* Works out the settings in force:
|
|
24
|
+
* built-in defaults -> settings from your code -> changes an admin saved in the database
|
|
25
|
+
*
|
|
26
|
+
* Settings from code are checked when the app starts; a mistake stops the app with a clear message.
|
|
27
|
+
*/
|
|
28
|
+
let SettingsService = class SettingsService {
|
|
29
|
+
database;
|
|
30
|
+
settingsFromCode;
|
|
31
|
+
cachedSettings;
|
|
32
|
+
constructor(options) {
|
|
33
|
+
this.database = options.dataSource;
|
|
34
|
+
const problemsInCode = (0, settings_validation_1.findProblemsInChanges)(options.settings ?? {});
|
|
35
|
+
this.settingsFromCode = (0, settings_validation_1.applySettingsChanges)(settings_defaults_1.DEFAULT_SETTINGS, options.settings);
|
|
36
|
+
problemsInCode.push(...(0, settings_validation_1.findSettingsConflicts)(this.settingsFromCode));
|
|
37
|
+
if (problemsInCode.length > 0) {
|
|
38
|
+
throw new Error(`AuthModule settings are invalid:\n - ${problemsInCode.join('\n - ')}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The settings in force right now: code settings with admin changes on top.
|
|
43
|
+
* Cached for a few seconds, so admin changes reach every server quickly without a query per request.
|
|
44
|
+
*
|
|
45
|
+
* @returns The full settings.
|
|
46
|
+
*/
|
|
47
|
+
getSettings() {
|
|
48
|
+
const cacheIsFresh = this.cachedSettings && Date.now() - this.cachedSettings.loadedAt < constants_1.SETTINGS_CACHE_SECONDS * constants_1.SECOND_IN_MILLISECONDS;
|
|
49
|
+
if (!cacheIsFresh) {
|
|
50
|
+
const settings = this.loadAdminChanges().then((adminChanges) => (0, settings_validation_1.applySettingsChanges)(this.settingsFromCode, adminChanges));
|
|
51
|
+
settings.catch(() => (this.cachedSettings = undefined));
|
|
52
|
+
this.cachedSettings = { settings, loadedAt: Date.now() };
|
|
53
|
+
}
|
|
54
|
+
return this.cachedSettings.settings;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Saves an admin's changes. Settings not mentioned keep their current values.
|
|
58
|
+
*
|
|
59
|
+
* @param changes - Only the sections and fields to change.
|
|
60
|
+
* @param changedBy - Who made the change, e.g. "admin:<id>".
|
|
61
|
+
* @returns The settings now in force.
|
|
62
|
+
* @throws AuthError INVALID_SETTINGS (with `problems`) when a value is not allowed or the
|
|
63
|
+
* result would conflict (e.g. no sign-in method left on).
|
|
64
|
+
*/
|
|
65
|
+
async saveAdminChanges(changes, changedBy) {
|
|
66
|
+
const problemsInChanges = (0, settings_validation_1.findProblemsInChanges)(changes);
|
|
67
|
+
if (problemsInChanges.length > 0)
|
|
68
|
+
throw new auth_error_1.AuthError(constants_1.AUTH_ERRORS.invalidSettings, { problems: problemsInChanges });
|
|
69
|
+
const allAdminChanges = (0, settings_validation_1.combineSettingsChanges)(await this.loadAdminChanges(), changes);
|
|
70
|
+
const newSettings = (0, settings_validation_1.applySettingsChanges)(this.settingsFromCode, allAdminChanges);
|
|
71
|
+
const combinedProblems = (0, settings_validation_1.findSettingsConflicts)(newSettings);
|
|
72
|
+
if (combinedProblems.length > 0)
|
|
73
|
+
throw new auth_error_1.AuthError(constants_1.AUTH_ERRORS.invalidSettings, { problems: combinedProblems });
|
|
74
|
+
await this.database.getRepository(entities_1.SettingsEntity).save({ id: constants_1.SETTINGS_ROW_ID, changedValues: allAdminChanges, changedBy });
|
|
75
|
+
this.cachedSettings = undefined;
|
|
76
|
+
return newSettings;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Forgets every admin change; the settings from your code apply again.
|
|
80
|
+
*
|
|
81
|
+
* @returns The settings from code.
|
|
82
|
+
*/
|
|
83
|
+
async discardAdminChanges() {
|
|
84
|
+
await this.database.getRepository(entities_1.SettingsEntity).delete({ id: constants_1.SETTINGS_ROW_ID });
|
|
85
|
+
this.cachedSettings = undefined;
|
|
86
|
+
return this.settingsFromCode;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Reads the admin's saved changes. If a code update made them invalid, they are ignored
|
|
90
|
+
* (rather than breaking sign-in for everyone).
|
|
91
|
+
*
|
|
92
|
+
* @returns The saved changes, or {} when there are none or they are no longer valid.
|
|
93
|
+
*/
|
|
94
|
+
async loadAdminChanges() {
|
|
95
|
+
const row = await this.database.getRepository(entities_1.SettingsEntity).findOne({ where: { id: constants_1.SETTINGS_ROW_ID } });
|
|
96
|
+
if (!row)
|
|
97
|
+
return {};
|
|
98
|
+
// A code update may have made an old admin change invalid. Fall back to the code settings
|
|
99
|
+
// rather than break sign-in for everyone.
|
|
100
|
+
const savedChanges = row.changedValues;
|
|
101
|
+
const stillValid = (0, settings_validation_1.findProblemsInChanges)(savedChanges).length === 0 &&
|
|
102
|
+
(0, settings_validation_1.findSettingsConflicts)((0, settings_validation_1.applySettingsChanges)(this.settingsFromCode, savedChanges)).length === 0;
|
|
103
|
+
return stillValid ? savedChanges : {};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
exports.SettingsService = SettingsService;
|
|
107
|
+
exports.SettingsService = SettingsService = __decorate([
|
|
108
|
+
(0, common_1.Injectable)(),
|
|
109
|
+
__param(0, (0, common_1.Inject)(constants_1.AUTH_OPTIONS_TOKEN)),
|
|
110
|
+
__metadata("design:paramtypes", [Object])
|
|
111
|
+
], SettingsService);
|
|
112
|
+
//# sourceMappingURL=settings.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.service.js","sourceRoot":"","sources":["../../../src/features/settings/settings.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything an app (or an admin at runtime) can switch on, off or adjust.
|
|
3
|
+
* Defaults are in settings.defaults.ts; validation rules in settings.validation.ts.
|
|
4
|
+
*/
|
|
5
|
+
export interface AuthSettings {
|
|
6
|
+
registration: {
|
|
7
|
+
/** Allow new accounts at all (with any method). */
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
/** Roles every new user gets, e.g. ["user"]. Users can never choose their own role. */
|
|
10
|
+
defaultRoles: string[];
|
|
11
|
+
requireFirstAndLastName: boolean;
|
|
12
|
+
/** Registration with email + password must also include a phone number. */
|
|
13
|
+
requirePhoneNumber: boolean;
|
|
14
|
+
requireTermsAcceptance: boolean;
|
|
15
|
+
requirePrivacyPolicyAcceptance: boolean;
|
|
16
|
+
/** Only these email domains may register, e.g. ["myapp.com"]. Empty = anyone. */
|
|
17
|
+
allowedEmailDomains: string[];
|
|
18
|
+
};
|
|
19
|
+
/** Which verifications move an account from PENDING_VERIFICATION to ACTIVE. */
|
|
20
|
+
activation: {
|
|
21
|
+
requireVerifiedEmail: boolean;
|
|
22
|
+
requireVerifiedPhone: boolean;
|
|
23
|
+
};
|
|
24
|
+
password: {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
minimumLength: number;
|
|
27
|
+
requireUppercaseLetter: boolean;
|
|
28
|
+
requireLowercaseLetter: boolean;
|
|
29
|
+
requireNumber: boolean;
|
|
30
|
+
requireSymbol: boolean;
|
|
31
|
+
/** Refuse passwords found in public data breaches (haveibeenpwned.com; the password never leaves your server). */
|
|
32
|
+
rejectBreachedPasswords: boolean;
|
|
33
|
+
/** Email the user when their password changes. */
|
|
34
|
+
notifyOnChange: boolean;
|
|
35
|
+
};
|
|
36
|
+
emailVerification: {
|
|
37
|
+
/** How long the "verify your email" link works. */
|
|
38
|
+
linkExpiresInHours: number;
|
|
39
|
+
};
|
|
40
|
+
passwordReset: {
|
|
41
|
+
/** How long the "reset your password" link works. */
|
|
42
|
+
linkExpiresInMinutes: number;
|
|
43
|
+
};
|
|
44
|
+
emailChange: {
|
|
45
|
+
/** How long the link that confirms a new email address works. */
|
|
46
|
+
linkExpiresInMinutes: number;
|
|
47
|
+
};
|
|
48
|
+
emailOtp: {
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
codeLength: number;
|
|
51
|
+
expiresInMinutes: number;
|
|
52
|
+
/** Wait before another code can be sent to the same email. */
|
|
53
|
+
resendAfterSeconds: number;
|
|
54
|
+
/** Create an account when an unknown email signs in with a code. */
|
|
55
|
+
allowSignUp: boolean;
|
|
56
|
+
};
|
|
57
|
+
magicLink: {
|
|
58
|
+
enabled: boolean;
|
|
59
|
+
/** How long the sign-in link works. */
|
|
60
|
+
expiresInMinutes: number;
|
|
61
|
+
allowSignUp: boolean;
|
|
62
|
+
};
|
|
63
|
+
phoneOtp: {
|
|
64
|
+
enabled: boolean;
|
|
65
|
+
codeLength: number;
|
|
66
|
+
expiresInMinutes: number;
|
|
67
|
+
/** Wait before another code can be sent to the same number. */
|
|
68
|
+
resendAfterSeconds: number;
|
|
69
|
+
allowSignUp: boolean;
|
|
70
|
+
/** Country calling codes allowed, e.g. ["+91"]. Empty = any country. */
|
|
71
|
+
allowedCountryCodes: string[];
|
|
72
|
+
};
|
|
73
|
+
google: {
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
/** OAuth client IDs of your apps (web, Android, iOS) from Google Cloud Console. */
|
|
76
|
+
clientIds: string[];
|
|
77
|
+
};
|
|
78
|
+
apple: {
|
|
79
|
+
enabled: boolean;
|
|
80
|
+
/** Your iOS bundle ID and/or web Services ID, e.g. ["com.myapp.ios"]. */
|
|
81
|
+
clientIds: string[];
|
|
82
|
+
};
|
|
83
|
+
facebook: {
|
|
84
|
+
enabled: boolean;
|
|
85
|
+
/** Your Facebook App ID (the secret goes in AuthOptions.facebookAppSecret). */
|
|
86
|
+
appId: string;
|
|
87
|
+
};
|
|
88
|
+
passkeys: {
|
|
89
|
+
enabled: boolean;
|
|
90
|
+
};
|
|
91
|
+
twoFactor: {
|
|
92
|
+
/** Users may turn on two-factor authentication with an authenticator app. */
|
|
93
|
+
enabled: boolean;
|
|
94
|
+
/** After the password (or code) is right, how long the user has to enter their 2FA code. */
|
|
95
|
+
challengeExpiresInMinutes: number;
|
|
96
|
+
};
|
|
97
|
+
organizations: {
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
/** Any user may create an organization (otherwise only admins). */
|
|
100
|
+
allowUsersToCreate: boolean;
|
|
101
|
+
/** How long an emailed invitation can be accepted. */
|
|
102
|
+
invitationExpiresInDays: number;
|
|
103
|
+
};
|
|
104
|
+
tokens: {
|
|
105
|
+
accessTokenMinutes: number;
|
|
106
|
+
refreshTokenDays: number;
|
|
107
|
+
/** Hard limit: after this many days the user must sign in again. */
|
|
108
|
+
sessionDays: number;
|
|
109
|
+
};
|
|
110
|
+
admin: {
|
|
111
|
+
/** Users with any of these roles may use the /auth/admin endpoints. */
|
|
112
|
+
adminRoles: string[];
|
|
113
|
+
};
|
|
114
|
+
security: {
|
|
115
|
+
/** Email the user when their account is signed in from a new device. */
|
|
116
|
+
notifyOnNewSignIn: boolean;
|
|
117
|
+
};
|
|
118
|
+
/** How long old rows are kept. A cleanup runs every hour on each server (DataRetentionService). */
|
|
119
|
+
retention: {
|
|
120
|
+
/** Turn the automatic hourly cleanup off (e.g. to run it from your own job instead). */
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
/** Ended sessions and used or expired codes, links, 2FA challenges and invitations. */
|
|
123
|
+
expiredRecordDays: number;
|
|
124
|
+
/** Delivered or failed webhook deliveries (pending ones are never removed). */
|
|
125
|
+
webhookDeliveryDays: number;
|
|
126
|
+
/** Audit log entries. 0 = keep forever. */
|
|
127
|
+
auditLogDays: number;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/** A partial set of settings: only the values you want to change. */
|
|
131
|
+
export type SettingsChanges = {
|
|
132
|
+
[Section in keyof AuthSettings]?: Partial<AuthSettings[Section]>;
|
|
133
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.types.js","sourceRoot":"","sources":["../../../src/features/settings/settings.types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AuthSettings, SettingsChanges } from './settings.types';
|
|
2
|
+
/**
|
|
3
|
+
* Checks a set of changes on its own (types, ranges, unknown fields).
|
|
4
|
+
*
|
|
5
|
+
* @param changes - Settings changes from code or from an admin.
|
|
6
|
+
* @returns Readable problems like "password.minimumLength must not be less than 8"; empty means valid.
|
|
7
|
+
*/
|
|
8
|
+
export declare function findProblemsInChanges(changes: unknown): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Checks rules that involve several settings together, on the final merged settings
|
|
11
|
+
* (e.g. at least one sign-in method must stay on).
|
|
12
|
+
*
|
|
13
|
+
* @param settings - The full merged settings.
|
|
14
|
+
* @returns Readable problems; empty means valid.
|
|
15
|
+
*/
|
|
16
|
+
export declare function findSettingsConflicts(settings: AuthSettings): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Applies changes on top of settings, one section at a time. Unknown sections are ignored.
|
|
19
|
+
* The input objects are not modified.
|
|
20
|
+
*
|
|
21
|
+
* @param base - The settings to start from.
|
|
22
|
+
* @param changes - The changes to apply.
|
|
23
|
+
* @returns A new settings object.
|
|
24
|
+
*/
|
|
25
|
+
export declare function applySettingsChanges(base: AuthSettings, changes?: SettingsChanges): AuthSettings;
|
|
26
|
+
/**
|
|
27
|
+
* Combines two sets of changes; later values win. Used to keep admin changes on top of each other.
|
|
28
|
+
*
|
|
29
|
+
* @param earlier - The changes saved before.
|
|
30
|
+
* @param later - The new changes.
|
|
31
|
+
* @returns A new, combined set of changes.
|
|
32
|
+
*/
|
|
33
|
+
export declare function combineSettingsChanges(earlier: SettingsChanges, later: SettingsChanges): SettingsChanges;
|