@blamejs/core 0.7.1 → 0.7.18
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 +423 -389
- package/README.md +150 -149
- package/bin/blamejs.js +0 -0
- package/index.js +308 -282
- package/lib/api-key.js +660 -672
- package/lib/api-snapshot.js +338 -338
- package/lib/app-shutdown.js +385 -385
- package/lib/app.js +365 -365
- package/lib/archive.js +250 -250
- package/lib/atomic-file.js +544 -544
- package/lib/audit-chain.js +177 -177
- package/lib/audit-sign.js +344 -344
- package/lib/audit-tools.js +677 -677
- package/lib/audit.js +766 -766
- package/lib/auth/jwt.js +311 -311
- package/lib/auth/lockout.js +436 -436
- package/lib/auth/oauth.js +721 -721
- package/lib/auth/passkey.js +181 -181
- package/lib/auth/password.js +594 -594
- package/lib/backup/bundle.js +217 -217
- package/lib/backup/crypto.js +176 -176
- package/lib/backup/index.js +515 -515
- package/lib/backup/manifest.js +282 -282
- package/lib/break-glass.js +1338 -1338
- package/lib/bundler.js +441 -441
- package/lib/cache-redis.js +256 -266
- package/lib/cache.js +1206 -1211
- package/lib/canonical-json.js +115 -115
- package/lib/chain-writer.js +234 -234
- package/lib/cli-helpers.js +206 -206
- package/lib/cli.js +2334 -2334
- package/lib/cluster-provider-db.js +317 -317
- package/lib/cluster-storage.js +226 -226
- package/lib/cluster.js +703 -703
- package/lib/codepoint-class.js +196 -0
- package/lib/config-drift.js +301 -301
- package/lib/consent.js +222 -222
- package/lib/constants.js +191 -191
- package/lib/cookies.js +315 -315
- package/lib/credential-hash.js +322 -322
- package/lib/crypto.js +266 -266
- package/lib/csv.js +275 -286
- package/lib/db-declare-row-policy.js +267 -267
- package/lib/db-declare-view.js +420 -421
- package/lib/db-query.js +406 -406
- package/lib/db-schema.js +319 -319
- package/lib/db.js +1288 -1288
- package/lib/deprecate.js +222 -222
- package/lib/dev.js +335 -335
- package/lib/dual-control.js +473 -473
- package/lib/error-page.js +420 -420
- package/lib/external-db-migrate.js +441 -441
- package/lib/external-db.js +1061 -1061
- package/lib/file-type.js +273 -273
- package/lib/file-upload.js +1136 -0
- package/lib/forms.js +422 -422
- package/lib/framework-error.js +293 -202
- package/lib/framework-schema.js +717 -717
- package/lib/gate-contract.js +971 -0
- package/lib/guard-all.js +405 -0
- package/lib/guard-archive.js +739 -0
- package/lib/guard-csv.js +816 -0
- package/lib/guard-email.js +744 -0
- package/lib/guard-filename.js +724 -0
- package/lib/guard-html.js +976 -0
- package/lib/guard-json.js +729 -0
- package/lib/guard-markdown.js +586 -0
- package/lib/guard-svg.js +976 -0
- package/lib/guard-xml.js +405 -0
- package/lib/guard-yaml.js +529 -0
- package/lib/handlers.js +350 -350
- package/lib/http-client-cookie-jar.js +508 -508
- package/lib/http-client.js +1195 -1195
- package/lib/i18n.js +878 -878
- package/lib/jobs.js +185 -185
- package/lib/log-stream-cloudwatch.js +369 -369
- package/lib/log-stream-local.js +146 -146
- package/lib/log-stream-otlp-grpc.js +410 -410
- package/lib/log-stream-otlp.js +286 -286
- package/lib/log-stream-syslog.js +302 -302
- package/lib/log-stream-webhook.js +199 -199
- package/lib/log-stream.js +330 -330
- package/lib/log.js +500 -500
- package/lib/mail-bounce.js +528 -528
- package/lib/mail-dkim.js +369 -362
- package/lib/mail.js +981 -962
- package/lib/metrics.js +683 -683
- package/lib/middleware/api-encrypt.js +936 -573
- package/lib/middleware/attach-user.js +157 -157
- package/lib/middleware/body-parser.js +1170 -1091
- package/lib/middleware/bot-guard.js +178 -178
- package/lib/middleware/compression.js +452 -452
- package/lib/middleware/cors.js +314 -314
- package/lib/middleware/csp-nonce.js +348 -348
- package/lib/middleware/csrf-protect.js +316 -316
- package/lib/middleware/db-role-for.js +264 -269
- package/lib/middleware/health.js +392 -392
- package/lib/middleware/index.js +79 -79
- package/lib/middleware/rate-limit.js +358 -358
- package/lib/middleware/request-id.js +61 -61
- package/lib/middleware/request-log.js +168 -168
- package/lib/middleware/require-auth.js +104 -104
- package/lib/middleware/security-headers.js +116 -116
- package/lib/middleware/sse.js +166 -166
- package/lib/migrations.js +383 -383
- package/lib/mtls-ca.js +518 -518
- package/lib/mtls-engine-default.js +481 -481
- package/lib/network-dns.js +632 -632
- package/lib/network-heartbeat.js +290 -290
- package/lib/network-nts.js +574 -574
- package/lib/network-proxy.js +265 -265
- package/lib/network-tls.js +328 -328
- package/lib/network.js +233 -233
- package/lib/notify.js +612 -614
- package/lib/ntp-check.js +229 -229
- package/lib/numeric-bounds.js +111 -91
- package/lib/object-store/azure-blob-bucket-ops.js +349 -349
- package/lib/object-store/azure-blob.js +488 -451
- package/lib/object-store/gcs-bucket-ops.js +351 -351
- package/lib/object-store/gcs.js +519 -479
- package/lib/object-store/http-put.js +153 -153
- package/lib/object-store/index.js +197 -197
- package/lib/object-store/sigv4-bucket-ops.js +1092 -1092
- package/lib/object-store/sigv4.js +903 -855
- package/lib/observability.js +151 -151
- package/lib/otel-export.js +269 -269
- package/lib/pagination.js +464 -464
- package/lib/parsers/index.js +80 -80
- package/lib/parsers/safe-env.js +642 -642
- package/lib/parsers/safe-ini.js +292 -292
- package/lib/parsers/safe-toml.js +784 -784
- package/lib/parsers/safe-xml.js +390 -390
- package/lib/parsers/safe-yaml.js +1015 -1015
- package/lib/permissions.js +708 -708
- package/lib/pqc-agent.js +87 -87
- package/lib/pqc-gate.js +279 -279
- package/lib/protobuf-encoder.js +190 -190
- package/lib/protocol-dispatcher.js +161 -161
- package/lib/pubsub-redis.js +167 -177
- package/lib/pubsub.js +429 -429
- package/lib/queue-local.js +476 -476
- package/lib/queue-redis.js +745 -752
- package/lib/queue-sqs.js +319 -319
- package/lib/queue.js +695 -695
- package/lib/redis-client.js +519 -489
- package/lib/request-helpers.js +340 -336
- package/lib/restore-bundle.js +237 -237
- package/lib/restore-rollback.js +259 -259
- package/lib/restore.js +409 -409
- package/lib/retry.js +376 -376
- package/lib/router.js +748 -748
- package/lib/safe-async.js +735 -735
- package/lib/safe-buffer.js +237 -237
- package/lib/safe-json.js +541 -541
- package/lib/safe-schema.js +1266 -1266
- package/lib/safe-url.js +159 -159
- package/lib/scheduler.js +706 -706
- package/lib/security-assert.js +373 -373
- package/lib/seeders.js +618 -630
- package/lib/session.js +478 -478
- package/lib/slug.js +269 -269
- package/lib/ssrf-guard.js +401 -401
- package/lib/static.js +879 -114
- package/lib/storage.js +471 -471
- package/lib/subject.js +281 -281
- package/lib/template.js +791 -791
- package/lib/testing.js +798 -798
- package/lib/time.js +310 -310
- package/lib/totp.js +302 -302
- package/lib/tracing.js +494 -494
- package/lib/uuid.js +132 -132
- package/lib/validate-opts.js +340 -270
- package/lib/vault/index.js +308 -308
- package/lib/vault/rotate.js +784 -784
- package/lib/vault/wrap.js +296 -296
- package/lib/vendor/noble-ciphers.cjs +9 -9
- package/lib/webhook.js +595 -598
- package/lib/websocket.js +1048 -1048
- package/package.json +77 -77
- package/sbom.cyclonedx.json +7 -7
|
@@ -1,157 +1,157 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* attach-user middleware — populates req.user (and req.session) from a
|
|
4
|
-
* verified session token.
|
|
5
|
-
*
|
|
6
|
-
* Token sources, tried in order:
|
|
7
|
-
* 1. Cookie named opts.cookieName (default "blamejs_session")
|
|
8
|
-
* 2. Authorization: Bearer <token> header
|
|
9
|
-
* The first one that produces a verified session wins. Operators who
|
|
10
|
-
* want only one path can disable the other via opts.tokenFrom.
|
|
11
|
-
*
|
|
12
|
-
* Sealed cookies (access-gated): when opts.sealed is true and opts.vault
|
|
13
|
-
* is provided, the cookie value is read via cookies.readSealed (which
|
|
14
|
-
* vault-unseals and recovers the original session token). Without the
|
|
15
|
-
* framework's vault key no client can hand-craft a valid cookie, so the
|
|
16
|
-
* API is unreachable via curl-with-arbitrary-cookies. Default off for
|
|
17
|
-
* back-compat with apps that put the raw token in the cookie.
|
|
18
|
-
*
|
|
19
|
-
* The framework can't know the application's user schema, so the
|
|
20
|
-
* middleware delegates user-record loading to opts.userLoader — an
|
|
21
|
-
* async function `(verifiedSession) => user | null`. Operators
|
|
22
|
-
* typically look up by userId in their own users table.
|
|
23
|
-
*
|
|
24
|
-
* Failure modes (none of which throw):
|
|
25
|
-
* - No token in either source → req.user = null, next()
|
|
26
|
-
* - Sealed cookie present but unsealable → req.user = null, next()
|
|
27
|
-
* - Token present but session.verify rejects → req.user = null, next()
|
|
28
|
-
* - Session valid but userLoader returns null/undefined → req.user
|
|
29
|
-
* = null, next() + audit emit (with outcome=failure)
|
|
30
|
-
*
|
|
31
|
-
* Always calls next() — the gating decision is downstream's job (use
|
|
32
|
-
* middleware.requireAuth for that). This middleware only ATTACHES.
|
|
33
|
-
*
|
|
34
|
-
* Options:
|
|
35
|
-
* {
|
|
36
|
-
* cookieName: 'blamejs_session' (cookie name to read)
|
|
37
|
-
* tokenFrom: 'both' | 'cookie' | 'header' (default 'both')
|
|
38
|
-
* sealed: false (use cookies.readSealed)
|
|
39
|
-
* vault: b.vault (required when sealed)
|
|
40
|
-
* userLoader: async (verifiedSession) => user (REQUIRED)
|
|
41
|
-
* audit: true (emit user-load audits)
|
|
42
|
-
* }
|
|
43
|
-
*/
|
|
44
|
-
var lazyRequire = require("../lazy-require");
|
|
45
|
-
var cookies = require("../cookies");
|
|
46
|
-
var requestHelpers = require("../request-helpers");
|
|
47
|
-
var validateOpts = require("../validate-opts");
|
|
48
|
-
var session = lazyRequire(function () { return require("../session"); });
|
|
49
|
-
var audit = lazyRequire(function () { return require("../audit"); });
|
|
50
|
-
|
|
51
|
-
// Back-compat helper: read a single named cookie from a Cookie: header
|
|
52
|
-
// string. Delegates to cookies.parse so the parser is one place.
|
|
53
|
-
function _readCookie(cookieHeader, name) {
|
|
54
|
-
if (!cookieHeader || typeof cookieHeader !== "string") return null;
|
|
55
|
-
var jar = cookies.parse(cookieHeader);
|
|
56
|
-
return Object.prototype.hasOwnProperty.call(jar, name) ? jar[name] : null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function _readBearer(authHeader) {
|
|
60
|
-
if (!authHeader || typeof authHeader !== "string") return null;
|
|
61
|
-
// case-insensitive scheme match
|
|
62
|
-
var m = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
63
|
-
return m ? m[1].trim() : null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function create(opts) {
|
|
67
|
-
opts = opts || {};
|
|
68
|
-
validateOpts(opts, [
|
|
69
|
-
"cookieName", "tokenFrom", "sealed", "vault", "userLoader", "audit",
|
|
70
|
-
], "middleware.attachUser");
|
|
71
|
-
if (typeof opts.userLoader !== "function") {
|
|
72
|
-
throw new Error("middleware.attachUser: opts.userLoader is required " +
|
|
73
|
-
"(async function (verifiedSession) → user | null)");
|
|
74
|
-
}
|
|
75
|
-
var cookieName = opts.cookieName || "blamejs_session";
|
|
76
|
-
var tokenFrom = opts.tokenFrom || "both";
|
|
77
|
-
var auditOn = opts.audit !== false;
|
|
78
|
-
var sealed = !!opts.sealed;
|
|
79
|
-
if (sealed && (!opts.vault || typeof opts.vault.unseal !== "function")) {
|
|
80
|
-
throw new Error("middleware.attachUser: opts.sealed requires opts.vault " +
|
|
81
|
-
"with a .unseal method (typically b.vault)");
|
|
82
|
-
}
|
|
83
|
-
// Cookie reader: instance bound to the operator's vault when sealed,
|
|
84
|
-
// otherwise the stateless plain reader.
|
|
85
|
-
var cookieJar = sealed ? cookies.create({ vault: opts.vault }) : null;
|
|
86
|
-
|
|
87
|
-
return async function attachUser(req, res, next) {
|
|
88
|
-
req.user = null;
|
|
89
|
-
req.session = null;
|
|
90
|
-
|
|
91
|
-
var token = null;
|
|
92
|
-
if (tokenFrom === "cookie" || tokenFrom === "both") {
|
|
93
|
-
token = sealed
|
|
94
|
-
? cookieJar.readSealed(req, cookieName)
|
|
95
|
-
: _readCookie(req.headers && req.headers.cookie, cookieName);
|
|
96
|
-
}
|
|
97
|
-
if (!token && (tokenFrom === "header" || tokenFrom === "both")) {
|
|
98
|
-
token = _readBearer(req.headers && req.headers.authorization);
|
|
99
|
-
}
|
|
100
|
-
if (!token) return next();
|
|
101
|
-
|
|
102
|
-
var verified;
|
|
103
|
-
try {
|
|
104
|
-
verified = await session().verify(token);
|
|
105
|
-
} catch (_e) {
|
|
106
|
-
// session.verify is tolerant — shouldn't normally throw, but if it
|
|
107
|
-
// does (DB hiccup), don't propagate; treat as "no user" and let
|
|
108
|
-
// downstream require-auth produce a 401.
|
|
109
|
-
return next();
|
|
110
|
-
}
|
|
111
|
-
if (!verified) return next();
|
|
112
|
-
|
|
113
|
-
var user;
|
|
114
|
-
try {
|
|
115
|
-
user = await opts.userLoader(verified);
|
|
116
|
-
} catch (e) {
|
|
117
|
-
// userLoader threw — treat as "no user" but record so the
|
|
118
|
-
// operator can investigate. Don't surface to the response.
|
|
119
|
-
if (auditOn) {
|
|
120
|
-
try {
|
|
121
|
-
audit().emit({
|
|
122
|
-
action: "auth.session.user_loader_threw",
|
|
123
|
-
outcome: "failure",
|
|
124
|
-
actor: requestHelpers.extractActorContext(req, { userId: verified.userId }),
|
|
125
|
-
reason: (e && e.message) || String(e),
|
|
126
|
-
});
|
|
127
|
-
} catch (_ignored) { /* audit best-effort */ }
|
|
128
|
-
}
|
|
129
|
-
return next();
|
|
130
|
-
}
|
|
131
|
-
if (!user) {
|
|
132
|
-
// Session valid but user record is gone (deleted) or rejected
|
|
133
|
-
// (suspended, etc.). Record + don't attach.
|
|
134
|
-
if (auditOn) {
|
|
135
|
-
try {
|
|
136
|
-
audit().emit({
|
|
137
|
-
action: "auth.session.user_unloadable",
|
|
138
|
-
outcome: "failure",
|
|
139
|
-
actor: requestHelpers.extractActorContext(req, { userId: verified.userId }),
|
|
140
|
-
});
|
|
141
|
-
} catch (_ignored) { /* audit best-effort */ }
|
|
142
|
-
}
|
|
143
|
-
return next();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
req.user = user;
|
|
147
|
-
req.session = verified;
|
|
148
|
-
return next();
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
module.exports = {
|
|
153
|
-
create: create,
|
|
154
|
-
// Exported for tests and operator-side cookie reading
|
|
155
|
-
_readCookie: _readCookie,
|
|
156
|
-
_readBearer: _readBearer,
|
|
157
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* attach-user middleware — populates req.user (and req.session) from a
|
|
4
|
+
* verified session token.
|
|
5
|
+
*
|
|
6
|
+
* Token sources, tried in order:
|
|
7
|
+
* 1. Cookie named opts.cookieName (default "blamejs_session")
|
|
8
|
+
* 2. Authorization: Bearer <token> header
|
|
9
|
+
* The first one that produces a verified session wins. Operators who
|
|
10
|
+
* want only one path can disable the other via opts.tokenFrom.
|
|
11
|
+
*
|
|
12
|
+
* Sealed cookies (access-gated): when opts.sealed is true and opts.vault
|
|
13
|
+
* is provided, the cookie value is read via cookies.readSealed (which
|
|
14
|
+
* vault-unseals and recovers the original session token). Without the
|
|
15
|
+
* framework's vault key no client can hand-craft a valid cookie, so the
|
|
16
|
+
* API is unreachable via curl-with-arbitrary-cookies. Default off for
|
|
17
|
+
* back-compat with apps that put the raw token in the cookie.
|
|
18
|
+
*
|
|
19
|
+
* The framework can't know the application's user schema, so the
|
|
20
|
+
* middleware delegates user-record loading to opts.userLoader — an
|
|
21
|
+
* async function `(verifiedSession) => user | null`. Operators
|
|
22
|
+
* typically look up by userId in their own users table.
|
|
23
|
+
*
|
|
24
|
+
* Failure modes (none of which throw):
|
|
25
|
+
* - No token in either source → req.user = null, next()
|
|
26
|
+
* - Sealed cookie present but unsealable → req.user = null, next()
|
|
27
|
+
* - Token present but session.verify rejects → req.user = null, next()
|
|
28
|
+
* - Session valid but userLoader returns null/undefined → req.user
|
|
29
|
+
* = null, next() + audit emit (with outcome=failure)
|
|
30
|
+
*
|
|
31
|
+
* Always calls next() — the gating decision is downstream's job (use
|
|
32
|
+
* middleware.requireAuth for that). This middleware only ATTACHES.
|
|
33
|
+
*
|
|
34
|
+
* Options:
|
|
35
|
+
* {
|
|
36
|
+
* cookieName: 'blamejs_session' (cookie name to read)
|
|
37
|
+
* tokenFrom: 'both' | 'cookie' | 'header' (default 'both')
|
|
38
|
+
* sealed: false (use cookies.readSealed)
|
|
39
|
+
* vault: b.vault (required when sealed)
|
|
40
|
+
* userLoader: async (verifiedSession) => user (REQUIRED)
|
|
41
|
+
* audit: true (emit user-load audits)
|
|
42
|
+
* }
|
|
43
|
+
*/
|
|
44
|
+
var lazyRequire = require("../lazy-require");
|
|
45
|
+
var cookies = require("../cookies");
|
|
46
|
+
var requestHelpers = require("../request-helpers");
|
|
47
|
+
var validateOpts = require("../validate-opts");
|
|
48
|
+
var session = lazyRequire(function () { return require("../session"); });
|
|
49
|
+
var audit = lazyRequire(function () { return require("../audit"); });
|
|
50
|
+
|
|
51
|
+
// Back-compat helper: read a single named cookie from a Cookie: header
|
|
52
|
+
// string. Delegates to cookies.parse so the parser is one place.
|
|
53
|
+
function _readCookie(cookieHeader, name) {
|
|
54
|
+
if (!cookieHeader || typeof cookieHeader !== "string") return null;
|
|
55
|
+
var jar = cookies.parse(cookieHeader);
|
|
56
|
+
return Object.prototype.hasOwnProperty.call(jar, name) ? jar[name] : null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function _readBearer(authHeader) {
|
|
60
|
+
if (!authHeader || typeof authHeader !== "string") return null;
|
|
61
|
+
// case-insensitive scheme match
|
|
62
|
+
var m = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
63
|
+
return m ? m[1].trim() : null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function create(opts) {
|
|
67
|
+
opts = opts || {};
|
|
68
|
+
validateOpts(opts, [
|
|
69
|
+
"cookieName", "tokenFrom", "sealed", "vault", "userLoader", "audit",
|
|
70
|
+
], "middleware.attachUser");
|
|
71
|
+
if (typeof opts.userLoader !== "function") {
|
|
72
|
+
throw new Error("middleware.attachUser: opts.userLoader is required " +
|
|
73
|
+
"(async function (verifiedSession) → user | null)");
|
|
74
|
+
}
|
|
75
|
+
var cookieName = opts.cookieName || "blamejs_session";
|
|
76
|
+
var tokenFrom = opts.tokenFrom || "both";
|
|
77
|
+
var auditOn = opts.audit !== false;
|
|
78
|
+
var sealed = !!opts.sealed;
|
|
79
|
+
if (sealed && (!opts.vault || typeof opts.vault.unseal !== "function")) {
|
|
80
|
+
throw new Error("middleware.attachUser: opts.sealed requires opts.vault " +
|
|
81
|
+
"with a .unseal method (typically b.vault)");
|
|
82
|
+
}
|
|
83
|
+
// Cookie reader: instance bound to the operator's vault when sealed,
|
|
84
|
+
// otherwise the stateless plain reader.
|
|
85
|
+
var cookieJar = sealed ? cookies.create({ vault: opts.vault }) : null;
|
|
86
|
+
|
|
87
|
+
return async function attachUser(req, res, next) {
|
|
88
|
+
req.user = null;
|
|
89
|
+
req.session = null;
|
|
90
|
+
|
|
91
|
+
var token = null;
|
|
92
|
+
if (tokenFrom === "cookie" || tokenFrom === "both") {
|
|
93
|
+
token = sealed
|
|
94
|
+
? cookieJar.readSealed(req, cookieName)
|
|
95
|
+
: _readCookie(req.headers && req.headers.cookie, cookieName);
|
|
96
|
+
}
|
|
97
|
+
if (!token && (tokenFrom === "header" || tokenFrom === "both")) {
|
|
98
|
+
token = _readBearer(req.headers && req.headers.authorization);
|
|
99
|
+
}
|
|
100
|
+
if (!token) return next();
|
|
101
|
+
|
|
102
|
+
var verified;
|
|
103
|
+
try {
|
|
104
|
+
verified = await session().verify(token);
|
|
105
|
+
} catch (_e) {
|
|
106
|
+
// session.verify is tolerant — shouldn't normally throw, but if it
|
|
107
|
+
// does (DB hiccup), don't propagate; treat as "no user" and let
|
|
108
|
+
// downstream require-auth produce a 401.
|
|
109
|
+
return next();
|
|
110
|
+
}
|
|
111
|
+
if (!verified) return next();
|
|
112
|
+
|
|
113
|
+
var user;
|
|
114
|
+
try {
|
|
115
|
+
user = await opts.userLoader(verified);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
// userLoader threw — treat as "no user" but record so the
|
|
118
|
+
// operator can investigate. Don't surface to the response.
|
|
119
|
+
if (auditOn) {
|
|
120
|
+
try {
|
|
121
|
+
audit().emit({
|
|
122
|
+
action: "auth.session.user_loader_threw",
|
|
123
|
+
outcome: "failure",
|
|
124
|
+
actor: requestHelpers.extractActorContext(req, { userId: verified.userId }),
|
|
125
|
+
reason: (e && e.message) || String(e),
|
|
126
|
+
});
|
|
127
|
+
} catch (_ignored) { /* audit best-effort */ }
|
|
128
|
+
}
|
|
129
|
+
return next();
|
|
130
|
+
}
|
|
131
|
+
if (!user) {
|
|
132
|
+
// Session valid but user record is gone (deleted) or rejected
|
|
133
|
+
// (suspended, etc.). Record + don't attach.
|
|
134
|
+
if (auditOn) {
|
|
135
|
+
try {
|
|
136
|
+
audit().emit({
|
|
137
|
+
action: "auth.session.user_unloadable",
|
|
138
|
+
outcome: "failure",
|
|
139
|
+
actor: requestHelpers.extractActorContext(req, { userId: verified.userId }),
|
|
140
|
+
});
|
|
141
|
+
} catch (_ignored) { /* audit best-effort */ }
|
|
142
|
+
}
|
|
143
|
+
return next();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
req.user = user;
|
|
147
|
+
req.session = verified;
|
|
148
|
+
return next();
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
module.exports = {
|
|
153
|
+
create: create,
|
|
154
|
+
// Exported for tests and operator-side cookie reading
|
|
155
|
+
_readCookie: _readCookie,
|
|
156
|
+
_readBearer: _readBearer,
|
|
157
|
+
};
|