@spinajs/authn-orm 3.0.3 → 3.0.4
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/lib/cjs/audit/index.d.ts +1 -0
- package/lib/cjs/audit/index.d.ts.map +1 -1
- package/lib/cjs/audit/index.js +3 -1
- package/lib/cjs/audit/index.js.map +1 -1
- package/lib/cjs/audit/retention.d.ts +21 -0
- package/lib/cjs/audit/retention.d.ts.map +1 -0
- package/lib/cjs/audit/retention.js +105 -0
- package/lib/cjs/audit/retention.js.map +1 -0
- package/lib/cjs/cli/PurgeAudit.d.ts +10 -0
- package/lib/cjs/cli/PurgeAudit.d.ts.map +1 -0
- package/lib/cjs/cli/PurgeAudit.js +46 -0
- package/lib/cjs/cli/PurgeAudit.js.map +1 -0
- package/lib/cjs/config/authn-orm.d.ts +9 -0
- package/lib/cjs/config/authn-orm.d.ts.map +1 -0
- package/lib/cjs/config/authn-orm.js +21 -0
- package/lib/cjs/config/authn-orm.js.map +1 -0
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/mfa/db-mfa-enrolment-marks.d.ts +16 -0
- package/lib/cjs/mfa/db-mfa-enrolment-marks.d.ts.map +1 -0
- package/lib/cjs/mfa/db-mfa-enrolment-marks.js +54 -0
- package/lib/cjs/mfa/db-mfa-enrolment-marks.js.map +1 -0
- package/lib/cjs/mfa/index.d.ts +1 -0
- package/lib/cjs/mfa/index.d.ts.map +1 -1
- package/lib/cjs/mfa/index.js +1 -0
- package/lib/cjs/mfa/index.js.map +1 -1
- package/lib/cjs/secrets/db-secret-store.d.ts +2 -2
- package/lib/cjs/secrets/db-secret-store.d.ts.map +1 -1
- package/lib/cjs/secrets/db-secret-store.js +5 -3
- package/lib/cjs/secrets/db-secret-store.js.map +1 -1
- package/lib/cjs/throttle/db-throttle-store.d.ts +8 -1
- package/lib/cjs/throttle/db-throttle-store.d.ts.map +1 -1
- package/lib/cjs/throttle/db-throttle-store.js +20 -10
- package/lib/cjs/throttle/db-throttle-store.js.map +1 -1
- package/lib/cjs/throttle/db-throttle.js +1 -1
- package/lib/cjs/throttle/db-throttle.js.map +1 -1
- package/lib/mjs/audit/index.d.ts +1 -0
- package/lib/mjs/audit/index.d.ts.map +1 -1
- package/lib/mjs/audit/index.js +1 -0
- package/lib/mjs/audit/index.js.map +1 -1
- package/lib/mjs/audit/retention.d.ts +21 -0
- package/lib/mjs/audit/retention.d.ts.map +1 -0
- package/lib/mjs/audit/retention.js +102 -0
- package/lib/mjs/audit/retention.js.map +1 -0
- package/lib/mjs/cli/PurgeAudit.d.ts +10 -0
- package/lib/mjs/cli/PurgeAudit.d.ts.map +1 -0
- package/lib/mjs/cli/PurgeAudit.js +43 -0
- package/lib/mjs/cli/PurgeAudit.js.map +1 -0
- package/lib/mjs/config/authn-orm.d.ts +9 -0
- package/lib/mjs/config/authn-orm.d.ts.map +1 -0
- package/lib/mjs/config/authn-orm.js +19 -0
- package/lib/mjs/config/authn-orm.js.map +1 -0
- package/lib/mjs/index.d.ts +1 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +1 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/mfa/db-mfa-enrolment-marks.d.ts +16 -0
- package/lib/mjs/mfa/db-mfa-enrolment-marks.d.ts.map +1 -0
- package/lib/mjs/mfa/db-mfa-enrolment-marks.js +51 -0
- package/lib/mjs/mfa/db-mfa-enrolment-marks.js.map +1 -0
- package/lib/mjs/mfa/index.d.ts +1 -0
- package/lib/mjs/mfa/index.d.ts.map +1 -1
- package/lib/mjs/mfa/index.js +1 -0
- package/lib/mjs/mfa/index.js.map +1 -1
- package/lib/mjs/secrets/db-secret-store.d.ts +2 -2
- package/lib/mjs/secrets/db-secret-store.d.ts.map +1 -1
- package/lib/mjs/secrets/db-secret-store.js +5 -3
- package/lib/mjs/secrets/db-secret-store.js.map +1 -1
- package/lib/mjs/throttle/db-throttle-store.d.ts +8 -1
- package/lib/mjs/throttle/db-throttle-store.d.ts.map +1 -1
- package/lib/mjs/throttle/db-throttle-store.js +20 -10
- package/lib/mjs/throttle/db-throttle-store.js.map +1 -1
- package/lib/mjs/throttle/db-throttle.js +1 -1
- package/lib/mjs/throttle/db-throttle.js.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +14 -13
package/lib/cjs/audit/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/lib/cjs/audit/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DbAuthnAuditSink = void 0;
|
|
3
|
+
exports.AuthnAuditRetention = exports.DbAuthnAuditSink = void 0;
|
|
4
4
|
var db_audit_sink_js_1 = require("./db-audit-sink.js");
|
|
5
5
|
Object.defineProperty(exports, "DbAuthnAuditSink", { enumerable: true, get: function () { return db_audit_sink_js_1.DbAuthnAuditSink; } });
|
|
6
|
+
var retention_js_1 = require("./retention.js");
|
|
7
|
+
Object.defineProperty(exports, "AuthnAuditRetention", { enumerable: true, get: function () { return retention_js_1.AuthnAuditRetention; } });
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/audit/index.ts"],"names":[],"mappings":";;;AAAA,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/audit/index.ts"],"names":[],"mappings":";;;AAAA,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,+CAAqD;AAA5C,mHAAA,mBAAmB,OAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import '@spinajs/authn/register-schema';
|
|
2
|
+
import { AsyncService } from '@spinajs/di';
|
|
3
|
+
import { Log } from '@spinajs/log';
|
|
4
|
+
/**
|
|
5
|
+
* Deletes `authn_audit` rows older than `authn.audit.retentionDays`, in batches, on `purge` and, when
|
|
6
|
+
* `authn.audit.purgeInterval` (ms) is set, on a timer. Both keys are unset by default: audit rows are kept forever.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AuthnAuditRetention extends AsyncService {
|
|
9
|
+
protected RetentionDays: number | null | undefined;
|
|
10
|
+
protected PurgeInterval: number | null | undefined;
|
|
11
|
+
protected Log: Log;
|
|
12
|
+
private timer;
|
|
13
|
+
private running;
|
|
14
|
+
get Enabled(): boolean;
|
|
15
|
+
resolve(): Promise<void>;
|
|
16
|
+
dispose(): Promise<void>;
|
|
17
|
+
/** Deletes the rows older than the retention; returns how many went. 0 while `retentionDays` is unset. */
|
|
18
|
+
purge(now?: Date): Promise<number>;
|
|
19
|
+
private tick;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=retention.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../../src/audit/retention.ts"],"names":[],"mappings":"AAAA,OAAO,gCAAgC,CAAC;AACxC,OAAO,EAAE,YAAY,EAAgC,MAAM,aAAa,CAAC;AAEzE,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAS3C;;;GAGG;AACH,qBAEa,mBAAoB,SAAQ,YAAY;IAEnD,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAGnD,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAGnD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEnB,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,OAAO,CAAS;IAExB,IAAW,OAAO,IAAI,OAAO,CAE5B;IAEY,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAOpC;IAEY,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAGpC;IAED,0GAA0G;IAC7F,KAAK,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyB1D;YAEa,IAAI;CAkBnB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AuthnAuditRetention = void 0;
|
|
13
|
+
require("@spinajs/authn/register-schema");
|
|
14
|
+
const di_1 = require("@spinajs/di");
|
|
15
|
+
const configuration_1 = require("@spinajs/configuration");
|
|
16
|
+
const log_1 = require("@spinajs/log");
|
|
17
|
+
const orm_1 = require("@spinajs/orm");
|
|
18
|
+
const AuthnAudit_js_1 = require("../models/AuthnAudit.js");
|
|
19
|
+
const sql_js_1 = require("../support/sql.js");
|
|
20
|
+
const DAY_MS = 86_400_000;
|
|
21
|
+
const PURGE_BATCH = 500;
|
|
22
|
+
/**
|
|
23
|
+
* Deletes `authn_audit` rows older than `authn.audit.retentionDays`, in batches, on `purge` and, when
|
|
24
|
+
* `authn.audit.purgeInterval` (ms) is set, on a timer. Both keys are unset by default: audit rows are kept forever.
|
|
25
|
+
*/
|
|
26
|
+
let AuthnAuditRetention = class AuthnAuditRetention extends di_1.AsyncService {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
29
|
+
this.running = false;
|
|
30
|
+
}
|
|
31
|
+
get Enabled() {
|
|
32
|
+
return typeof this.RetentionDays === 'number' && this.RetentionDays > 0;
|
|
33
|
+
}
|
|
34
|
+
async resolve() {
|
|
35
|
+
if (!this.Enabled || !this.PurgeInterval || this.PurgeInterval < 1) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.timer = setInterval(() => void this.tick(), this.PurgeInterval);
|
|
39
|
+
this.timer.unref?.();
|
|
40
|
+
}
|
|
41
|
+
async dispose() {
|
|
42
|
+
clearInterval(this.timer);
|
|
43
|
+
this.timer = undefined;
|
|
44
|
+
}
|
|
45
|
+
/** Deletes the rows older than the retention; returns how many went. 0 while `retentionDays` is unset. */
|
|
46
|
+
async purge(now = new Date()) {
|
|
47
|
+
const days = this.RetentionDays;
|
|
48
|
+
if (typeof days !== 'number' || !(days > 0)) {
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
const cutoff = (0, sql_js_1.instant)((0, sql_js_1.checkedMs)(now, 'AuthnAuditRetention.purge: now') - days * DAY_MS);
|
|
52
|
+
await (0, orm_1.ormReady)();
|
|
53
|
+
let removed = 0;
|
|
54
|
+
for (;;) {
|
|
55
|
+
// MSSQL pages with OFFSET ... FETCH, which needs an ORDER BY.
|
|
56
|
+
const ids = (await AuthnAudit_js_1.AuthnAudit.query().columns(['id']).where('at', '<', cutoff).orderBy('at').take(PURGE_BATCH)).map((r) => r.id);
|
|
57
|
+
if (ids.length === 0) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
const deleted = (await AuthnAudit_js_1.AuthnAudit.destroy().whereIn('id', ids).where('at', '<', cutoff)).RowsAffected;
|
|
61
|
+
removed += deleted;
|
|
62
|
+
if (ids.length < PURGE_BATCH || deleted === 0) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return removed;
|
|
67
|
+
}
|
|
68
|
+
async tick() {
|
|
69
|
+
if (this.running) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.running = true;
|
|
73
|
+
try {
|
|
74
|
+
const count = await this.purge();
|
|
75
|
+
if (count > 0) {
|
|
76
|
+
this.Log.info({ count }, 'Purged audit rows past retention, count: ${count}');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
// An unhandled rejection here would end the process; the next tick retries.
|
|
81
|
+
this.Log.error(err, 'Audit retention purge failed');
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
this.running = false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
exports.AuthnAuditRetention = AuthnAuditRetention;
|
|
89
|
+
__decorate([
|
|
90
|
+
(0, configuration_1.Config)('authn.audit.retentionDays'),
|
|
91
|
+
__metadata("design:type", Object)
|
|
92
|
+
], AuthnAuditRetention.prototype, "RetentionDays", void 0);
|
|
93
|
+
__decorate([
|
|
94
|
+
(0, configuration_1.Config)('authn.audit.purgeInterval'),
|
|
95
|
+
__metadata("design:type", Object)
|
|
96
|
+
], AuthnAuditRetention.prototype, "PurgeInterval", void 0);
|
|
97
|
+
__decorate([
|
|
98
|
+
(0, log_1.Logger)('authn-orm'),
|
|
99
|
+
__metadata("design:type", log_1.Log)
|
|
100
|
+
], AuthnAuditRetention.prototype, "Log", void 0);
|
|
101
|
+
exports.AuthnAuditRetention = AuthnAuditRetention = __decorate([
|
|
102
|
+
(0, di_1.PerChildInstance)(),
|
|
103
|
+
(0, di_1.Injectable)()
|
|
104
|
+
], AuthnAuditRetention);
|
|
105
|
+
//# sourceMappingURL=retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../../src/audit/retention.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CliCommand } from '@spinajs/cli';
|
|
2
|
+
import { Log } from '@spinajs/log';
|
|
3
|
+
import { AuthnAuditRetention } from '../audit/retention.js';
|
|
4
|
+
/** Housekeeping for a scheduler (cron, worker); a no-op while `authn.audit.retentionDays` is unset. */
|
|
5
|
+
export declare class PurgeAudit extends CliCommand {
|
|
6
|
+
protected Log: Log;
|
|
7
|
+
protected Retention: AuthnAuditRetention;
|
|
8
|
+
execute(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=PurgeAudit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PurgeAudit.d.ts","sourceRoot":"","sources":["../../../src/cli/PurgeAudit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAW,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,uGAAuG;AACvG,qBACa,UAAW,SAAQ,UAAU;IAExC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,SAAS,EAAE,mBAAmB,CAAC;IAE5B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAapC;CACF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PurgeAudit = void 0;
|
|
13
|
+
const di_1 = require("@spinajs/di");
|
|
14
|
+
const cli_1 = require("@spinajs/cli");
|
|
15
|
+
const log_1 = require("@spinajs/log");
|
|
16
|
+
const retention_js_1 = require("../audit/retention.js");
|
|
17
|
+
/** Housekeeping for a scheduler (cron, worker); a no-op while `authn.audit.retentionDays` is unset. */
|
|
18
|
+
let PurgeAudit = class PurgeAudit extends cli_1.CliCommand {
|
|
19
|
+
async execute() {
|
|
20
|
+
try {
|
|
21
|
+
if (!this.Retention.Enabled) {
|
|
22
|
+
this.Log.warn('authn.audit.retentionDays is not set, no audit rows were purged');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const count = await this.Retention.purge();
|
|
26
|
+
this.Log.success({ count }, 'Deleted ${count} audit row(s) past retention');
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
this.Log.error({ error: e }, 'Error while purging audit rows');
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.PurgeAudit = PurgeAudit;
|
|
35
|
+
__decorate([
|
|
36
|
+
(0, log_1.Logger)('authn-orm'),
|
|
37
|
+
__metadata("design:type", log_1.Log)
|
|
38
|
+
], PurgeAudit.prototype, "Log", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, di_1.Autoinject)(retention_js_1.AuthnAuditRetention),
|
|
41
|
+
__metadata("design:type", retention_js_1.AuthnAuditRetention)
|
|
42
|
+
], PurgeAudit.prototype, "Retention", void 0);
|
|
43
|
+
exports.PurgeAudit = PurgeAudit = __decorate([
|
|
44
|
+
(0, cli_1.Command)('authn:audit-purge', 'Deletes audit rows older than authn.audit.retentionDays')
|
|
45
|
+
], PurgeAudit);
|
|
46
|
+
//# sourceMappingURL=PurgeAudit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PurgeAudit.js","sourceRoot":"","sources":["../../../src/cli/PurgeAudit.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oCAAyC;AACzC,sCAAmD;AACnD,sCAA2C;AAE3C,wDAA4D;AAE5D,uGAAuG;AAEhG,IAAM,UAAU,GAAhB,MAAM,UAAW,SAAQ,gBAAU;IAOjC,KAAK,CAAC,OAAO;QAClB,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;gBACjF,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YAC3C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,8CAA8C,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,gCAAgC,CAAC,CAAC;YAC/D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;CACF,CAAA;;AAnBW;IADT,IAAA,YAAM,EAAC,WAAW,CAAC;8BACL,SAAG;uCAAC;AAGT;IADT,IAAA,eAAU,EAAC,kCAAmB,CAAC;8BACX,kCAAmB;6CAAC;qBAL9B,UAAU;IADtB,IAAA,aAAO,EAAC,mBAAmB,EAAE,yDAAyD,CAAC;GAC3E,UAAU,CAqBtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authn-orm.d.ts","sourceRoot":"","sources":["../../../src/config/authn-orm.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,QAAQ;IACZ,MAAM;QACJ,IAAI;YAEF,GAAG;;;CAGR,CAAC;eAEa,QAAQ"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const path_1 = require("path");
|
|
4
|
+
function dir(path) {
|
|
5
|
+
const inCommonJs = typeof module !== 'undefined';
|
|
6
|
+
return [
|
|
7
|
+
(0, path_1.resolve)((0, path_1.normalize)((0, path_1.join)(process.env.WORKSPACE_ROOT_PATH ?? process.cwd(), 'node_modules', '@spinajs', 'authn-orm', 'lib', inCommonJs ? 'cjs' : 'mjs', path))),
|
|
8
|
+
// one up if we run from app or build folder
|
|
9
|
+
(0, path_1.resolve)((0, path_1.normalize)((0, path_1.join)(process.env.WORKSPACE_ROOT_PATH ?? process.cwd(), '../', 'node_modules', '@spinajs', 'authn-orm', 'lib', inCommonJs ? 'cjs' : 'mjs', path))),
|
|
10
|
+
];
|
|
11
|
+
}
|
|
12
|
+
const authnOrm = {
|
|
13
|
+
system: {
|
|
14
|
+
dirs: {
|
|
15
|
+
// CLI commands are found by a filesystem scan, so without this entry `authn:audit-purge` is unreachable in a consuming app.
|
|
16
|
+
cli: [...dir('cli')],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
exports.default = authnOrm;
|
|
21
|
+
//# sourceMappingURL=authn-orm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authn-orm.js","sourceRoot":"","sources":["../../../src/config/authn-orm.ts"],"names":[],"mappings":";;AAAA,+BAAgD;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IACjD,OAAO;QACL,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QAE5J,4CAA4C;QAC5C,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;KACpK,CAAC;AACJ,CAAC;AAED,MAAM,QAAQ,GAAG;IACf,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,4HAA4H;YAC5H,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;SACrB;KACF;CACF,CAAC;kBAEa,QAAQ"}
|
package/lib/cjs/index.d.ts
CHANGED
package/lib/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
|
package/lib/cjs/index.js
CHANGED
|
@@ -23,4 +23,5 @@ __exportStar(require("./links/index.js"), exports);
|
|
|
23
23
|
__exportStar(require("./nonces/index.js"), exports);
|
|
24
24
|
__exportStar(require("./mfa/index.js"), exports);
|
|
25
25
|
__exportStar(require("./audit/index.js"), exports);
|
|
26
|
+
__exportStar(require("./cli/PurgeAudit.js"), exports);
|
|
26
27
|
//# sourceMappingURL=index.js.map
|
package/lib/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,oDAAkC;AAClC,gDAA8B;AAC9B,sDAAoC;AACpC,qDAAmC;AACnC,mDAAiC;AACjC,oDAAkC;AAClC,iDAA+B;AAC/B,mDAAiC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,oDAAkC;AAClC,gDAA8B;AAC9B,sDAAoC;AACpC,qDAAmC;AACnC,mDAAiC;AACjC,oDAAkC;AAClC,iDAA+B;AAC/B,mDAAiC;AACjC,sDAAoC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IdentityRef } from '@spinajs/authn/contracts';
|
|
2
|
+
import { MfaEnrolmentMarks } from '@spinajs/authn/contracts';
|
|
3
|
+
import { DbMfaStore } from './db-mfa-store.js';
|
|
4
|
+
/** Enrolment marks of steps without a secret of their own, as confirmed `authn_mfa` rows. */
|
|
5
|
+
export declare class DbMfaEnrolmentMarks extends MfaEnrolmentMarks {
|
|
6
|
+
protected readonly db?: DbMfaStore | undefined;
|
|
7
|
+
protected DbMfaStore: DbMfaStore;
|
|
8
|
+
/** DI passes nothing and injects `DbMfaStore`. */
|
|
9
|
+
constructor(db?: DbMfaStore | undefined);
|
|
10
|
+
has(id: IdentityRef, step: string): Promise<boolean>;
|
|
11
|
+
/** True for exactly the call that confirmed the row; false when the identity is marked already. */
|
|
12
|
+
mark(id: IdentityRef, step: string): Promise<boolean>;
|
|
13
|
+
unmark(id: IdentityRef, step: string): Promise<void>;
|
|
14
|
+
private store;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=db-mfa-enrolment-marks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-mfa-enrolment-marks.d.ts","sourceRoot":"","sources":["../../../src/mfa/db-mfa-enrolment-marks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM/C,6FAA6F;AAC7F,qBAEa,mBAAoB,SAAQ,iBAAiB;IAK5C,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,UAAU;IAH9C,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC;IAEjC,kDAAkD;IAClD,YAA+B,EAAE,CAAC,EAAE,UAAU,YAAA,EAE7C;IAEY,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGhE;IAED,mGAAmG;IACtF,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIjE;IAEY,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhE;IAED,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DbMfaEnrolmentMarks = void 0;
|
|
13
|
+
const contracts_1 = require("@spinajs/authn/contracts");
|
|
14
|
+
const di_1 = require("@spinajs/di");
|
|
15
|
+
const db_mfa_store_js_1 = require("./db-mfa-store.js");
|
|
16
|
+
/** What the row holds in place of a secret: the store keeps cipher text, and a mark has nothing to hide. */
|
|
17
|
+
const MARK_SECRET = 'mark';
|
|
18
|
+
const MARK_KEY = 'none';
|
|
19
|
+
/** Enrolment marks of steps without a secret of their own, as confirmed `authn_mfa` rows. */
|
|
20
|
+
let DbMfaEnrolmentMarks = class DbMfaEnrolmentMarks extends contracts_1.MfaEnrolmentMarks {
|
|
21
|
+
/** DI passes nothing and injects `DbMfaStore`. */
|
|
22
|
+
constructor(db) {
|
|
23
|
+
super();
|
|
24
|
+
this.db = db;
|
|
25
|
+
}
|
|
26
|
+
async has(id, step) {
|
|
27
|
+
const row = await this.store().get(id, step);
|
|
28
|
+
return row !== null && row.confirmedAt !== null;
|
|
29
|
+
}
|
|
30
|
+
/** True for exactly the call that confirmed the row; false when the identity is marked already. */
|
|
31
|
+
async mark(id, step) {
|
|
32
|
+
const store = this.store();
|
|
33
|
+
if (!(await store.putPending(id, step, MARK_SECRET, MARK_KEY)))
|
|
34
|
+
return false;
|
|
35
|
+
return store.confirm(id, step, new Date(), MARK_SECRET);
|
|
36
|
+
}
|
|
37
|
+
async unmark(id, step) {
|
|
38
|
+
await this.store().remove(id, step);
|
|
39
|
+
}
|
|
40
|
+
store() {
|
|
41
|
+
return this.db ?? this.DbMfaStore;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
exports.DbMfaEnrolmentMarks = DbMfaEnrolmentMarks;
|
|
45
|
+
__decorate([
|
|
46
|
+
(0, di_1.Autoinject)(db_mfa_store_js_1.DbMfaStore),
|
|
47
|
+
__metadata("design:type", db_mfa_store_js_1.DbMfaStore)
|
|
48
|
+
], DbMfaEnrolmentMarks.prototype, "DbMfaStore", void 0);
|
|
49
|
+
exports.DbMfaEnrolmentMarks = DbMfaEnrolmentMarks = __decorate([
|
|
50
|
+
(0, di_1.PerChildInstance)(),
|
|
51
|
+
(0, di_1.Injectable)(contracts_1.MfaEnrolmentMarks),
|
|
52
|
+
__metadata("design:paramtypes", [db_mfa_store_js_1.DbMfaStore])
|
|
53
|
+
], DbMfaEnrolmentMarks);
|
|
54
|
+
//# sourceMappingURL=db-mfa-enrolment-marks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-mfa-enrolment-marks.js","sourceRoot":"","sources":["../../../src/mfa/db-mfa-enrolment-marks.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,wDAA6D;AAC7D,oCAAuE;AAEvE,uDAA+C;AAE/C,4GAA4G;AAC5G,MAAM,WAAW,GAAG,MAAM,CAAC;AAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC;AAExB,6FAA6F;AAGtF,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,6BAAiB;IAIxD,kDAAkD;IAClD,YAA+B,EAAe;QAC5C,KAAK,EAAE,CAAC;kBADqB,EAAE;IAEjC,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,EAAe,EAAE,IAAY;QAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7C,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC;IAClD,CAAC;IAED,mGAAmG;IAC5F,KAAK,CAAC,IAAI,CAAC,EAAe,EAAE,IAAY;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7E,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1D,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,EAAe,EAAE,IAAY;QAC/C,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAEO,KAAK;QACX,OAAO,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC;IACpC,CAAC;CACF,CAAA;;AA1BW;IADT,IAAA,eAAU,EAAC,4BAAU,CAAC;8BACD,4BAAU;uDAAC;8BAFtB,mBAAmB;IAF/B,IAAA,qBAAgB,GAAE;IAClB,IAAA,eAAU,EAAC,6BAAiB,CAAC;qCAMQ,4BAAU;GALnC,mBAAmB,CA4B/B"}
|
package/lib/cjs/mfa/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mfa/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mfa/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,aAAa,CAAC"}
|
package/lib/cjs/mfa/index.js
CHANGED
|
@@ -16,5 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./db-mfa-store.js"), exports);
|
|
18
18
|
__exportStar(require("./db-mfa-enrolments.js"), exports);
|
|
19
|
+
__exportStar(require("./db-mfa-enrolment-marks.js"), exports);
|
|
19
20
|
__exportStar(require("./cipher.js"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
package/lib/cjs/mfa/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mfa/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,yDAAuC;AACvC,8CAA4B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mfa/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,yDAAuC;AACvC,8DAA4C;AAC5C,8CAA4B"}
|
|
@@ -3,14 +3,14 @@ import type { IdentityRef } from '@spinajs/authn/contracts';
|
|
|
3
3
|
import type { DateTime } from 'luxon';
|
|
4
4
|
/**
|
|
5
5
|
* `authn_secret`: single-use secrets stored as the hex SHA-256 of the raw value only (SR-09). The raw secret is
|
|
6
|
-
* 32 random bytes as base64url (43 chars). Times are taken in Node at call time (F7); the claim of `redeem`
|
|
6
|
+
* 32 random bytes as base64url (43 chars), or the `value` the caller gives (a short code). Times are taken in Node at call time (F7); the claim of `redeem`
|
|
7
7
|
* decides expiry and single use in SQL against that time (D10).
|
|
8
8
|
*
|
|
9
9
|
* Two parallel `issue` calls for one identity and purpose may both leave a live row: each deletes, then inserts.
|
|
10
10
|
*/
|
|
11
11
|
export declare class DbSecretStore extends SecretStore {
|
|
12
12
|
private readonly purgeDue;
|
|
13
|
-
issue(identity: IdentityRef, purpose: string, ttlSeconds: number): Promise<string>;
|
|
13
|
+
issue(identity: IdentityRef, purpose: string, ttlSeconds: number, value?: string): Promise<string>;
|
|
14
14
|
/**
|
|
15
15
|
* Looks the row up by the hash of `raw`, so no stored value is compared with the input in Node. The lookup
|
|
16
16
|
* also matches identity and purpose; the claim succeeds for exactly one caller.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-secret-store.d.ts","sourceRoot":"","sources":["../../../src/secrets/db-secret-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAK5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAatC;;;;;;GAMG;AACH,qBAEa,aAAc,SAAQ,WAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IAEzC,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"db-secret-store.d.ts","sourceRoot":"","sources":["../../../src/secrets/db-secret-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAK5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAatC;;;;;;GAMG;AACH,qBAEa,aAAc,SAAQ,WAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IAEzC,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa9G;IAED;;;OAGG;IACU,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBzF;IAED,gFAAgF;IACnE,KAAK,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAW1D;IAED,mEAAmE;IACnE,SAAS,CAAC,UAAU,CAAC,SAAS,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnF;YAEa,eAAe;CAK9B"}
|
|
@@ -23,7 +23,7 @@ const PURGE_BATCH = 500;
|
|
|
23
23
|
const RAW_MAX = 1024;
|
|
24
24
|
/**
|
|
25
25
|
* `authn_secret`: single-use secrets stored as the hex SHA-256 of the raw value only (SR-09). The raw secret is
|
|
26
|
-
* 32 random bytes as base64url (43 chars). Times are taken in Node at call time (F7); the claim of `redeem`
|
|
26
|
+
* 32 random bytes as base64url (43 chars), or the `value` the caller gives (a short code). Times are taken in Node at call time (F7); the claim of `redeem`
|
|
27
27
|
* decides expiry and single use in SQL against that time (D10).
|
|
28
28
|
*
|
|
29
29
|
* Two parallel `issue` calls for one identity and purpose may both leave a live row: each deletes, then inserts.
|
|
@@ -33,14 +33,16 @@ let DbSecretStore = class DbSecretStore extends contracts_1.SecretStore {
|
|
|
33
33
|
super(...arguments);
|
|
34
34
|
this.purgeDue = (0, orm_1.everyNthCall)(PURGE_EVERY);
|
|
35
35
|
}
|
|
36
|
-
async issue(identity, purpose, ttlSeconds) {
|
|
36
|
+
async issue(identity, purpose, ttlSeconds, value) {
|
|
37
37
|
const key = (0, identity_js_1.identityKey)(identity);
|
|
38
38
|
(0, sql_js_1.checkedText)(purpose, PURPOSE_MAX, 'DbSecretStore: purpose');
|
|
39
39
|
(0, util_1._check_arg)((0, util_1._is_number)((0, util_1._finite)(), (0, util_1._gt)(0)))(ttlSeconds, 'ttlSeconds');
|
|
40
|
+
if (value !== undefined)
|
|
41
|
+
(0, util_1._check_arg)((0, util_1._is_string)((0, util_1._non_empty)(), (0, util_1._max_length)(RAW_MAX)))(value, 'value');
|
|
40
42
|
const nowMs = (0, sql_js_1.checkedMs)(new Date(), 'DbSecretStore.issue: the clock');
|
|
41
43
|
await (0, orm_1.ormReady)();
|
|
42
44
|
await this.purgeNowAndThen(nowMs);
|
|
43
|
-
const raw = (0, node_crypto_1.randomBytes)(32).toString('base64url');
|
|
45
|
+
const raw = value ?? (0, node_crypto_1.randomBytes)(32).toString('base64url');
|
|
44
46
|
await AuthnSecret_js_1.AuthnSecret.destroy().where('identity', key).where('purpose', purpose);
|
|
45
47
|
await AuthnSecret_js_1.AuthnSecret.insert((0, values_js_1.columnValues)({ id: (0, node_crypto_1.randomUUID)(), identity: key, purpose, secret_hash: (0, sql_js_1.sha256hex)(raw), expires_at: (0, sql_js_1.instant)(nowMs + ttlSeconds * 1000), used_at: null, created_at: (0, sql_js_1.instant)(nowMs) }));
|
|
46
48
|
return raw;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-secret-store.js","sourceRoot":"","sources":["../../../src/secrets/db-secret-store.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6CAAsD;AAEtD,wDAAuD;AAEvD,oCAA2D;AAC3D,sCAAsD;AAEtD,wCAA0H;AAG1H,gDAA6C;AAC7C,6DAAuD;AACvD,8CAA+E;AAC/E,oDAAoD;AAEpD,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,sFAAsF;AACtF,MAAM,OAAO,GAAG,IAAI,CAAC;AAErB;;;;;;GAMG;AAGI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,uBAAW;IAAvC;;QACY,aAAQ,GAAG,IAAA,kBAAY,EAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"db-secret-store.js","sourceRoot":"","sources":["../../../src/secrets/db-secret-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PeekVerdict } from '@spinajs/authn/contracts';
|
|
1
2
|
import type { KeyedBackoffVerdict, ThrottleGate, ThrottleLower, ThrottleStore } from '@spinajs/util';
|
|
2
3
|
import type { DateTime } from 'luxon';
|
|
3
4
|
/** @internal "now" and the staleness cutoff of one call. */
|
|
@@ -46,7 +47,12 @@ export declare class DbThrottleStore implements ThrottleStore {
|
|
|
46
47
|
private readonly purgeDue;
|
|
47
48
|
constructor(options: DbThrottleStoreOptions);
|
|
48
49
|
attempt(_flow: string, gates: readonly ThrottleGate[], counted: readonly string[], nowMs: number): Promise<KeyedBackoffVerdict>;
|
|
49
|
-
|
|
50
|
+
/**
|
|
51
|
+
* One SELECT of the live rows of the gates: refuses as `attempt` would for a delay, else `clean` when there are
|
|
52
|
+
* none. A success lowers or clears only rows an attempt writes next to its account gate, so a clean peek needs no
|
|
53
|
+
* `succeed`.
|
|
54
|
+
*/
|
|
55
|
+
peek(_flow: string, gates: readonly ThrottleGate[], nowMs: number): Promise<PeekVerdict>;
|
|
50
56
|
/** Lowers by the largest count it consumed: rows carry no run, so a `by` row older than its target is taken off too. */
|
|
51
57
|
succeed(_flow: string, lower: readonly ThrottleLower[], clear: readonly string[], nowMs: number): Promise<void>;
|
|
52
58
|
/** Deletes up to one batch of stale rows (idle for resetAfterMs and delaying nobody); returns how many went. */
|
|
@@ -70,6 +76,7 @@ export declare class DbThrottleStore implements ThrottleStore {
|
|
|
70
76
|
private subtract;
|
|
71
77
|
/** The longest wait any of `ks` imposes now, 0 when none delays. */
|
|
72
78
|
private blockedWait;
|
|
79
|
+
private waitOf;
|
|
73
80
|
/** Rows of `ks` that are not stale; stale and missing rows both count as zero. */
|
|
74
81
|
private readLive;
|
|
75
82
|
private isLive;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-throttle-store.d.ts","sourceRoot":"","sources":["../../../src/throttle/db-throttle-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"db-throttle-store.d.ts","sourceRoot":"","sources":["../../../src/throttle/db-throttle-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,12 +53,22 @@ class DbThrottleStore {
|
|
|
53
53
|
}
|
|
54
54
|
return { allowed: true };
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* One SELECT of the live rows of the gates: refuses as `attempt` would for a delay, else `clean` when there are
|
|
58
|
+
* none. A success lowers or clears only rows an attempt writes next to its account gate, so a clean peek needs no
|
|
59
|
+
* `succeed`.
|
|
60
|
+
*/
|
|
56
61
|
async peek(_flow, gates, nowMs) {
|
|
57
62
|
if (gates.length === 0)
|
|
58
|
-
return { allowed: true };
|
|
63
|
+
return { allowed: true, clean: true };
|
|
59
64
|
await (0, orm_1.ormReady)();
|
|
60
|
-
const
|
|
61
|
-
|
|
65
|
+
const t = this.times(nowMs);
|
|
66
|
+
const live = await AuthnThrottle_js_1.AuthnThrottle.query()
|
|
67
|
+
.columns(['k', 'next_allowed_at'])
|
|
68
|
+
.whereIn('k', gates.map((g) => g.id))
|
|
69
|
+
.where(this.isLive(t));
|
|
70
|
+
const waitMs = Math.max(0, ...live.map((r) => this.waitOf(r, t)));
|
|
71
|
+
return waitMs > 0 ? this.refuse(waitMs) : { allowed: true, clean: live.length === 0 };
|
|
62
72
|
}
|
|
63
73
|
/** Lowers by the largest count it consumed: rows carry no run, so a `by` row older than its target is taken off too. */
|
|
64
74
|
async succeed(_flow, lower, clear, nowMs) {
|
|
@@ -191,13 +201,13 @@ class DbThrottleStore {
|
|
|
191
201
|
.columns(['k', 'next_allowed_at'])
|
|
192
202
|
.whereIn('k', [...ks])
|
|
193
203
|
.where('next_allowed_at', '>', t.now);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return
|
|
204
|
+
// SQL found each row delaying, so one that reads as not delaying still delays.
|
|
205
|
+
return Math.max(0, ...rows.map((r) => this.waitOf(r, t) || FAIL_CLOSED_MS));
|
|
206
|
+
}
|
|
207
|
+
// A row whose datetime does not read is taken to delay.
|
|
208
|
+
waitOf(r, t) {
|
|
209
|
+
const ms = (r.next_allowed_at?.toMillis() ?? NaN) - t.nowMs;
|
|
210
|
+
return Number.isFinite(ms) ? Math.max(0, ms) : FAIL_CLOSED_MS;
|
|
201
211
|
}
|
|
202
212
|
/** Rows of `ks` that are not stale; stale and missing rows both count as zero. */
|
|
203
213
|
async readLive(ks, t) {
|