@getstrata/core 1.0.3 → 1.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/CHANGELOG.md +9 -0
- package/dist/core/runtime/appEnv.d.ts +16 -2
- package/dist/core/runtime/appKeyPrefix.d.ts +8 -1
- package/dist/entries/audit/exportAuditLogs.js +83 -18
- package/dist/entries/audit/siemFormatter.js +32 -3
- package/dist/entries/auth/intendedUrlCookie.js +33 -4
- package/dist/entries/auth/jwt.js +36 -4
- package/dist/entries/auth/jwtGuard.js +36 -4
- package/dist/entries/auth/oauth/providers.js +32 -3
- package/dist/entries/auth/oauth/samlProvider.js +32 -3
- package/dist/entries/auth/passwordConfirmCookie.js +35 -6
- package/dist/entries/auth/sessionCookie.js +35 -6
- package/dist/entries/auth/sessionGuard.js +35 -6
- package/dist/entries/auth/tokenHash.js +33 -4
- package/dist/entries/cache/createCacheStore.js +32 -3
- package/dist/entries/facades.js +32 -3
- package/dist/entries/http/corsMiddleware.js +16 -1
- package/dist/entries/http/csrfMiddleware.js +34 -5
- package/dist/entries/http/csrfToken.js +34 -5
- package/dist/entries/http/flashMiddleware.js +33 -4
- package/dist/entries/http/flashSession.js +33 -4
- package/dist/entries/http/loginThrottleMiddleware.js +1 -373
- package/dist/entries/http/memoryThrottleMiddleware.js +32 -58
- package/dist/entries/http/response.js +16 -56
- package/dist/entries/http/scimThrottleMiddleware.js +32 -3
- package/dist/entries/http/securityHeadersMiddleware.js +32 -3
- package/dist/entries/http/signedUrl.js +33 -4
- package/dist/entries/http/throttleMiddleware.js +32 -58
- package/dist/entries/http/webErrorResponse.js +1 -401
- package/dist/entries/jobs/exportAuditLogsJob.js +83 -18
- package/dist/entries/lifecycle/gracefulShutdown.js +1 -50
- package/dist/entries/mail/mailer.js +32 -3
- package/dist/entries/openapi/generator.js +32 -3
- package/dist/entries/queue/createAppQueue.js +32 -3
- package/dist/entries/queue/publicQueue.js +32 -3
- package/dist/entries/queue/queueMetrics.js +32 -3
- package/dist/entries/queue/redisQueue.js +32 -3
- package/dist/entries/runtime/appEnv.js +18 -1
- package/dist/entries/runtime/appKeyPrefix.js +1 -70
- package/dist/entries/security/oauthState.js +33 -4
- package/dist/entries/security/safeFetch.js +32 -9
- package/dist/entries/security/safeUrl.js +1 -105
- package/dist/entries/security/totp.js +32 -3
- package/dist/entries/tenant/databaseTenantContext.js +48 -6
- package/dist/entries/tracing/tracingMiddleware.js +32 -3
- package/dist/entries/view.js +1 -778
- package/dist/framework/public-api.d.ts +27 -18
- package/dist/index.js +442 -53
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -490,6 +490,26 @@ class AuthManager {
|
|
|
490
490
|
// ../../src/core/auth/jwt.ts
|
|
491
491
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
492
492
|
|
|
493
|
+
// ../../src/core/runtime/appEnv.ts
|
|
494
|
+
var NON_PRODUCTION_APP_ENVS = new Set(["local", "development", "dev", "test", "testing", "ci"]);
|
|
495
|
+
function normalizeEnvValue(value) {
|
|
496
|
+
return (value ?? "").trim().toLowerCase();
|
|
497
|
+
}
|
|
498
|
+
function isProductionEnv(env = process.env) {
|
|
499
|
+
const appEnv = normalizeEnvValue(env.APP_ENV);
|
|
500
|
+
const nodeEnv = normalizeEnvValue(env.NODE_ENV);
|
|
501
|
+
if (appEnv === "production" || nodeEnv === "production") {
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
if (appEnv === "") {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
return !NON_PRODUCTION_APP_ENVS.has(appEnv);
|
|
508
|
+
}
|
|
509
|
+
function envFlagEnabled(value) {
|
|
510
|
+
return value === "true";
|
|
511
|
+
}
|
|
512
|
+
|
|
493
513
|
// ../../src/core/runtime/appKeyPrefix.ts
|
|
494
514
|
function appKeyPrefix() {
|
|
495
515
|
return process.env.APP_KEY_PREFIX?.trim() || "strata";
|
|
@@ -500,6 +520,18 @@ function appCookieName(kind) {
|
|
|
500
520
|
function appDevSecret(kind) {
|
|
501
521
|
return `${appKeyPrefix()}-dev-${kind}`;
|
|
502
522
|
}
|
|
523
|
+
function requireConfiguredSecret(names, devKind, env = process.env) {
|
|
524
|
+
for (const name of names) {
|
|
525
|
+
const value = env[name]?.trim();
|
|
526
|
+
if (value) {
|
|
527
|
+
return value;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (isProductionEnv(env)) {
|
|
531
|
+
throw new Error(`${names[0]} must be set outside development. Do not derive secrets from the app name.`);
|
|
532
|
+
}
|
|
533
|
+
return appDevSecret(devKind);
|
|
534
|
+
}
|
|
503
535
|
function namespacedRedisKey(kind) {
|
|
504
536
|
return `${appKeyPrefix()}:${kind}`;
|
|
505
537
|
}
|
|
@@ -508,16 +540,48 @@ function smtpEhloHost() {
|
|
|
508
540
|
const safe = raw.replace(/[^a-zA-Z0-9.-]/g, "");
|
|
509
541
|
return safe || "strata.local";
|
|
510
542
|
}
|
|
543
|
+
function siemEventType() {
|
|
544
|
+
return process.env.SIEM_EVENT_TYPE?.trim() || `${appKeyPrefix()}.audit`;
|
|
545
|
+
}
|
|
546
|
+
function appUserAgent() {
|
|
547
|
+
return process.env.APP_USER_AGENT?.trim() || appKeyPrefix();
|
|
548
|
+
}
|
|
511
549
|
function otelServiceName() {
|
|
512
550
|
return process.env.OTEL_SERVICE_NAME?.trim() || `${appKeyPrefix()}-api`;
|
|
513
551
|
}
|
|
552
|
+
function webhookSignatureHeader() {
|
|
553
|
+
return process.env.WEBHOOK_SIGNATURE_HEADER?.trim() || `x-${appKeyPrefix()}-signature`;
|
|
554
|
+
}
|
|
555
|
+
function appDisplayName() {
|
|
556
|
+
return process.env.APP_NAME?.trim() || "Strata";
|
|
557
|
+
}
|
|
514
558
|
function appEnv() {
|
|
515
559
|
return process.env.APP_ENV?.trim() || "local";
|
|
516
560
|
}
|
|
561
|
+
function appUrl() {
|
|
562
|
+
return (process.env.APP_URL?.trim() || "http://localhost:3000").replace(/\/$/, "");
|
|
563
|
+
}
|
|
564
|
+
function apiPrefix() {
|
|
565
|
+
const raw = process.env.API_PREFIX?.trim() || "/api/v1";
|
|
566
|
+
const withSlash = raw.startsWith("/") ? raw : `/${raw}`;
|
|
567
|
+
const trimmed = withSlash.replace(/\/+$/, "");
|
|
568
|
+
return trimmed || "/api/v1";
|
|
569
|
+
}
|
|
570
|
+
function sdkClientClassName() {
|
|
571
|
+
const override = process.env.APP_SDK_CLASS?.trim();
|
|
572
|
+
if (override && /^[A-Za-z_][A-Za-z0-9_]*$/.test(override)) {
|
|
573
|
+
return override;
|
|
574
|
+
}
|
|
575
|
+
const fromName = appDisplayName().replace(/[^A-Za-z0-9]/g, "");
|
|
576
|
+
return fromName ? `${fromName}Client` : "AppClient";
|
|
577
|
+
}
|
|
517
578
|
|
|
518
579
|
// ../../src/core/auth/jwt.ts
|
|
519
580
|
function resolveJwtSecret(secret) {
|
|
520
|
-
|
|
581
|
+
if (secret?.trim()) {
|
|
582
|
+
return secret.trim();
|
|
583
|
+
}
|
|
584
|
+
return requireConfiguredSecret(["JWT_SECRET", "SESSION_SECRET"], "jwt-secret");
|
|
521
585
|
}
|
|
522
586
|
function jwtTtlSeconds(override) {
|
|
523
587
|
if (typeof override === "number" && Number.isInteger(override) && override > 0) {
|
|
@@ -642,6 +706,9 @@ function configureMembershipLookup(lookup) {
|
|
|
642
706
|
function resolveMembershipLookup() {
|
|
643
707
|
return membershipRepository;
|
|
644
708
|
}
|
|
709
|
+
function resetMembershipLookupForTests() {
|
|
710
|
+
membershipRepository = uninitializedMembershipLookup;
|
|
711
|
+
}
|
|
645
712
|
async function runWithMembershipContext(callback) {
|
|
646
713
|
const user = currentAuthUser();
|
|
647
714
|
if (!user || isGlobalAdmin(user)) {
|
|
@@ -1101,6 +1168,11 @@ function getDefaultDatabaseQuery() {
|
|
|
1101
1168
|
}
|
|
1102
1169
|
return query;
|
|
1103
1170
|
}
|
|
1171
|
+
function resetDefaultDatabasePoolForTests() {
|
|
1172
|
+
const holder = defaultConnectionState();
|
|
1173
|
+
holder.pool = null;
|
|
1174
|
+
holder.query = null;
|
|
1175
|
+
}
|
|
1104
1176
|
|
|
1105
1177
|
// ../../src/core/security/timingSafeCompare.ts
|
|
1106
1178
|
import { timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
@@ -2215,6 +2287,14 @@ function appendWhereParts(tableName, where, params) {
|
|
|
2215
2287
|
}
|
|
2216
2288
|
return clauses.join(" AND ");
|
|
2217
2289
|
}
|
|
2290
|
+
function buildWhereClause(tableName, where = {}) {
|
|
2291
|
+
const params = [];
|
|
2292
|
+
const body = appendWhereParts(tableName, where, params);
|
|
2293
|
+
return {
|
|
2294
|
+
clause: body.length > 0 ? ` WHERE ${body}` : "",
|
|
2295
|
+
params
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2218
2298
|
function remapExistsSql(sql, existsParams, params) {
|
|
2219
2299
|
const offset = params.length;
|
|
2220
2300
|
params.push(...existsParams);
|
|
@@ -6643,6 +6723,9 @@ function generateCspNonce() {
|
|
|
6643
6723
|
function configureContentSecurityPolicy(options) {
|
|
6644
6724
|
configuredHtmlOptions = { ...options };
|
|
6645
6725
|
}
|
|
6726
|
+
function resetContentSecurityPolicyForTests() {
|
|
6727
|
+
configuredHtmlOptions = {};
|
|
6728
|
+
}
|
|
6646
6729
|
function cloneDirectives(source) {
|
|
6647
6730
|
const copy = {};
|
|
6648
6731
|
for (const [directive, values] of Object.entries(source)) {
|
|
@@ -6753,11 +6836,6 @@ function readRequestCookie(request, name) {
|
|
|
6753
6836
|
function readBunRequestCookie(request, name) {
|
|
6754
6837
|
return request.cookies.get(name) ?? readRequestCookie(request, name);
|
|
6755
6838
|
}
|
|
6756
|
-
// ../../src/core/runtime/appEnv.ts
|
|
6757
|
-
function isProductionEnv(env = process.env) {
|
|
6758
|
-
return env.APP_ENV === "production" || env.NODE_ENV === "production";
|
|
6759
|
-
}
|
|
6760
|
-
|
|
6761
6839
|
// ../../src/core/http/corsMiddleware.ts
|
|
6762
6840
|
function defaultAllowedOrigins() {
|
|
6763
6841
|
return isProductionEnv() ? "" : "*";
|
|
@@ -6823,7 +6901,7 @@ function csrfCookieName() {
|
|
|
6823
6901
|
return process.env.CSRF_COOKIE_NAME?.trim() || appCookieName("csrf");
|
|
6824
6902
|
}
|
|
6825
6903
|
function resolveCsrfSecret() {
|
|
6826
|
-
return
|
|
6904
|
+
return requireConfiguredSecret(["SESSION_SECRET", "OAUTH_STATE_SECRET", "ADMIN_API_TOKEN"], "csrf-secret");
|
|
6827
6905
|
}
|
|
6828
6906
|
function csrfVerifyOptions() {
|
|
6829
6907
|
return { secret: resolveCsrfSecret(), maxAge: CSRF_TTL_MS };
|
|
@@ -6838,7 +6916,7 @@ function tokensMatch(left, right) {
|
|
|
6838
6916
|
}
|
|
6839
6917
|
function createCsrfTokenCookie() {
|
|
6840
6918
|
const token = Bun.CSRF.generate(resolveCsrfSecret(), { expiresIn: CSRF_TTL_MS });
|
|
6841
|
-
const secure =
|
|
6919
|
+
const secure = isProductionEnv() ? "; Secure" : "";
|
|
6842
6920
|
return {
|
|
6843
6921
|
token,
|
|
6844
6922
|
cookie: `${csrfCookieName()}=${encodeURIComponent(token)}; Path=/; SameSite=Lax; Max-Age=${Math.floor(CSRF_TTL_MS / 1000)}${secure}`
|
|
@@ -6958,7 +7036,7 @@ function flashCookieName() {
|
|
|
6958
7036
|
return process.env.FLASH_COOKIE_NAME?.trim() || appCookieName("flash");
|
|
6959
7037
|
}
|
|
6960
7038
|
function resolveFlashSecret() {
|
|
6961
|
-
return
|
|
7039
|
+
return requireConfiguredSecret(["SESSION_SECRET", "OAUTH_STATE_SECRET"], "flash-secret");
|
|
6962
7040
|
}
|
|
6963
7041
|
function signFlashPayload(payload, issuedAt) {
|
|
6964
7042
|
const signature = createHmac2("sha256", resolveFlashSecret()).update(`${payload}.${issuedAt}`).digest("hex");
|
|
@@ -7068,6 +7146,49 @@ function getQueryParams(request) {
|
|
|
7068
7146
|
}
|
|
7069
7147
|
return new URL(request.url).searchParams;
|
|
7070
7148
|
}
|
|
7149
|
+
function parseOptionalPositiveIntQueryParam(params, name) {
|
|
7150
|
+
const value = params.get(name);
|
|
7151
|
+
if (value === null || value.trim() === "") {
|
|
7152
|
+
return;
|
|
7153
|
+
}
|
|
7154
|
+
const parsed = Number.parseInt(value, 10);
|
|
7155
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
7156
|
+
throw new BadRequestError(`Invalid query parameter "${name}". Expected a positive integer.`);
|
|
7157
|
+
}
|
|
7158
|
+
return parsed;
|
|
7159
|
+
}
|
|
7160
|
+
function parseOptionalBooleanQueryParam(params, name) {
|
|
7161
|
+
const value = params.get(name);
|
|
7162
|
+
if (value === null || value.trim() === "") {
|
|
7163
|
+
return;
|
|
7164
|
+
}
|
|
7165
|
+
switch (value.toLowerCase()) {
|
|
7166
|
+
case "true":
|
|
7167
|
+
case "1":
|
|
7168
|
+
return true;
|
|
7169
|
+
case "false":
|
|
7170
|
+
case "0":
|
|
7171
|
+
return false;
|
|
7172
|
+
default:
|
|
7173
|
+
throw new BadRequestError(`Invalid query parameter "${name}". Expected a boolean.`);
|
|
7174
|
+
}
|
|
7175
|
+
}
|
|
7176
|
+
function parseOptionalEnumQueryParam(params, name, allowedValues) {
|
|
7177
|
+
const value = params.get(name);
|
|
7178
|
+
if (value === null || value.trim() === "") {
|
|
7179
|
+
return;
|
|
7180
|
+
}
|
|
7181
|
+
if (!allowedValues.includes(value)) {
|
|
7182
|
+
throw new BadRequestError(`Invalid query parameter "${name}". Expected one of: ${allowedValues.join(", ")}.`);
|
|
7183
|
+
}
|
|
7184
|
+
return value;
|
|
7185
|
+
}
|
|
7186
|
+
function expectObject(value, label = "request body") {
|
|
7187
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
7188
|
+
throw new BadRequestError(`${label} must be a JSON object.`);
|
|
7189
|
+
}
|
|
7190
|
+
return value;
|
|
7191
|
+
}
|
|
7071
7192
|
async function parseJsonBody(request, validator) {
|
|
7072
7193
|
let payload;
|
|
7073
7194
|
try {
|
|
@@ -7077,6 +7198,55 @@ async function parseJsonBody(request, validator) {
|
|
|
7077
7198
|
}
|
|
7078
7199
|
return validator(payload);
|
|
7079
7200
|
}
|
|
7201
|
+
function readRequiredString(payload, field, options = {}) {
|
|
7202
|
+
const value = payload[field];
|
|
7203
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
7204
|
+
throw new BadRequestError(`"${field}" is required and must be a string.`);
|
|
7205
|
+
}
|
|
7206
|
+
const trimmed = value.trim();
|
|
7207
|
+
if (options.minLength !== undefined && trimmed.length < options.minLength) {
|
|
7208
|
+
throw new BadRequestError(`"${field}" must be at least ${options.minLength} characters.`);
|
|
7209
|
+
}
|
|
7210
|
+
if (options.maxLength !== undefined && trimmed.length > options.maxLength) {
|
|
7211
|
+
throw new BadRequestError(`"${field}" must be at most ${options.maxLength} characters.`);
|
|
7212
|
+
}
|
|
7213
|
+
if (options.pattern && !options.pattern.test(trimmed)) {
|
|
7214
|
+
throw new BadRequestError(`"${field}" has an invalid format.`);
|
|
7215
|
+
}
|
|
7216
|
+
return trimmed;
|
|
7217
|
+
}
|
|
7218
|
+
function readOptionalString(payload, field, options = {}) {
|
|
7219
|
+
if (!(field in payload) || payload[field] === undefined) {
|
|
7220
|
+
return;
|
|
7221
|
+
}
|
|
7222
|
+
return readRequiredString(payload, field, options);
|
|
7223
|
+
}
|
|
7224
|
+
function readRequiredEnum(payload, field, allowedValues) {
|
|
7225
|
+
const value = readRequiredString(payload, field);
|
|
7226
|
+
if (!allowedValues.includes(value)) {
|
|
7227
|
+
throw new BadRequestError(`"${field}" must be one of: ${allowedValues.join(", ")}.`);
|
|
7228
|
+
}
|
|
7229
|
+
return value;
|
|
7230
|
+
}
|
|
7231
|
+
function readOptionalEnum(payload, field, allowedValues) {
|
|
7232
|
+
if (!(field in payload) || payload[field] === undefined) {
|
|
7233
|
+
return;
|
|
7234
|
+
}
|
|
7235
|
+
return readRequiredEnum(payload, field, allowedValues);
|
|
7236
|
+
}
|
|
7237
|
+
function readRequiredPositiveInt(payload, field) {
|
|
7238
|
+
const value = payload[field];
|
|
7239
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
7240
|
+
throw new BadRequestError(`"${field}" is required and must be a positive integer.`);
|
|
7241
|
+
}
|
|
7242
|
+
return value;
|
|
7243
|
+
}
|
|
7244
|
+
function readOptionalPositiveInt(payload, field) {
|
|
7245
|
+
if (!(field in payload) || payload[field] === undefined) {
|
|
7246
|
+
return;
|
|
7247
|
+
}
|
|
7248
|
+
return readRequiredPositiveInt(payload, field);
|
|
7249
|
+
}
|
|
7080
7250
|
function parsePositiveIntParam(value, name = "id") {
|
|
7081
7251
|
const parsed = Number.parseInt(value, 10);
|
|
7082
7252
|
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
@@ -7097,6 +7267,12 @@ class FormRequest {
|
|
|
7097
7267
|
return await parseJsonBody(request, (payload) => this.parse(payload));
|
|
7098
7268
|
}
|
|
7099
7269
|
}
|
|
7270
|
+
|
|
7271
|
+
class QueryFormRequest {
|
|
7272
|
+
validate(request) {
|
|
7273
|
+
return this.parseQuery(request);
|
|
7274
|
+
}
|
|
7275
|
+
}
|
|
7100
7276
|
// ../../src/core/http/authMiddleware.ts
|
|
7101
7277
|
function createAuthMiddleware(auth) {
|
|
7102
7278
|
return async (request, next) => {
|
|
@@ -7659,6 +7835,10 @@ function withErrorHandling(handler) {
|
|
|
7659
7835
|
}
|
|
7660
7836
|
};
|
|
7661
7837
|
}
|
|
7838
|
+
// ../../src/core/http/route.ts
|
|
7839
|
+
function getRouteParams(request) {
|
|
7840
|
+
return request.params;
|
|
7841
|
+
}
|
|
7662
7842
|
// ../../src/core/http/routeMiddleware.ts
|
|
7663
7843
|
function withMiddleware(...middleware) {
|
|
7664
7844
|
const wrap = composeMiddleware(...middleware);
|
|
@@ -7832,6 +8012,9 @@ function createLoginThrottleMiddleware(options) {
|
|
|
7832
8012
|
}
|
|
7833
8013
|
return createMemoryLoginThrottleMiddleware(options);
|
|
7834
8014
|
}
|
|
8015
|
+
function resetMemoryLoginThrottleForTests() {
|
|
8016
|
+
memoryLoginBuckets.clear();
|
|
8017
|
+
}
|
|
7835
8018
|
// ../../src/core/http/memoryThrottleMiddleware.ts
|
|
7836
8019
|
var throttleBucketRegistries = new Set;
|
|
7837
8020
|
function createMemoryThrottleMiddleware(options) {
|
|
@@ -8019,7 +8202,7 @@ function intendedUrlTtlSeconds() {
|
|
|
8019
8202
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_INTENDED_URL_TTL_SECONDS;
|
|
8020
8203
|
}
|
|
8021
8204
|
function cookieSecureFlag() {
|
|
8022
|
-
return
|
|
8205
|
+
return isProductionEnv() ? "; Secure" : "";
|
|
8023
8206
|
}
|
|
8024
8207
|
function pathnameOf(path) {
|
|
8025
8208
|
const pathname = path.split("?")[0] ?? path;
|
|
@@ -8140,7 +8323,7 @@ function createSecurityHeadersMiddleware(options = {}) {
|
|
|
8140
8323
|
// ../../src/core/http/signedUrl.ts
|
|
8141
8324
|
import { createHmac as createHmac3 } from "crypto";
|
|
8142
8325
|
function resolveSignedUrlSecret() {
|
|
8143
|
-
return
|
|
8326
|
+
return requireConfiguredSecret(["SIGNED_URL_SECRET", "SESSION_SECRET", "OAUTH_STATE_SECRET"], "signed-url-secret");
|
|
8144
8327
|
}
|
|
8145
8328
|
function resolveSignedUrlOrigin() {
|
|
8146
8329
|
return (process.env.APP_URL ?? "http://localhost:3000").replace(/\/$/, "");
|
|
@@ -8339,6 +8522,11 @@ function installGracefulShutdownSignals(signals = ["SIGINT", "SIGTERM"]) {
|
|
|
8339
8522
|
});
|
|
8340
8523
|
}
|
|
8341
8524
|
}
|
|
8525
|
+
function resetGracefulShutdownForTests() {
|
|
8526
|
+
shutdownHandlers.clear();
|
|
8527
|
+
shutdownInstalled = false;
|
|
8528
|
+
shuttingDown = false;
|
|
8529
|
+
}
|
|
8342
8530
|
// ../../src/core/logging/requestLoggingMiddleware.ts
|
|
8343
8531
|
function createRequestLoggingMiddleware() {
|
|
8344
8532
|
return async (request, next) => {
|
|
@@ -8584,6 +8772,42 @@ class AsyncQueue {
|
|
|
8584
8772
|
function createQueue(driver) {
|
|
8585
8773
|
return driver === "async" ? new AsyncQueue : new SyncQueue;
|
|
8586
8774
|
}
|
|
8775
|
+
// ../../src/core/queue/jobRegistry.ts
|
|
8776
|
+
class JobRegistry {
|
|
8777
|
+
factories = new Map;
|
|
8778
|
+
instances = new WeakMap;
|
|
8779
|
+
register(name, factory) {
|
|
8780
|
+
this.factories.set(name, factory);
|
|
8781
|
+
}
|
|
8782
|
+
resolveName(job) {
|
|
8783
|
+
return this.instances.get(job);
|
|
8784
|
+
}
|
|
8785
|
+
track(name, job) {
|
|
8786
|
+
this.instances.set(job, name);
|
|
8787
|
+
return job;
|
|
8788
|
+
}
|
|
8789
|
+
create(name) {
|
|
8790
|
+
const factory = this.factories.get(name);
|
|
8791
|
+
if (!factory) {
|
|
8792
|
+
return;
|
|
8793
|
+
}
|
|
8794
|
+
return factory();
|
|
8795
|
+
}
|
|
8796
|
+
names() {
|
|
8797
|
+
return [...this.factories.keys()];
|
|
8798
|
+
}
|
|
8799
|
+
}
|
|
8800
|
+
var JOB_REGISTRY_KEY = Symbol.for("@getstrata/jobRegistry");
|
|
8801
|
+
function readSharedJobRegistry() {
|
|
8802
|
+
const globalRegistry = globalThis[JOB_REGISTRY_KEY];
|
|
8803
|
+
if (globalRegistry) {
|
|
8804
|
+
return globalRegistry;
|
|
8805
|
+
}
|
|
8806
|
+
const registry = new JobRegistry;
|
|
8807
|
+
globalThis[JOB_REGISTRY_KEY] = registry;
|
|
8808
|
+
return registry;
|
|
8809
|
+
}
|
|
8810
|
+
var jobRegistry = readSharedJobRegistry();
|
|
8587
8811
|
// ../../src/core/queue/failedJobTable.ts
|
|
8588
8812
|
var failedJobTable = defineTable({
|
|
8589
8813
|
name: "failed_job",
|
|
@@ -8644,43 +8868,6 @@ class FailedJobService {
|
|
|
8644
8868
|
}
|
|
8645
8869
|
var failedJobService_default = FailedJobService;
|
|
8646
8870
|
|
|
8647
|
-
// ../../src/core/queue/jobRegistry.ts
|
|
8648
|
-
class JobRegistry {
|
|
8649
|
-
factories = new Map;
|
|
8650
|
-
instances = new WeakMap;
|
|
8651
|
-
register(name, factory) {
|
|
8652
|
-
this.factories.set(name, factory);
|
|
8653
|
-
}
|
|
8654
|
-
resolveName(job) {
|
|
8655
|
-
return this.instances.get(job);
|
|
8656
|
-
}
|
|
8657
|
-
track(name, job) {
|
|
8658
|
-
this.instances.set(job, name);
|
|
8659
|
-
return job;
|
|
8660
|
-
}
|
|
8661
|
-
create(name) {
|
|
8662
|
-
const factory = this.factories.get(name);
|
|
8663
|
-
if (!factory) {
|
|
8664
|
-
return;
|
|
8665
|
-
}
|
|
8666
|
-
return factory();
|
|
8667
|
-
}
|
|
8668
|
-
names() {
|
|
8669
|
-
return [...this.factories.keys()];
|
|
8670
|
-
}
|
|
8671
|
-
}
|
|
8672
|
-
var JOB_REGISTRY_KEY = Symbol.for("@getstrata/jobRegistry");
|
|
8673
|
-
function readSharedJobRegistry() {
|
|
8674
|
-
const globalRegistry = globalThis[JOB_REGISTRY_KEY];
|
|
8675
|
-
if (globalRegistry) {
|
|
8676
|
-
return globalRegistry;
|
|
8677
|
-
}
|
|
8678
|
-
const registry = new JobRegistry;
|
|
8679
|
-
globalThis[JOB_REGISTRY_KEY] = registry;
|
|
8680
|
-
return registry;
|
|
8681
|
-
}
|
|
8682
|
-
var jobRegistry = readSharedJobRegistry();
|
|
8683
|
-
|
|
8684
8871
|
// ../../src/core/queue/queueConfig.ts
|
|
8685
8872
|
function resolveQueueConfig() {
|
|
8686
8873
|
const driver = process.env.QUEUE_DRIVER;
|
|
@@ -9027,20 +9214,131 @@ function isPublicReadsEnabled() {
|
|
|
9027
9214
|
function guestCanViewResource() {
|
|
9028
9215
|
return isPublicReadsEnabled();
|
|
9029
9216
|
}
|
|
9217
|
+
// ../../src/core/security/safeUrl.ts
|
|
9218
|
+
import { lookup as dnsLookupImpl } from "dns/promises";
|
|
9219
|
+
var dnsLookup = dnsLookupImpl;
|
|
9220
|
+
var BLOCKED_HOSTNAMES = new Set([
|
|
9221
|
+
"localhost",
|
|
9222
|
+
"127.0.0.1",
|
|
9223
|
+
"0.0.0.0",
|
|
9224
|
+
"::1",
|
|
9225
|
+
"metadata.google.internal"
|
|
9226
|
+
]);
|
|
9227
|
+
function isPrivateIpv4(hostname) {
|
|
9228
|
+
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(hostname);
|
|
9229
|
+
if (!match) {
|
|
9230
|
+
return false;
|
|
9231
|
+
}
|
|
9232
|
+
const octets = match.slice(1, 5).map((part) => Number.parseInt(part, 10));
|
|
9233
|
+
if (octets.some((octet) => octet < 0 || octet > 255)) {
|
|
9234
|
+
return true;
|
|
9235
|
+
}
|
|
9236
|
+
const [a = 0, b = 0] = octets;
|
|
9237
|
+
if (a === 10) {
|
|
9238
|
+
return true;
|
|
9239
|
+
}
|
|
9240
|
+
if (a === 127) {
|
|
9241
|
+
return true;
|
|
9242
|
+
}
|
|
9243
|
+
if (a === 0) {
|
|
9244
|
+
return true;
|
|
9245
|
+
}
|
|
9246
|
+
if (a === 169 && b === 254) {
|
|
9247
|
+
return true;
|
|
9248
|
+
}
|
|
9249
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
9250
|
+
return true;
|
|
9251
|
+
}
|
|
9252
|
+
if (a === 192 && b === 168) {
|
|
9253
|
+
return true;
|
|
9254
|
+
}
|
|
9255
|
+
return false;
|
|
9256
|
+
}
|
|
9257
|
+
function isBlockedHostname(hostname) {
|
|
9258
|
+
const normalized = hostname.trim().toLowerCase();
|
|
9259
|
+
if (normalized.length === 0) {
|
|
9260
|
+
return true;
|
|
9261
|
+
}
|
|
9262
|
+
if (BLOCKED_HOSTNAMES.has(normalized)) {
|
|
9263
|
+
return true;
|
|
9264
|
+
}
|
|
9265
|
+
if (normalized.endsWith(".local") || normalized.endsWith(".internal")) {
|
|
9266
|
+
return true;
|
|
9267
|
+
}
|
|
9268
|
+
if (normalized.includes(":")) {
|
|
9269
|
+
return true;
|
|
9270
|
+
}
|
|
9271
|
+
return isPrivateIpv4(normalized);
|
|
9272
|
+
}
|
|
9273
|
+
function assertSafeOutboundUrl(rawUrl, options = {}) {
|
|
9274
|
+
let parsed;
|
|
9275
|
+
try {
|
|
9276
|
+
parsed = new URL(rawUrl);
|
|
9277
|
+
} catch {
|
|
9278
|
+
throw new BadRequestError("Webhook URL is invalid.");
|
|
9279
|
+
}
|
|
9280
|
+
if (parsed.protocol !== "https:" && !(options.allowHttp && parsed.protocol === "http:")) {
|
|
9281
|
+
throw new BadRequestError("Webhook URL must use HTTPS.");
|
|
9282
|
+
}
|
|
9283
|
+
if (parsed.username || parsed.password) {
|
|
9284
|
+
throw new BadRequestError("Webhook URL must not include credentials.");
|
|
9285
|
+
}
|
|
9286
|
+
if (isBlockedHostname(parsed.hostname)) {
|
|
9287
|
+
throw new BadRequestError("Webhook URL targets a blocked host.");
|
|
9288
|
+
}
|
|
9289
|
+
return parsed;
|
|
9290
|
+
}
|
|
9291
|
+
function isBlockedIpAddress(address) {
|
|
9292
|
+
return isBlockedHostname(address.trim().toLowerCase());
|
|
9293
|
+
}
|
|
9294
|
+
async function assertSafeOutboundUrlResolved(rawUrl, options = {}) {
|
|
9295
|
+
const parsed = assertSafeOutboundUrl(rawUrl, options);
|
|
9296
|
+
if (options.resolveDns === false) {
|
|
9297
|
+
return parsed;
|
|
9298
|
+
}
|
|
9299
|
+
const hostname = parsed.hostname.trim().toLowerCase();
|
|
9300
|
+
const results = await dnsLookup(hostname, { all: true, verbatim: true });
|
|
9301
|
+
if (results.some((result) => isBlockedIpAddress(result.address))) {
|
|
9302
|
+
throw new BadRequestError("Webhook URL targets a blocked host.");
|
|
9303
|
+
}
|
|
9304
|
+
return parsed;
|
|
9305
|
+
}
|
|
9306
|
+
function setDnsLookupForTests(lookupFn) {
|
|
9307
|
+
dnsLookup = lookupFn;
|
|
9308
|
+
}
|
|
9309
|
+
function resetDnsLookupForTests() {
|
|
9310
|
+
dnsLookup = dnsLookupImpl;
|
|
9311
|
+
}
|
|
9030
9312
|
// ../../src/core/tenant/tenantMiddleware.ts
|
|
9031
9313
|
import { createHash } from "crypto";
|
|
9032
9314
|
|
|
9033
9315
|
// ../../src/core/tenant/databaseTenantContext.ts
|
|
9316
|
+
async function applyBypassToTransaction(transaction, bypass) {
|
|
9317
|
+
await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
|
|
9318
|
+
bypass ? "true" : "false"
|
|
9319
|
+
]);
|
|
9320
|
+
}
|
|
9034
9321
|
async function runWithMigrationBypass(callback) {
|
|
9035
9322
|
if (!isRlsTenancy()) {
|
|
9036
9323
|
return await callback();
|
|
9037
9324
|
}
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9325
|
+
if (hasActiveDatabaseConnection()) {
|
|
9326
|
+
const activeConnection = getActiveDatabaseConnection(getDefaultDatabasePool());
|
|
9327
|
+
await applyBypassToTransaction(activeConnection, true);
|
|
9328
|
+
try {
|
|
9329
|
+
return await callback();
|
|
9330
|
+
} finally {
|
|
9331
|
+
await applyBypassToTransaction(activeConnection, false);
|
|
9332
|
+
}
|
|
9043
9333
|
}
|
|
9334
|
+
const pool = getDefaultDatabasePool();
|
|
9335
|
+
if (typeof pool.begin !== "function") {
|
|
9336
|
+
throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
|
|
9337
|
+
}
|
|
9338
|
+
return await pool.begin(async (transaction) => {
|
|
9339
|
+
await applyBypassToTransaction(transaction, true);
|
|
9340
|
+
return await runWithDatabaseConnection(transaction, callback);
|
|
9341
|
+
});
|
|
9044
9342
|
}
|
|
9045
9343
|
|
|
9046
9344
|
// ../../src/core/tenant/tenantMiddleware.ts
|
|
@@ -9608,6 +9906,7 @@ export {
|
|
|
9608
9906
|
CompositeGuard,
|
|
9609
9907
|
ConfigStore,
|
|
9610
9908
|
ConflictError,
|
|
9909
|
+
DEFAULT_PER_PAGE,
|
|
9611
9910
|
DEFAULT_TENANT,
|
|
9612
9911
|
DEFAULT_VIEWS_DIRECTORY,
|
|
9613
9912
|
DatabaseTokenGuard,
|
|
@@ -9620,15 +9919,19 @@ export {
|
|
|
9620
9919
|
ForeignIdColumnDefinition,
|
|
9621
9920
|
FormRequest,
|
|
9622
9921
|
GuestGuard,
|
|
9922
|
+
HTMX_2_0_4_INDICATOR_STYLE_HASH,
|
|
9623
9923
|
HasManyRelationQuery,
|
|
9924
|
+
HasManyThroughRelationQuery,
|
|
9624
9925
|
HasOneRelationQuery,
|
|
9625
9926
|
HttpError,
|
|
9626
9927
|
InternalServerError,
|
|
9627
9928
|
Job,
|
|
9929
|
+
JobRegistry,
|
|
9628
9930
|
JsonResource,
|
|
9629
9931
|
JwtGuard,
|
|
9630
9932
|
LocalStorageDriver,
|
|
9631
9933
|
LogMailDriver,
|
|
9934
|
+
MAX_PER_PAGE,
|
|
9632
9935
|
Mailer,
|
|
9633
9936
|
membershipService_default as MembershipService,
|
|
9634
9937
|
Model,
|
|
@@ -9646,6 +9949,7 @@ export {
|
|
|
9646
9949
|
PostgresGrammar,
|
|
9647
9950
|
PreconditionFailedError,
|
|
9648
9951
|
PrometheusRegistry,
|
|
9952
|
+
QueryFormRequest,
|
|
9649
9953
|
QueueWorker,
|
|
9650
9954
|
RedisQueue,
|
|
9651
9955
|
RepositoryQuery,
|
|
@@ -9664,7 +9968,15 @@ export {
|
|
|
9664
9968
|
WebFormRequest,
|
|
9665
9969
|
WhereBuilder,
|
|
9666
9970
|
absoluteTemporarySignedUrl,
|
|
9971
|
+
apiPrefix,
|
|
9972
|
+
appCookieName,
|
|
9973
|
+
appDevSecret,
|
|
9974
|
+
appDisplayName,
|
|
9975
|
+
appEnv,
|
|
9976
|
+
appKeyPrefix,
|
|
9667
9977
|
appSchedule,
|
|
9978
|
+
appUrl,
|
|
9979
|
+
appUserAgent,
|
|
9668
9980
|
appendOrganizationScope,
|
|
9669
9981
|
appendProjectScope,
|
|
9670
9982
|
applyCasts,
|
|
@@ -9673,6 +9985,8 @@ export {
|
|
|
9673
9985
|
assertIfMatch,
|
|
9674
9986
|
assertOrganizationReadable,
|
|
9675
9987
|
assertResourceInCurrentTenant,
|
|
9988
|
+
assertSafeOutboundUrl,
|
|
9989
|
+
assertSafeOutboundUrlResolved,
|
|
9676
9990
|
assertValidSignature,
|
|
9677
9991
|
auditChecksum,
|
|
9678
9992
|
auth,
|
|
@@ -9682,13 +9996,29 @@ export {
|
|
|
9682
9996
|
bindBunSql,
|
|
9683
9997
|
bindDatabaseConnection,
|
|
9684
9998
|
bindRouteModel,
|
|
9999
|
+
buildAdvancedWhereClause,
|
|
10000
|
+
buildCountQuery,
|
|
10001
|
+
buildDeleteByIdQuery,
|
|
10002
|
+
buildGroupedCountQuery,
|
|
10003
|
+
buildInsertQuery,
|
|
10004
|
+
buildJoinClause,
|
|
9685
10005
|
buildMarkdownMailMessage,
|
|
10006
|
+
buildOrderByClause,
|
|
10007
|
+
buildPaginationMeta,
|
|
10008
|
+
buildProjectionQuery,
|
|
10009
|
+
buildQueryWhereClause,
|
|
9686
10010
|
buildRequestCacheKey,
|
|
10011
|
+
buildRestoreByIdQuery,
|
|
10012
|
+
buildSelectQuery,
|
|
9687
10013
|
buildSmtpPayload,
|
|
10014
|
+
buildSoftDeleteByIdQuery,
|
|
10015
|
+
buildUpdateQuery,
|
|
10016
|
+
buildWhereClause,
|
|
9688
10017
|
cache,
|
|
9689
10018
|
collectQueueMetrics,
|
|
9690
10019
|
compileBlueprint,
|
|
9691
10020
|
composeMiddleware,
|
|
10021
|
+
computeEtagFromJson,
|
|
9692
10022
|
conditionalJsonResponse,
|
|
9693
10023
|
config,
|
|
9694
10024
|
configureContentSecurityPolicy,
|
|
@@ -9710,6 +10040,7 @@ export {
|
|
|
9710
10040
|
createFlashMiddleware,
|
|
9711
10041
|
createLoginThrottleMiddleware,
|
|
9712
10042
|
createMembershipMiddleware,
|
|
10043
|
+
createMemoryLoginThrottleMiddleware,
|
|
9713
10044
|
createMemoryThrottleMiddleware,
|
|
9714
10045
|
createMetricsMiddleware,
|
|
9715
10046
|
createMysqlConnection,
|
|
@@ -9750,10 +10081,14 @@ export {
|
|
|
9750
10081
|
dialectFor,
|
|
9751
10082
|
emailRule,
|
|
9752
10083
|
emptyPaginateResult,
|
|
10084
|
+
envFlagEnabled,
|
|
10085
|
+
errorResponse,
|
|
9753
10086
|
errorTemplateName,
|
|
9754
10087
|
etagFromResource,
|
|
10088
|
+
etagValuesMatch,
|
|
9755
10089
|
eventBus,
|
|
9756
10090
|
events,
|
|
10091
|
+
expectObject,
|
|
9757
10092
|
filterMassAssignable,
|
|
9758
10093
|
foreignKeyFromTable,
|
|
9759
10094
|
formatAdminValue,
|
|
@@ -9765,10 +10100,13 @@ export {
|
|
|
9765
10100
|
getDefaultDatabaseQuery,
|
|
9766
10101
|
getMigrationStatus,
|
|
9767
10102
|
getNamedConnection,
|
|
10103
|
+
getQueryParams,
|
|
10104
|
+
getRouteParams,
|
|
9768
10105
|
grammarForDriver,
|
|
9769
10106
|
guestCanViewResource,
|
|
9770
10107
|
hasActiveDatabaseConnection,
|
|
9771
10108
|
hasMany,
|
|
10109
|
+
hasManyThrough,
|
|
9772
10110
|
hasMinimumOrgRole2 as hasMinimumOrgRole,
|
|
9773
10111
|
hasNamedConnection,
|
|
9774
10112
|
hasOne,
|
|
@@ -9777,20 +10115,26 @@ export {
|
|
|
9777
10115
|
htmlErrorResponse,
|
|
9778
10116
|
htmlResponse,
|
|
9779
10117
|
hydrateValue,
|
|
10118
|
+
ifMatchSatisfied,
|
|
10119
|
+
ifNoneMatchSatisfied,
|
|
9780
10120
|
indexBelongsToManyRelation,
|
|
9781
10121
|
indexBelongsToRelation,
|
|
9782
10122
|
indexHasManyRelation,
|
|
10123
|
+
indexHasManyThroughRelation,
|
|
9783
10124
|
indexHasOneRelation,
|
|
9784
10125
|
indexMorphManyRelation,
|
|
9785
10126
|
indexMorphOneRelation,
|
|
9786
10127
|
indexMorphToRelation,
|
|
9787
10128
|
inferReferencedTable,
|
|
9788
10129
|
installGracefulShutdownSignals,
|
|
10130
|
+
isBlockedHostname,
|
|
10131
|
+
isBlockedIpAddress,
|
|
9789
10132
|
isEtagEnabled,
|
|
9790
10133
|
isGlobalAdmin,
|
|
9791
10134
|
isHtmxRequest,
|
|
9792
10135
|
isHttpErrorLike,
|
|
9793
10136
|
isInsideTenantDatabaseScope,
|
|
10137
|
+
isProductionEnv,
|
|
9794
10138
|
isPublicReadsEnabled,
|
|
9795
10139
|
isRlsTenancy,
|
|
9796
10140
|
isTenancyEnabled,
|
|
@@ -9801,32 +10145,54 @@ export {
|
|
|
9801
10145
|
loadSeedersFromDirectory,
|
|
9802
10146
|
log,
|
|
9803
10147
|
logSecurityEvent,
|
|
10148
|
+
logServerError,
|
|
9804
10149
|
loginRedirectLocation,
|
|
9805
10150
|
mail,
|
|
9806
10151
|
mailer,
|
|
10152
|
+
mapDatabaseError,
|
|
9807
10153
|
markdownToHtml,
|
|
9808
10154
|
maxLength,
|
|
10155
|
+
membershipContext,
|
|
10156
|
+
membershipRepository,
|
|
9809
10157
|
migrateDatabase,
|
|
9810
10158
|
minLength,
|
|
9811
10159
|
modelEventName,
|
|
9812
10160
|
morphMany,
|
|
9813
10161
|
morphOne,
|
|
9814
10162
|
morphTo,
|
|
10163
|
+
namespacedRedisKey,
|
|
9815
10164
|
noContentResponse,
|
|
10165
|
+
normalizeFieldErrors,
|
|
9816
10166
|
normalizeMetricPath,
|
|
9817
10167
|
notFoundHtmlResponse,
|
|
10168
|
+
notModifiedResponse,
|
|
10169
|
+
otelServiceName,
|
|
9818
10170
|
paginatedResponse,
|
|
10171
|
+
parseJsonBody,
|
|
9819
10172
|
parseMultipartUpload,
|
|
10173
|
+
parseOptionalBooleanQueryParam,
|
|
10174
|
+
parseOptionalEnumQueryParam,
|
|
10175
|
+
parseOptionalPositiveIntQueryParam,
|
|
9820
10176
|
parsePaginationQuery,
|
|
9821
10177
|
parsePositiveIntParam,
|
|
10178
|
+
parseQualifiedColumn,
|
|
9822
10179
|
pivotTableName,
|
|
9823
10180
|
policyGate,
|
|
9824
10181
|
prometheusRegistry,
|
|
10182
|
+
qualifyColumn,
|
|
9825
10183
|
queue,
|
|
10184
|
+
quoteIdentifier,
|
|
9826
10185
|
rateLimitMultiplierForPlan,
|
|
9827
10186
|
readBunRequestCookie,
|
|
9828
10187
|
readClientIp,
|
|
10188
|
+
readOptionalEnum,
|
|
10189
|
+
readOptionalPositiveInt,
|
|
10190
|
+
readOptionalString,
|
|
9829
10191
|
readRequestCookie,
|
|
10192
|
+
readRequiredEnum,
|
|
10193
|
+
readRequiredPositiveInt,
|
|
10194
|
+
readRequiredString,
|
|
10195
|
+
readSharedEventBus,
|
|
9830
10196
|
readSubmittedCsrfToken,
|
|
9831
10197
|
readSubmittedCsrfTokenFromBody,
|
|
9832
10198
|
readTenancyDriver,
|
|
@@ -9838,11 +10204,20 @@ export {
|
|
|
9838
10204
|
registerShutdownHandler,
|
|
9839
10205
|
renderKernelErrorChrome,
|
|
9840
10206
|
renderMarkdownMail,
|
|
10207
|
+
renderWebErrorHtml,
|
|
9841
10208
|
repositoryConnection,
|
|
9842
10209
|
requestIdMiddleware,
|
|
10210
|
+
requestMetaContext,
|
|
10211
|
+
requireConfiguredSecret,
|
|
9843
10212
|
required,
|
|
9844
10213
|
resetBoundDatabaseConnection,
|
|
10214
|
+
resetContentSecurityPolicyForTests,
|
|
10215
|
+
resetDefaultDatabasePoolForTests,
|
|
9845
10216
|
resetDefaultStorage,
|
|
10217
|
+
resetDnsLookupForTests,
|
|
10218
|
+
resetGracefulShutdownForTests,
|
|
10219
|
+
resetMembershipLookupForTests,
|
|
10220
|
+
resetMemoryLoginThrottleForTests,
|
|
9846
10221
|
resetMemoryThrottleForTests,
|
|
9847
10222
|
resetNamedConnections,
|
|
9848
10223
|
resetSqlDialect,
|
|
@@ -9859,11 +10234,15 @@ export {
|
|
|
9859
10234
|
resolveCsrfTokenForRequest,
|
|
9860
10235
|
resolveDatabaseDriver,
|
|
9861
10236
|
resolveHtmlContentSecurityPolicy,
|
|
10237
|
+
resolveLoginEmail,
|
|
10238
|
+
resolveLoginIdentity,
|
|
9862
10239
|
resolveMembershipLookup,
|
|
9863
10240
|
resolveMembershipService,
|
|
9864
10241
|
resolveOrganizationScope,
|
|
10242
|
+
resolveQualifiedColumn,
|
|
9865
10243
|
resolveRepositoryConnection,
|
|
9866
10244
|
resolveService,
|
|
10245
|
+
resolveSoftDeleteColumn,
|
|
9867
10246
|
resolveUserId,
|
|
9868
10247
|
resolveUserTenantId,
|
|
9869
10248
|
resolveWebLayoutData,
|
|
@@ -9886,16 +10265,21 @@ export {
|
|
|
9886
10265
|
safeInternalRedirectPath,
|
|
9887
10266
|
sanitizeInternalPath,
|
|
9888
10267
|
sanitizeMailHtml,
|
|
10268
|
+
sanitizeUploadFileName,
|
|
9889
10269
|
scopedOrganizationIds,
|
|
10270
|
+
sdkClientClassName,
|
|
9890
10271
|
securedBindRouteModel,
|
|
9891
10272
|
securedBindRouteModelByKey,
|
|
9892
10273
|
sendMarkdownMail,
|
|
9893
10274
|
serializeDate,
|
|
9894
10275
|
serverHtmxContentSecurityPolicy,
|
|
9895
10276
|
setActiveApplicationContext,
|
|
10277
|
+
setDnsLookupForTests,
|
|
10278
|
+
siemEventType,
|
|
9896
10279
|
signJwt,
|
|
9897
10280
|
signedUrl,
|
|
9898
10281
|
singularize,
|
|
10282
|
+
smtpEhloHost,
|
|
9899
10283
|
spaContentSecurityPolicy,
|
|
9900
10284
|
sqlTimestamp,
|
|
9901
10285
|
storageFacade as storage,
|
|
@@ -9903,17 +10287,22 @@ export {
|
|
|
9903
10287
|
stringRule,
|
|
9904
10288
|
stripMarkdown,
|
|
9905
10289
|
temporarySignedUrl,
|
|
10290
|
+
tenantContext,
|
|
9906
10291
|
textResponse,
|
|
9907
10292
|
toHttpError,
|
|
9908
10293
|
toPaginatedResourceCollection,
|
|
9909
10294
|
toResourceCollection,
|
|
10295
|
+
traceContextStorage,
|
|
9910
10296
|
trustForwardedFor,
|
|
9911
10297
|
unregisterNamedConnection,
|
|
9912
10298
|
useSqlDialect,
|
|
9913
10299
|
validateObject,
|
|
9914
10300
|
verifyCsrfToken,
|
|
9915
10301
|
verifyJwt,
|
|
10302
|
+
webErrorResponse,
|
|
10303
|
+
webhookSignatureHeader,
|
|
9916
10304
|
whenLoaded,
|
|
10305
|
+
withDatabaseErrorHandling,
|
|
9917
10306
|
withErrorHandling,
|
|
9918
10307
|
withMiddleware,
|
|
9919
10308
|
withMigrationLock,
|