@astram/guard 0.13.0 → 0.15.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/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +57 -30
- package/dist/auth/connections.d.ts +2 -2
- package/dist/auth/connections.d.ts.map +1 -1
- package/dist/auth/connections.js +4 -13
- package/dist/authentication/mariadb-api-key-store.d.ts +10 -1
- package/dist/authentication/mariadb-api-key-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-api-key-store.js +20 -10
- package/dist/authentication/mariadb-credential-resolver.d.ts +8 -1
- package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-resolver.js +15 -5
- package/dist/authentication/mariadb-credential-writer.d.ts +6 -1
- package/dist/authentication/mariadb-credential-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-writer.js +9 -3
- package/dist/authentication/mariadb-email-address-changer.d.ts +10 -1
- package/dist/authentication/mariadb-email-address-changer.d.ts.map +1 -1
- package/dist/authentication/mariadb-email-address-changer.js +22 -9
- package/dist/authentication/mariadb-email-change-token-store.d.ts +8 -1
- package/dist/authentication/mariadb-email-change-token-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-email-change-token-store.js +18 -9
- package/dist/authentication/mariadb-mfa-device-store.d.ts +6 -1
- package/dist/authentication/mariadb-mfa-device-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-mfa-device-store.js +22 -13
- package/dist/authentication/mariadb-profile-resolver.d.ts +6 -1
- package/dist/authentication/mariadb-profile-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-profile-resolver.js +12 -6
- package/dist/authentication/mariadb-profile-writer.d.ts +6 -1
- package/dist/authentication/mariadb-profile-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-profile-writer.js +11 -4
- package/dist/authentication/mariadb-recovery-code-store.d.ts +6 -1
- package/dist/authentication/mariadb-recovery-code-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-recovery-code-store.js +11 -5
- package/dist/authentication/mariadb-reset-token-store.d.ts +6 -1
- package/dist/authentication/mariadb-reset-token-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-reset-token-store.js +11 -5
- package/dist/authentication/mariadb-session-sweeper.d.ts +6 -1
- package/dist/authentication/mariadb-session-sweeper.d.ts.map +1 -1
- package/dist/authentication/mariadb-session-sweeper.js +11 -5
- package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -1
- package/dist/authz/cross-tenant-grant-writer.js +4 -3
- package/dist/authz/list-scope-sql.d.ts +10 -2
- package/dist/authz/list-scope-sql.d.ts.map +1 -1
- package/dist/authz/list-scope-sql.js +4 -4
- package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-cross-tenant-grant-adapter.js +4 -3
- package/dist/authz/mariadb-list-scope-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-list-scope-adapter.js +4 -3
- package/dist/authz/mariadb-policy-store.d.ts.map +1 -1
- package/dist/authz/mariadb-policy-store.js +4 -3
- package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-record-rule-adapter.js +4 -3
- package/dist/authz/mariadb-record-share-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-record-share-adapter.js +4 -3
- package/dist/authz/record-share-cascade.d.ts.map +1 -1
- package/dist/authz/record-share-cascade.js +4 -3
- package/dist/authz/record-share-writer.d.ts.map +1 -1
- package/dist/authz/record-share-writer.js +4 -3
- package/dist/authz/wire-record-authorization.d.ts +8 -0
- package/dist/authz/wire-record-authorization.d.ts.map +1 -1
- package/dist/authz/wire-record-authorization.js +14 -6
- package/dist/boot/boot-sequence.d.ts +4 -0
- package/dist/boot/boot-sequence.d.ts.map +1 -1
- package/dist/boot/boot-sequence.js +13 -1
- package/dist/boot/migration-ledger-check.d.ts +94 -0
- package/dist/boot/migration-ledger-check.d.ts.map +1 -0
- package/dist/boot/migration-ledger-check.js +280 -0
- package/dist/config/app-config.d.ts +72 -3
- package/dist/config/app-config.d.ts.map +1 -1
- package/dist/config/app-config.js +129 -7
- package/dist/config/config.module.d.ts +7 -0
- package/dist/config/config.module.d.ts.map +1 -1
- package/dist/config/config.module.js +13 -2
- package/dist/config/framework-schema-names.d.ts +29 -0
- package/dist/config/framework-schema-names.d.ts.map +1 -0
- package/dist/config/framework-schema-names.js +41 -0
- package/dist/config/loopback-host.d.ts +9 -0
- package/dist/config/loopback-host.d.ts.map +1 -0
- package/dist/config/loopback-host.js +19 -0
- package/dist/encryption/local-kek-crypto.d.ts +6 -0
- package/dist/encryption/local-kek-crypto.d.ts.map +1 -1
- package/dist/encryption/local-kek-crypto.js +8 -0
- package/dist/identity/identity-actions.d.ts +18 -7
- package/dist/identity/identity-actions.d.ts.map +1 -1
- package/dist/identity/identity-actions.js +16 -17
- package/dist/identity/module-registry.bridge.d.ts.map +1 -1
- package/dist/identity/module-registry.bridge.js +5 -3
- package/dist/identity/permission-facts.adapter.d.ts +7 -1
- package/dist/identity/permission-facts.adapter.d.ts.map +1 -1
- package/dist/identity/permission-facts.adapter.js +15 -6
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -22
- package/dist/module/shield-tokens.d.ts +11 -0
- package/dist/module/shield-tokens.d.ts.map +1 -1
- package/dist/module/shield-tokens.js +12 -1
- package/dist/module/shield.module.d.ts +10 -0
- package/dist/module/shield.module.d.ts.map +1 -1
- package/dist/module/shield.module.js +78 -12
- package/dist/secrets/boot-secrets.d.ts +33 -0
- package/dist/secrets/boot-secrets.d.ts.map +1 -0
- package/dist/secrets/boot-secrets.js +180 -0
- package/dist/session/mariadb-session-record-store.d.ts +8 -1
- package/dist/session/mariadb-session-record-store.d.ts.map +1 -1
- package/dist/session/mariadb-session-record-store.js +23 -13
- package/dist/session/session-restriction-store.d.ts +8 -1
- package/dist/session/session-restriction-store.d.ts.map +1 -1
- package/dist/session/session-restriction-store.js +15 -5
- package/dist/storage/file-intake.interceptor.d.ts +54 -0
- package/dist/storage/file-intake.interceptor.d.ts.map +1 -0
- package/dist/storage/file-intake.interceptor.js +223 -0
- package/dist/storage/node-sha256-digest.d.ts +6 -0
- package/dist/storage/node-sha256-digest.d.ts.map +1 -0
- package/dist/storage/node-sha256-digest.js +15 -0
- package/dist/storage/object-store-boot-check.d.ts +16 -0
- package/dist/storage/object-store-boot-check.d.ts.map +1 -0
- package/dist/storage/object-store-boot-check.js +52 -0
- package/dist/storage/optional-peer.d.ts +10 -0
- package/dist/storage/optional-peer.d.ts.map +1 -0
- package/dist/storage/optional-peer.js +26 -0
- package/dist/storage/s3-object-store.d.ts +35 -0
- package/dist/storage/s3-object-store.d.ts.map +1 -0
- package/dist/storage/s3-object-store.js +238 -0
- package/dist/storage/storage.providers.d.ts +10 -0
- package/dist/storage/storage.providers.d.ts.map +1 -0
- package/dist/storage/storage.providers.js +104 -0
- package/migrations/1710000000006-CreateAuthzSchema.cjs +15 -4
- package/migrations/1710000000007-ExtendPermissionAndRolePermission.cjs +11 -3
- package/migrations/1710000000008-CreateAccessBundleTables.cjs +14 -4
- package/migrations/1710000000009-CreateRecordPermissionRule.cjs +15 -4
- package/migrations/1710000000014-CreateRecordShare.cjs +15 -4
- package/migrations/1710000000015-CreateScopeClosure.cjs +14 -4
- package/migrations/1710000000016-AlterCompanyParentFkRestrict.cjs +20 -9
- package/migrations/1710000000017-CreateServiceAccountKey.cjs +14 -4
- package/package.json +11 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,OAAO,EAAkB,KAAK,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAanF,OAAO,KAAK,EAGV,kBAAkB,EAOlB,QAAQ,EACR,cAAc,EAIf,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/auth.module.js
CHANGED
|
@@ -112,6 +112,8 @@ const common_1 = require("@nestjs/common");
|
|
|
112
112
|
const node_crypto_1 = require("node:crypto");
|
|
113
113
|
const app_config_js_1 = require("../config/app-config.js");
|
|
114
114
|
const config_module_js_1 = require("../config/config.module.js");
|
|
115
|
+
const migration_ledger_check_js_1 = require("../boot/migration-ledger-check.js");
|
|
116
|
+
const migrations_dir_js_1 = require("../migrations-dir.js");
|
|
115
117
|
const argon2id_password_hasher_js_1 = require("../authentication/argon2id-password-hasher.js");
|
|
116
118
|
const mariadb_credential_resolver_js_1 = require("../authentication/mariadb-credential-resolver.js");
|
|
117
119
|
const mariadb_profile_resolver_js_1 = require("../authentication/mariadb-profile-resolver.js");
|
|
@@ -251,8 +253,8 @@ function makeCredentialResolverProvider(override) {
|
|
|
251
253
|
provide: tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
|
|
252
254
|
// #7: the default resolver folds the principal's CONFIRMED MFA devices into a
|
|
253
255
|
// `totp` required factor, so enrolled MFA is enforced at every password login.
|
|
254
|
-
useFactory: (pool, devices) => new mariadb_credential_resolver_js_1.MariaDbCredentialResolver(pool, devices),
|
|
255
|
-
inject: [tokens_js_1.SHIELD_DB_POOL, tokens_js_1.SHIELD_MFA_DEVICE_STORE],
|
|
256
|
+
useFactory: (pool, devices, config) => new mariadb_credential_resolver_js_1.MariaDbCredentialResolver(pool, devices, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
257
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, tokens_js_1.SHIELD_MFA_DEVICE_STORE, config_module_js_1.APP_CONFIG],
|
|
256
258
|
};
|
|
257
259
|
}
|
|
258
260
|
/**
|
|
@@ -272,11 +274,11 @@ const sessionLifetimesProvider = {
|
|
|
272
274
|
*/
|
|
273
275
|
const sessionRecordStoreProvider = {
|
|
274
276
|
provide: index_js_1.SHIELD_SESSION_RECORD_STORE,
|
|
275
|
-
useFactory: (pool, binder) => {
|
|
276
|
-
const durable = new index_js_1.MariaDbSessionRecordStore(pool);
|
|
277
|
+
useFactory: (pool, binder, config) => {
|
|
278
|
+
const durable = new index_js_1.MariaDbSessionRecordStore(pool, (0, app_config_js_1.frameworkSchemasOf)(config));
|
|
277
279
|
return new index_js_1.HotRevokingSessionRecordStore(durable, binder, durable);
|
|
278
280
|
},
|
|
279
|
-
inject: [tokens_js_1.SHIELD_DB_POOL, tokens_js_2.SHIELD_SESSION_TOKEN_BINDER],
|
|
281
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, tokens_js_2.SHIELD_SESSION_TOKEN_BINDER, config_module_js_1.APP_CONFIG],
|
|
280
282
|
};
|
|
281
283
|
/**
|
|
282
284
|
* The Redis permission-version cache (ADR-0035, GAPS #6): gate 5 reads the tenant's version from
|
|
@@ -295,8 +297,8 @@ const permissionVersionCacheProvider = {
|
|
|
295
297
|
*/
|
|
296
298
|
const sessionRestrictionStoreProvider = {
|
|
297
299
|
provide: tokens_js_1.SHIELD_SESSION_RESTRICTIONS,
|
|
298
|
-
useFactory: (pool) => new session_restriction_store_js_1.MariaDbSessionRestrictionStore(pool),
|
|
299
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
300
|
+
useFactory: (pool, config) => new session_restriction_store_js_1.MariaDbSessionRestrictionStore(pool, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
301
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
300
302
|
};
|
|
301
303
|
/** Hot session store (Redis adapter, injected with the live client). */
|
|
302
304
|
const hotSessionStoreProvider = {
|
|
@@ -356,11 +358,34 @@ const mfaLimiterProvider = {
|
|
|
356
358
|
*/
|
|
357
359
|
const serviceAuthenticatorProvider = {
|
|
358
360
|
provide: tokens_js_2.SHIELD_SERVICE_AUTHENTICATOR,
|
|
359
|
-
useFactory: (pool) => (0, core_1.createServiceAuthenticator)({
|
|
360
|
-
store: new mariadb_api_key_store_js_1.MariaDbApiKeyStore(pool),
|
|
361
|
+
useFactory: (pool, config) => (0, core_1.createServiceAuthenticator)({
|
|
362
|
+
store: new mariadb_api_key_store_js_1.MariaDbApiKeyStore(pool, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
361
363
|
hasher: new argon2id_password_hasher_js_1.Argon2idPasswordHasher(),
|
|
362
364
|
}),
|
|
363
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
365
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* configurable-framework-db spec 5.D: at application bootstrap (once, never per request, Shield
|
|
369
|
+
* #12) check that every guard migration is in the `@astram/migrate` ledger, read with ONE SELECT
|
|
370
|
+
* over this module's runtime pool. Lives here, not in `BootModule`, because this is the only
|
|
371
|
+
* guard module holding a pool (the raw pool stays unexported, Phase 8 #5); an enforcement-only
|
|
372
|
+
* app opens no pool and reads no guard table, so it has nothing to check.
|
|
373
|
+
*/
|
|
374
|
+
const migrationLedgerCheckProvider = {
|
|
375
|
+
// Its own token (identity provides another), so a merged module can never shadow one check.
|
|
376
|
+
provide: migration_ledger_check_js_1.SHIELD_GUARD_MIGRATION_LEDGER_CHECK,
|
|
377
|
+
useFactory: (pool, config, registry) => new migration_ledger_check_js_1.FrameworkMigrationLedgerCheck({
|
|
378
|
+
query: (sql) => pool.query(sql),
|
|
379
|
+
// The ledger candidates (G-007 QA P1): `<ns>_app`, or DDL_DB_NAME / APP_DB_NAME /
|
|
380
|
+
// shield_app probed in order in default mode.
|
|
381
|
+
...(0, migration_ledger_check_js_1.resolveMigrationLedgerCheck)(process.env, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
382
|
+
migrationsDir: migrations_dir_js_1.guardMigrationsDir,
|
|
383
|
+
nodeEnv: process.env.NODE_ENV,
|
|
384
|
+
logger: new common_1.Logger('Shield'),
|
|
385
|
+
},
|
|
386
|
+
// ShieldModule's per-app registry: one ledger read shared with identity's check.
|
|
387
|
+
registry ?? null),
|
|
388
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG, { token: migration_ledger_check_js_1.SHIELD_MIGRATION_LEDGER_REGISTRY, optional: true }],
|
|
364
389
|
};
|
|
365
390
|
/** Boot-time warnings from the auth composition (dev email logger, disabled email, …). */
|
|
366
391
|
const authBootLogger = new common_1.Logger('ShieldAuth');
|
|
@@ -656,8 +681,8 @@ function makeProfileResolverProvider(override) {
|
|
|
656
681
|
? { provide: tokens_js_1.SHIELD_PROFILE_RESOLVER, useValue: override }
|
|
657
682
|
: {
|
|
658
683
|
provide: tokens_js_1.SHIELD_PROFILE_RESOLVER,
|
|
659
|
-
useFactory: (pool) => new mariadb_profile_resolver_js_1.MariaDbProfileResolver(pool),
|
|
660
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
684
|
+
useFactory: (pool, config) => new mariadb_profile_resolver_js_1.MariaDbProfileResolver(pool, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
685
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
661
686
|
};
|
|
662
687
|
}
|
|
663
688
|
/**
|
|
@@ -671,8 +696,8 @@ function makeCredentialWriterProvider(override) {
|
|
|
671
696
|
? { provide: tokens_js_1.SHIELD_CREDENTIAL_WRITER, useValue: override }
|
|
672
697
|
: {
|
|
673
698
|
provide: tokens_js_1.SHIELD_CREDENTIAL_WRITER,
|
|
674
|
-
useFactory: (pool) => new mariadb_credential_writer_js_1.MariaDbCredentialWriter(pool),
|
|
675
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
699
|
+
useFactory: (pool, config) => new mariadb_credential_writer_js_1.MariaDbCredentialWriter(pool, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
700
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
676
701
|
};
|
|
677
702
|
}
|
|
678
703
|
function makeResetTokenStoreProvider(override) {
|
|
@@ -680,8 +705,8 @@ function makeResetTokenStoreProvider(override) {
|
|
|
680
705
|
? { provide: tokens_js_1.SHIELD_RESET_TOKEN_STORE, useValue: override }
|
|
681
706
|
: {
|
|
682
707
|
provide: tokens_js_1.SHIELD_RESET_TOKEN_STORE,
|
|
683
|
-
useFactory: (pool) => new mariadb_reset_token_store_js_1.MariaDbResetTokenStore(pool),
|
|
684
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
708
|
+
useFactory: (pool, config) => new mariadb_reset_token_store_js_1.MariaDbResetTokenStore(pool, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
709
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
685
710
|
};
|
|
686
711
|
}
|
|
687
712
|
/**
|
|
@@ -690,14 +715,14 @@ function makeResetTokenStoreProvider(override) {
|
|
|
690
715
|
*/
|
|
691
716
|
const emailChangeTokenStoreProvider = {
|
|
692
717
|
provide: tokens_js_1.SHIELD_EMAIL_CHANGE_TOKEN_STORE,
|
|
693
|
-
useFactory: (pool) => new mariadb_email_change_token_store_js_1.MariaDbEmailChangeTokenStore(pool),
|
|
694
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
718
|
+
useFactory: (pool, config) => new mariadb_email_change_token_store_js_1.MariaDbEmailChangeTokenStore(pool, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
719
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
695
720
|
};
|
|
696
721
|
/** The ONE email read/write path for an email change (Phase 12): the framework default. */
|
|
697
722
|
const emailAddressChangerProvider = {
|
|
698
723
|
provide: tokens_js_1.SHIELD_EMAIL_ADDRESS_CHANGER,
|
|
699
|
-
useFactory: (pool) => new mariadb_email_address_changer_js_1.MariaDbEmailAddressChanger(pool),
|
|
700
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
724
|
+
useFactory: (pool, config) => new mariadb_email_address_changer_js_1.MariaDbEmailAddressChanger(pool, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
725
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
701
726
|
};
|
|
702
727
|
/**
|
|
703
728
|
* The per-account email-change REQUEST limiter (Phase 12) — `email-change:pid:<id>`, 3 per 60-min
|
|
@@ -781,8 +806,8 @@ function makeRecoveryCodeStoreProvider(override) {
|
|
|
781
806
|
? { provide: tokens_js_1.SHIELD_RECOVERY_CODE_STORE, useValue: override }
|
|
782
807
|
: {
|
|
783
808
|
provide: tokens_js_1.SHIELD_RECOVERY_CODE_STORE,
|
|
784
|
-
useFactory: (pool, hasher) => new mariadb_recovery_code_store_js_1.MariaDbRecoveryCodeStore(pool, hasher),
|
|
785
|
-
inject: [tokens_js_1.SHIELD_DB_POOL, argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER],
|
|
809
|
+
useFactory: (pool, hasher, config) => new mariadb_recovery_code_store_js_1.MariaDbRecoveryCodeStore(pool, hasher, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
810
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER, config_module_js_1.APP_CONFIG],
|
|
786
811
|
};
|
|
787
812
|
}
|
|
788
813
|
function makeProfileWriterProvider(override) {
|
|
@@ -790,8 +815,8 @@ function makeProfileWriterProvider(override) {
|
|
|
790
815
|
? { provide: tokens_js_1.SHIELD_PROFILE_WRITER, useValue: override }
|
|
791
816
|
: {
|
|
792
817
|
provide: tokens_js_1.SHIELD_PROFILE_WRITER,
|
|
793
|
-
useFactory: (pool) => new mariadb_profile_writer_js_1.MariaDbProfileWriter(pool),
|
|
794
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
818
|
+
useFactory: (pool, config) => new mariadb_profile_writer_js_1.MariaDbProfileWriter(pool, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
819
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
795
820
|
};
|
|
796
821
|
}
|
|
797
822
|
function makeSessionSweeperProvider(override) {
|
|
@@ -799,8 +824,8 @@ function makeSessionSweeperProvider(override) {
|
|
|
799
824
|
? { provide: tokens_js_1.SHIELD_SESSION_SWEEPER, useValue: override }
|
|
800
825
|
: {
|
|
801
826
|
provide: tokens_js_1.SHIELD_SESSION_SWEEPER,
|
|
802
|
-
useFactory: (pool, binder) => new mariadb_session_sweeper_js_1.MariaDbSessionSweeper(pool, binder),
|
|
803
|
-
inject: [tokens_js_1.SHIELD_DB_POOL, tokens_js_2.SHIELD_SESSION_TOKEN_BINDER],
|
|
827
|
+
useFactory: (pool, binder, config) => new mariadb_session_sweeper_js_1.MariaDbSessionSweeper(pool, binder, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
828
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, tokens_js_2.SHIELD_SESSION_TOKEN_BINDER, config_module_js_1.APP_CONFIG],
|
|
804
829
|
};
|
|
805
830
|
}
|
|
806
831
|
function makeMfaDeviceStoreProvider(override) {
|
|
@@ -808,8 +833,8 @@ function makeMfaDeviceStoreProvider(override) {
|
|
|
808
833
|
? { provide: tokens_js_1.SHIELD_MFA_DEVICE_STORE, useValue: override }
|
|
809
834
|
: {
|
|
810
835
|
provide: tokens_js_1.SHIELD_MFA_DEVICE_STORE,
|
|
811
|
-
useFactory: (pool) => new mariadb_mfa_device_store_js_1.MariaDbMfaDeviceStore(pool),
|
|
812
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
836
|
+
useFactory: (pool, config) => new mariadb_mfa_device_store_js_1.MariaDbMfaDeviceStore(pool, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
837
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
813
838
|
};
|
|
814
839
|
}
|
|
815
840
|
function makeAuditSinkProvider(override) {
|
|
@@ -947,8 +972,8 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
947
972
|
// keys. The keys are CLOSED-OVER option values (never a guard→identity import).
|
|
948
973
|
{
|
|
949
974
|
provide: tokens_js_1.SHIELD_PERMISSION_FACTS,
|
|
950
|
-
useFactory: (pool) => new permission_facts_adapter_js_1.MariaDbPermissionFactsAdapter(pool, () => identityActionKeys, identityControlPlaneKeys),
|
|
951
|
-
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
975
|
+
useFactory: (pool, config) => new permission_facts_adapter_js_1.MariaDbPermissionFactsAdapter(pool, () => identityActionKeys, identityControlPlaneKeys, undefined, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
976
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
952
977
|
},
|
|
953
978
|
// The reset-link base URL value the forgot-password handler composes into the
|
|
954
979
|
// emailed link (framework-owned URL composition; EmailSender stays dumb).
|
|
@@ -1002,6 +1027,8 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
1002
1027
|
forgotLimiterProvider,
|
|
1003
1028
|
forgotHintLimiterProvider,
|
|
1004
1029
|
resetLimiterProvider,
|
|
1030
|
+
// spec 5.D: the guard migrations are in the ledger (once at bootstrap; production fails).
|
|
1031
|
+
migrationLedgerCheckProvider,
|
|
1005
1032
|
],
|
|
1006
1033
|
exports: [
|
|
1007
1034
|
tokens_js_1.SHIELD_AUTHENTICATOR,
|
|
@@ -25,6 +25,7 @@ import { type OnModuleDestroy } from '@nestjs/common';
|
|
|
25
25
|
import { type Pool } from 'mariadb';
|
|
26
26
|
import Redis from 'ioredis';
|
|
27
27
|
import { type AppConfig, type DbTlsConfig } from '../config/app-config.js';
|
|
28
|
+
import { isLoopbackHost } from '../config/loopback-host.js';
|
|
28
29
|
/**
|
|
29
30
|
* Create the ONE live `mariadb` {@link Pool} for the `shield_core` account from
|
|
30
31
|
* {@link AppConfig}. The `connectionLimit` comes from the ADR-0018 budget
|
|
@@ -37,8 +38,7 @@ import { type AppConfig, type DbTlsConfig } from '../config/app-config.js';
|
|
|
37
38
|
* documented defaults, so the descriptor is always well-formed.
|
|
38
39
|
*/
|
|
39
40
|
export declare function createDbPool(config: AppConfig): Pool;
|
|
40
|
-
|
|
41
|
-
export declare function isLoopbackHost(host: string): boolean;
|
|
41
|
+
export { isLoopbackHost };
|
|
42
42
|
/**
|
|
43
43
|
* The boot warning for a production pool to a remote MariaDB without TLS (Phase 16), or
|
|
44
44
|
* `undefined` when none applies. Warns only: production accounts are provisioned `REQUIRE SSL`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/auth/connections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAgB,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/auth/connections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAgB,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiBpD;AAMD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAC7B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CASpB;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,GAAG,SAAS,GAC3B;IAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAA;CAAE,GAAG,SAAS,CAIzE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,CAgB1D;AAED;;;;;;GAMG;AACH,qBACa,mBAAoB,YAAW,eAAe;IAEvD,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK;IAGzB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAavC"}
|
package/dist/auth/connections.js
CHANGED
|
@@ -35,9 +35,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.ConnectionLifecycle = void 0;
|
|
38
|
+
exports.ConnectionLifecycle = exports.isLoopbackHost = void 0;
|
|
39
39
|
exports.createDbPool = createDbPool;
|
|
40
|
-
exports.isLoopbackHost = isLoopbackHost;
|
|
41
40
|
exports.dbTlsBootWarning = dbTlsBootWarning;
|
|
42
41
|
exports.mariadbSslOption = mariadbSslOption;
|
|
43
42
|
exports.createRedisClient = createRedisClient;
|
|
@@ -46,6 +45,8 @@ const common_1 = require("@nestjs/common");
|
|
|
46
45
|
const mariadb_1 = __importDefault(require("mariadb"));
|
|
47
46
|
const ioredis_1 = __importDefault(require("ioredis"));
|
|
48
47
|
const app_config_js_1 = require("../config/app-config.js");
|
|
48
|
+
const loopback_host_js_1 = require("../config/loopback-host.js");
|
|
49
|
+
Object.defineProperty(exports, "isLoopbackHost", { enumerable: true, get: function () { return loopback_host_js_1.isLoopbackHost; } });
|
|
49
50
|
/**
|
|
50
51
|
* Create the ONE live `mariadb` {@link Pool} for the `shield_core` account from
|
|
51
52
|
* {@link AppConfig}. The `connectionLimit` comes from the ADR-0018 budget
|
|
@@ -77,16 +78,6 @@ function createDbPool(config) {
|
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
const dbBootLogger = new common_1.Logger('ShieldAuth');
|
|
80
|
-
/** `localhost`, `127.0.0.0/8` or `::1` (any case, with or without IPv6 brackets). */
|
|
81
|
-
function isLoopbackHost(host) {
|
|
82
|
-
const h = host
|
|
83
|
-
.trim()
|
|
84
|
-
.toLowerCase()
|
|
85
|
-
.replace(/^\[(.*)\]$/, '$1');
|
|
86
|
-
if (h === 'localhost' || h === '::1' || h === '0:0:0:0:0:0:0:1')
|
|
87
|
-
return true;
|
|
88
|
-
return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h);
|
|
89
|
-
}
|
|
90
81
|
/**
|
|
91
82
|
* The boot warning for a production pool to a remote MariaDB without TLS (Phase 16), or
|
|
92
83
|
* `undefined` when none applies. Warns only: production accounts are provisioned `REQUIRE SSL`,
|
|
@@ -98,7 +89,7 @@ function dbTlsBootWarning(config, env = process.env) {
|
|
|
98
89
|
return undefined;
|
|
99
90
|
if ((config.db.tls?.mode ?? 'off') === 'on')
|
|
100
91
|
return undefined;
|
|
101
|
-
if (isLoopbackHost(config.db.host))
|
|
92
|
+
if ((0, loopback_host_js_1.isLoopbackHost)(config.db.host))
|
|
102
93
|
return undefined;
|
|
103
94
|
return (`APP_DB_TLS is off but APP_DB_HOST '${config.db.host}' is not loopback (NODE_ENV=production): ` +
|
|
104
95
|
'database traffic, credentials included, is sent in plaintext. Set APP_DB_TLS=on ' +
|
|
@@ -20,9 +20,18 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import type { Pool } from 'mariadb';
|
|
22
22
|
import type { ApiKeyStore, ApiKeyRecord } from '@astram/core';
|
|
23
|
+
import { type FrameworkSchemaNames } from '../config/framework-schema-names.js';
|
|
23
24
|
export declare class MariaDbApiKeyStore implements ApiKeyStore {
|
|
24
25
|
private readonly pool;
|
|
25
|
-
|
|
26
|
+
/** `<authz>`.`service_account_key`. */
|
|
27
|
+
private readonly keyTable;
|
|
28
|
+
/** The account rows (`<app>`.`service_account`, created by the identity migration `…018`). */
|
|
29
|
+
private readonly accountTable;
|
|
30
|
+
/** `<app>`.`companies` (the account's tenant company). */
|
|
31
|
+
private readonly companyTable;
|
|
32
|
+
constructor(pool: Pool,
|
|
33
|
+
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
34
|
+
schemas?: FrameworkSchemaNames);
|
|
26
35
|
getByAccountId(accountId: string): Promise<ApiKeyRecord | null>;
|
|
27
36
|
/**
|
|
28
37
|
* Persist a NEW key version for an account (issue or rotate). Only the HASH is stored. `version`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-api-key-store.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-api-key-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-api-key-store.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-api-key-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AA2C7C,qBAAa,kBAAmB,YAAW,WAAW;IASlD,OAAO,CAAC,QAAQ,CAAC,IAAI;IARvB,uCAAuC;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,8FAA8F;IAC9F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAGnB,IAAI,EAAE,IAAI;IAC3B,yFAAyF;IACzF,OAAO,CAAC,EAAE,oBAAoB;IAQ1B,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA0DrE;;;;OAIG;IACG,UAAU,CAAC,KAAK,EAAE;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;QACvC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBjB,iGAAiG;IAC3F,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxD,+FAA+F;IACzF,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ7D"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MariaDbApiKeyStore = void 0;
|
|
4
|
-
const
|
|
5
|
-
/** The account rows (`service_account`, created by the identity migration `…018`). */
|
|
6
|
-
const APP = 'shield_app';
|
|
4
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
7
5
|
/**
|
|
8
6
|
* Read a JSON-array column into a `string[]`. The mariadb driver returns a JSON/`longtext` column
|
|
9
7
|
* EITHER already-parsed (an array/object — its default for JSON columns) OR as a raw string,
|
|
@@ -28,8 +26,20 @@ function parseJsonArray(v) {
|
|
|
28
26
|
}
|
|
29
27
|
class MariaDbApiKeyStore {
|
|
30
28
|
pool;
|
|
31
|
-
|
|
29
|
+
/** `<authz>`.`service_account_key`. */
|
|
30
|
+
keyTable;
|
|
31
|
+
/** The account rows (`<app>`.`service_account`, created by the identity migration `…018`). */
|
|
32
|
+
accountTable;
|
|
33
|
+
/** `<app>`.`companies` (the account's tenant company). */
|
|
34
|
+
companyTable;
|
|
35
|
+
constructor(pool,
|
|
36
|
+
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
37
|
+
schemas) {
|
|
32
38
|
this.pool = pool;
|
|
39
|
+
const s = (0, framework_schema_names_js_1.schemaNamesAtConstruction)(schemas);
|
|
40
|
+
this.keyTable = (0, framework_schema_names_js_1.qualifiedTableName)(s.authz, 'service_account_key');
|
|
41
|
+
this.accountTable = (0, framework_schema_names_js_1.qualifiedTableName)(s.app, 'service_account');
|
|
42
|
+
this.companyTable = (0, framework_schema_names_js_1.qualifiedTableName)(s.app, 'companies');
|
|
33
43
|
}
|
|
34
44
|
async getByAccountId(accountId) {
|
|
35
45
|
// The CURRENT key = highest version for the account. (Rotation inserts a new version; the old
|
|
@@ -56,9 +66,9 @@ class MariaDbApiKeyStore {
|
|
|
56
66
|
k.sak_secret_hash, k.sak_version, k.sak_expires_at_ms, k.sak_revoked_at_ms,
|
|
57
67
|
sa.sa_scope_subtree, sa.sa_role_ids, sa.sa_status, sa.sa_tenant_id,
|
|
58
68
|
c.c_uuid AS tenant_company_uuid
|
|
59
|
-
FROM
|
|
60
|
-
JOIN
|
|
61
|
-
LEFT JOIN
|
|
69
|
+
FROM ${this.keyTable} k
|
|
70
|
+
JOIN ${this.accountTable} sa ON sa.sa_id = k.sak_account_id
|
|
71
|
+
LEFT JOIN ${this.companyTable} c ON c.c_uuid = sa.sa_tenant_id
|
|
62
72
|
WHERE k.sak_account_id = ?
|
|
63
73
|
ORDER BY k.sak_version DESC
|
|
64
74
|
LIMIT 1`, [accountId]));
|
|
@@ -94,7 +104,7 @@ class MariaDbApiKeyStore {
|
|
|
94
104
|
* the natural key `(account, version)`.
|
|
95
105
|
*/
|
|
96
106
|
async putVersion(input) {
|
|
97
|
-
await this.pool.query(`INSERT INTO
|
|
107
|
+
await this.pool.query(`INSERT INTO ${this.keyTable}
|
|
98
108
|
(sak_account_id, sak_tenant_id, sak_scope_subtree, sak_role_ids,
|
|
99
109
|
sak_secret_hash, sak_version, sak_expires_at_ms, sak_revoked_at_ms, sak_created_at_ms)
|
|
100
110
|
VALUES (?, ?, ?, ?, ?, ?, ?, NULL, ?)`, [
|
|
@@ -110,12 +120,12 @@ class MariaDbApiKeyStore {
|
|
|
110
120
|
}
|
|
111
121
|
/** The current highest version for an account (0 if none) — for computing the next on rotate. */
|
|
112
122
|
async currentVersion(accountId) {
|
|
113
|
-
const rows = (await this.pool.query(`SELECT MAX(sak_version) AS v FROM
|
|
123
|
+
const rows = (await this.pool.query(`SELECT MAX(sak_version) AS v FROM ${this.keyTable} WHERE sak_account_id = ?`, [accountId]));
|
|
114
124
|
return rows[0]?.v != null ? Number(rows[0].v) : 0;
|
|
115
125
|
}
|
|
116
126
|
/** Revoke ALL of an account's keys (immediate fail-closed on the next request). Idempotent. */
|
|
117
127
|
async revoke(accountId, atMs) {
|
|
118
|
-
await this.pool.query(`UPDATE
|
|
128
|
+
await this.pool.query(`UPDATE ${this.keyTable}
|
|
119
129
|
SET sak_revoked_at_ms = ?
|
|
120
130
|
WHERE sak_account_id = ? AND sak_revoked_at_ms IS NULL`, [atMs, accountId]);
|
|
121
131
|
}
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
import type { Pool } from 'mariadb';
|
|
61
61
|
import type { CredentialResolver, ResolvedCredential } from '@astram/core';
|
|
62
62
|
import type { MfaDeviceStore } from '../auth/ports/mfa-device-store.js';
|
|
63
|
+
import { type FrameworkSchemaNames } from '../config/framework-schema-names.js';
|
|
63
64
|
/** DI token for the resolver — re-exported from the shared auth tokens module. */
|
|
64
65
|
export { SHIELD_CREDENTIAL_RESOLVER } from '../auth/tokens.js';
|
|
65
66
|
/**
|
|
@@ -83,6 +84,10 @@ export declare class MariaDbCredentialResolver implements CredentialResolver {
|
|
|
83
84
|
* installed or migrated while the process runs) is enforced without a restart.
|
|
84
85
|
*/
|
|
85
86
|
private usersTableMissingUntil;
|
|
87
|
+
/** `<identity>`.`identity_credential`. */
|
|
88
|
+
private readonly credentialTable;
|
|
89
|
+
/** `<app>`.`users` (the account status JOIN). */
|
|
90
|
+
private readonly usersTable;
|
|
86
91
|
constructor(pool: Pool,
|
|
87
92
|
/**
|
|
88
93
|
* The device store whose CONFIRMED keys become the login's `totp` required factor.
|
|
@@ -91,7 +96,9 @@ export declare class MariaDbCredentialResolver implements CredentialResolver {
|
|
|
91
96
|
*/
|
|
92
97
|
mfaDevices?: (Pick<MfaDeviceStore, "listConfirmedSecrets"> | null) | undefined,
|
|
93
98
|
/** Clock (epoch-ms) for the users-table re-probe window. */
|
|
94
|
-
now?: () => number
|
|
99
|
+
now?: () => number,
|
|
100
|
+
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
101
|
+
schemas?: FrameworkSchemaNames);
|
|
95
102
|
/**
|
|
96
103
|
* Resolve `identityHint` → {@link ResolvedCredential}, or `null` when no such
|
|
97
104
|
* principal exists.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-credential-resolver.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-credential-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAkB,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-credential-resolver.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-credential-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAkB,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAE7C,kFAAkF;AAClF,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AA6D/D;;;;GAIG;AACH,qBAAa,yBAA0B,YAAW,kBAAkB;IAchE,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAC5B,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,GAAG;IArBtB;;;;OAIG;IACH,OAAO,CAAC,sBAAsB,CAAK;IAEnC,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,iDAAiD;IACjD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAGjB,IAAI,EAAE,IAAI;IAC3B;;;;OAIG;IACc,UAAU,CAAC,GAAE,IAAI,CAAC,cAAc,EAAE,sBAAsB,CAAC,GAAG,IAAI,aAAA;IACjF,4DAA4D;IAC3C,GAAG,GAAE,MAAM,MAAiB;IAC7C,yFAAyF;IACzF,OAAO,CAAC,EAAE,oBAAoB;IAOhC;;;;;;;;;;;;;OAaG;IACG,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAoCvE;;;;;;OAMG;YACW,MAAM;IAyBpB;;;OAGG;YACW,kBAAkB;CAQjC"}
|
|
@@ -60,10 +60,11 @@
|
|
|
60
60
|
*/
|
|
61
61
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
62
62
|
exports.MariaDbCredentialResolver = exports.SHIELD_CREDENTIAL_RESOLVER = void 0;
|
|
63
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
63
64
|
/** DI token for the resolver — re-exported from the shared auth tokens module. */
|
|
64
65
|
var tokens_js_1 = require("../auth/tokens.js");
|
|
65
66
|
Object.defineProperty(exports, "SHIELD_CREDENTIAL_RESOLVER", { enumerable: true, get: function () { return tokens_js_1.SHIELD_CREDENTIAL_RESOLVER; } });
|
|
66
|
-
/** MariaDB `ER_NO_SUCH_TABLE`: the app keeps no
|
|
67
|
+
/** MariaDB `ER_NO_SUCH_TABLE`: the app keeps no `<app>.users` table. */
|
|
67
68
|
const ER_NO_SUCH_TABLE = 1146;
|
|
68
69
|
/** How long the credential-only fallback is used before the users JOIN is tried again. */
|
|
69
70
|
const USERS_TABLE_REPROBE_MS = 60_000;
|
|
@@ -113,6 +114,10 @@ class MariaDbCredentialResolver {
|
|
|
113
114
|
* installed or migrated while the process runs) is enforced without a restart.
|
|
114
115
|
*/
|
|
115
116
|
usersTableMissingUntil = 0;
|
|
117
|
+
/** `<identity>`.`identity_credential`. */
|
|
118
|
+
credentialTable;
|
|
119
|
+
/** `<app>`.`users` (the account status JOIN). */
|
|
120
|
+
usersTable;
|
|
116
121
|
constructor(pool,
|
|
117
122
|
/**
|
|
118
123
|
* The device store whose CONFIRMED keys become the login's `totp` required factor.
|
|
@@ -121,10 +126,15 @@ class MariaDbCredentialResolver {
|
|
|
121
126
|
*/
|
|
122
127
|
mfaDevices,
|
|
123
128
|
/** Clock (epoch-ms) for the users-table re-probe window. */
|
|
124
|
-
now = Date.now
|
|
129
|
+
now = Date.now,
|
|
130
|
+
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
131
|
+
schemas) {
|
|
125
132
|
this.pool = pool;
|
|
126
133
|
this.mfaDevices = mfaDevices;
|
|
127
134
|
this.now = now;
|
|
135
|
+
const s = (0, framework_schema_names_js_1.schemaNamesAtConstruction)(schemas);
|
|
136
|
+
this.credentialTable = (0, framework_schema_names_js_1.qualifiedTableName)(s.identity, 'identity_credential');
|
|
137
|
+
this.usersTable = (0, framework_schema_names_js_1.qualifiedTableName)(s.app, 'users');
|
|
128
138
|
}
|
|
129
139
|
/**
|
|
130
140
|
* Resolve `identityHint` → {@link ResolvedCredential}, or `null` when no such
|
|
@@ -182,8 +192,8 @@ class MariaDbCredentialResolver {
|
|
|
182
192
|
if (this.now() >= this.usersTableMissingUntil) {
|
|
183
193
|
try {
|
|
184
194
|
return (await this.pool.query(`SELECT ic_password_hash, ic_principal_id, ic_tenant_id, ic_roles, u.u_status
|
|
185
|
-
FROM
|
|
186
|
-
LEFT JOIN
|
|
195
|
+
FROM ${this.credentialTable}
|
|
196
|
+
LEFT JOIN ${this.usersTable} u ON u.u_uuid = ic_principal_id
|
|
187
197
|
WHERE ic_identity_hint = ?
|
|
188
198
|
LIMIT 1`, [identityHint]));
|
|
189
199
|
}
|
|
@@ -194,7 +204,7 @@ class MariaDbCredentialResolver {
|
|
|
194
204
|
}
|
|
195
205
|
}
|
|
196
206
|
return (await this.pool.query(`SELECT ic_password_hash, ic_principal_id, ic_tenant_id, ic_roles
|
|
197
|
-
FROM
|
|
207
|
+
FROM ${this.credentialTable}
|
|
198
208
|
WHERE ic_identity_hint = ?
|
|
199
209
|
LIMIT 1`, [identityHint]));
|
|
200
210
|
}
|
|
@@ -6,10 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Pool } from 'mariadb';
|
|
8
8
|
import type { CredentialWriter } from '../auth/ports/credential-writer.js';
|
|
9
|
+
import { type FrameworkSchemaNames } from '../config/framework-schema-names.js';
|
|
9
10
|
export declare class MariaDbCredentialWriter implements CredentialWriter {
|
|
10
11
|
private readonly pool;
|
|
11
12
|
private readonly now;
|
|
12
|
-
|
|
13
|
+
/** `<identity>`.`identity_credential`, resolved at construction. */
|
|
14
|
+
private readonly table;
|
|
15
|
+
constructor(pool: Pool, now?: () => number,
|
|
16
|
+
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
17
|
+
schemas?: FrameworkSchemaNames);
|
|
13
18
|
setPassword(principalId: string, passwordHash: string): Promise<void>;
|
|
14
19
|
getPasswordHash(principalId: string): Promise<string | null>;
|
|
15
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-credential-writer.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-credential-writer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-credential-writer.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-credential-writer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAM7C,qBAAa,uBAAwB,YAAW,gBAAgB;IAK5D,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IALtB,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAGZ,IAAI,EAAE,IAAI,EACV,GAAG,GAAE,MAAM,MAAiB;IAC7C,yFAAyF;IACzF,OAAO,CAAC,EAAE,oBAAoB;IAQ1B,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrE,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAOnE"}
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MariaDbCredentialWriter = void 0;
|
|
4
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
4
5
|
class MariaDbCredentialWriter {
|
|
5
6
|
pool;
|
|
6
7
|
now;
|
|
7
|
-
|
|
8
|
+
/** `<identity>`.`identity_credential`, resolved at construction. */
|
|
9
|
+
table;
|
|
10
|
+
constructor(pool, now = Date.now,
|
|
11
|
+
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
12
|
+
schemas) {
|
|
8
13
|
this.pool = pool;
|
|
9
14
|
this.now = now;
|
|
15
|
+
this.table = (0, framework_schema_names_js_1.qualifiedTableName)((0, framework_schema_names_js_1.schemaNamesAtConstruction)(schemas).identity, 'identity_credential');
|
|
10
16
|
}
|
|
11
17
|
async setPassword(principalId, passwordHash) {
|
|
12
|
-
await this.pool.query(
|
|
18
|
+
await this.pool.query(`UPDATE ${this.table} SET ic_password_hash = ?, ic_updated_at_ms = ? WHERE ic_principal_id = ?`, [passwordHash, this.now(), principalId]);
|
|
13
19
|
}
|
|
14
20
|
async getPasswordHash(principalId) {
|
|
15
|
-
const rows = (await this.pool.query(
|
|
21
|
+
const rows = (await this.pool.query(`SELECT ic_password_hash FROM ${this.table} WHERE ic_principal_id = ? LIMIT 1`, [principalId]));
|
|
16
22
|
return rows[0]?.ic_password_hash ?? null;
|
|
17
23
|
}
|
|
18
24
|
}
|
|
@@ -29,10 +29,19 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import type { Pool } from 'mariadb';
|
|
31
31
|
import type { CurrentEmail, EmailAddressChanger, EmailChangeOutcome, EmailChangeRequest } from '../auth/ports/email-address-changer.js';
|
|
32
|
+
import { type FrameworkSchemaNames } from '../config/framework-schema-names.js';
|
|
32
33
|
export declare class MariaDbEmailAddressChanger implements EmailAddressChanger {
|
|
33
34
|
private readonly pool;
|
|
34
35
|
private readonly now;
|
|
35
|
-
|
|
36
|
+
/** `<app>`.`users`. */
|
|
37
|
+
private readonly usersTable;
|
|
38
|
+
/** `<identity>`.`identity_credential`. */
|
|
39
|
+
private readonly credentialTable;
|
|
40
|
+
/** `<identity>`.`email_change_token`. */
|
|
41
|
+
private readonly tokenTable;
|
|
42
|
+
constructor(pool: Pool, now?: () => number,
|
|
43
|
+
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
44
|
+
schemas?: FrameworkSchemaNames);
|
|
36
45
|
readCurrent(principalId: string, candidate: string): Promise<CurrentEmail | null>;
|
|
37
46
|
change(request: EmailChangeRequest): Promise<EmailChangeOutcome>;
|
|
38
47
|
private changeLocked;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-email-address-changer.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-email-address-changer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,IAAI,EAAkB,MAAM,SAAS,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-email-address-changer.d.ts","sourceRoot":"","sources":["../../src/authentication/mariadb-email-address-changer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,IAAI,EAAkB,MAAM,SAAS,CAAC;AACpD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAqB7C,qBAAa,0BAA2B,YAAW,mBAAmB;IASlE,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IATtB,uBAAuB;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAGjB,IAAI,EAAE,IAAI,EACV,GAAG,GAAE,MAAM,MAAiB;IAC7C,yFAAyF;IACzF,OAAO,CAAC,EAAE,oBAAoB;IAQ1B,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAejF,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YA6BxD,YAAY;CAqE3B"}
|