@getstrata/core 1.0.3 → 1.0.5
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 +14 -0
- package/README.md +1 -1
- 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/database/mysqlConnection.js +1 -132
- 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 +28 -19
- package/dist/index.js +448 -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);
|
|
@@ -5226,6 +5306,11 @@ var importMysql = defaultImportMysql;
|
|
|
5226
5306
|
async function defaultImportMysql() {
|
|
5227
5307
|
return import("mysql2/promise");
|
|
5228
5308
|
}
|
|
5309
|
+
function resetMysqlLoaderForTests(importer) {
|
|
5310
|
+
mysqlModule = undefined;
|
|
5311
|
+
mysqlPending = undefined;
|
|
5312
|
+
importMysql = importer ? async () => await importer() : defaultImportMysql;
|
|
5313
|
+
}
|
|
5229
5314
|
function mysqlApi(mod) {
|
|
5230
5315
|
if (typeof mod.createPool === "function") {
|
|
5231
5316
|
return mod;
|
|
@@ -6643,6 +6728,9 @@ function generateCspNonce() {
|
|
|
6643
6728
|
function configureContentSecurityPolicy(options) {
|
|
6644
6729
|
configuredHtmlOptions = { ...options };
|
|
6645
6730
|
}
|
|
6731
|
+
function resetContentSecurityPolicyForTests() {
|
|
6732
|
+
configuredHtmlOptions = {};
|
|
6733
|
+
}
|
|
6646
6734
|
function cloneDirectives(source) {
|
|
6647
6735
|
const copy = {};
|
|
6648
6736
|
for (const [directive, values] of Object.entries(source)) {
|
|
@@ -6753,11 +6841,6 @@ function readRequestCookie(request, name) {
|
|
|
6753
6841
|
function readBunRequestCookie(request, name) {
|
|
6754
6842
|
return request.cookies.get(name) ?? readRequestCookie(request, name);
|
|
6755
6843
|
}
|
|
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
6844
|
// ../../src/core/http/corsMiddleware.ts
|
|
6762
6845
|
function defaultAllowedOrigins() {
|
|
6763
6846
|
return isProductionEnv() ? "" : "*";
|
|
@@ -6823,7 +6906,7 @@ function csrfCookieName() {
|
|
|
6823
6906
|
return process.env.CSRF_COOKIE_NAME?.trim() || appCookieName("csrf");
|
|
6824
6907
|
}
|
|
6825
6908
|
function resolveCsrfSecret() {
|
|
6826
|
-
return
|
|
6909
|
+
return requireConfiguredSecret(["SESSION_SECRET", "OAUTH_STATE_SECRET", "ADMIN_API_TOKEN"], "csrf-secret");
|
|
6827
6910
|
}
|
|
6828
6911
|
function csrfVerifyOptions() {
|
|
6829
6912
|
return { secret: resolveCsrfSecret(), maxAge: CSRF_TTL_MS };
|
|
@@ -6838,7 +6921,7 @@ function tokensMatch(left, right) {
|
|
|
6838
6921
|
}
|
|
6839
6922
|
function createCsrfTokenCookie() {
|
|
6840
6923
|
const token = Bun.CSRF.generate(resolveCsrfSecret(), { expiresIn: CSRF_TTL_MS });
|
|
6841
|
-
const secure =
|
|
6924
|
+
const secure = isProductionEnv() ? "; Secure" : "";
|
|
6842
6925
|
return {
|
|
6843
6926
|
token,
|
|
6844
6927
|
cookie: `${csrfCookieName()}=${encodeURIComponent(token)}; Path=/; SameSite=Lax; Max-Age=${Math.floor(CSRF_TTL_MS / 1000)}${secure}`
|
|
@@ -6958,7 +7041,7 @@ function flashCookieName() {
|
|
|
6958
7041
|
return process.env.FLASH_COOKIE_NAME?.trim() || appCookieName("flash");
|
|
6959
7042
|
}
|
|
6960
7043
|
function resolveFlashSecret() {
|
|
6961
|
-
return
|
|
7044
|
+
return requireConfiguredSecret(["SESSION_SECRET", "OAUTH_STATE_SECRET"], "flash-secret");
|
|
6962
7045
|
}
|
|
6963
7046
|
function signFlashPayload(payload, issuedAt) {
|
|
6964
7047
|
const signature = createHmac2("sha256", resolveFlashSecret()).update(`${payload}.${issuedAt}`).digest("hex");
|
|
@@ -7068,6 +7151,49 @@ function getQueryParams(request) {
|
|
|
7068
7151
|
}
|
|
7069
7152
|
return new URL(request.url).searchParams;
|
|
7070
7153
|
}
|
|
7154
|
+
function parseOptionalPositiveIntQueryParam(params, name) {
|
|
7155
|
+
const value = params.get(name);
|
|
7156
|
+
if (value === null || value.trim() === "") {
|
|
7157
|
+
return;
|
|
7158
|
+
}
|
|
7159
|
+
const parsed = Number.parseInt(value, 10);
|
|
7160
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
7161
|
+
throw new BadRequestError(`Invalid query parameter "${name}". Expected a positive integer.`);
|
|
7162
|
+
}
|
|
7163
|
+
return parsed;
|
|
7164
|
+
}
|
|
7165
|
+
function parseOptionalBooleanQueryParam(params, name) {
|
|
7166
|
+
const value = params.get(name);
|
|
7167
|
+
if (value === null || value.trim() === "") {
|
|
7168
|
+
return;
|
|
7169
|
+
}
|
|
7170
|
+
switch (value.toLowerCase()) {
|
|
7171
|
+
case "true":
|
|
7172
|
+
case "1":
|
|
7173
|
+
return true;
|
|
7174
|
+
case "false":
|
|
7175
|
+
case "0":
|
|
7176
|
+
return false;
|
|
7177
|
+
default:
|
|
7178
|
+
throw new BadRequestError(`Invalid query parameter "${name}". Expected a boolean.`);
|
|
7179
|
+
}
|
|
7180
|
+
}
|
|
7181
|
+
function parseOptionalEnumQueryParam(params, name, allowedValues) {
|
|
7182
|
+
const value = params.get(name);
|
|
7183
|
+
if (value === null || value.trim() === "") {
|
|
7184
|
+
return;
|
|
7185
|
+
}
|
|
7186
|
+
if (!allowedValues.includes(value)) {
|
|
7187
|
+
throw new BadRequestError(`Invalid query parameter "${name}". Expected one of: ${allowedValues.join(", ")}.`);
|
|
7188
|
+
}
|
|
7189
|
+
return value;
|
|
7190
|
+
}
|
|
7191
|
+
function expectObject(value, label = "request body") {
|
|
7192
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
7193
|
+
throw new BadRequestError(`${label} must be a JSON object.`);
|
|
7194
|
+
}
|
|
7195
|
+
return value;
|
|
7196
|
+
}
|
|
7071
7197
|
async function parseJsonBody(request, validator) {
|
|
7072
7198
|
let payload;
|
|
7073
7199
|
try {
|
|
@@ -7077,6 +7203,55 @@ async function parseJsonBody(request, validator) {
|
|
|
7077
7203
|
}
|
|
7078
7204
|
return validator(payload);
|
|
7079
7205
|
}
|
|
7206
|
+
function readRequiredString(payload, field, options = {}) {
|
|
7207
|
+
const value = payload[field];
|
|
7208
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
7209
|
+
throw new BadRequestError(`"${field}" is required and must be a string.`);
|
|
7210
|
+
}
|
|
7211
|
+
const trimmed = value.trim();
|
|
7212
|
+
if (options.minLength !== undefined && trimmed.length < options.minLength) {
|
|
7213
|
+
throw new BadRequestError(`"${field}" must be at least ${options.minLength} characters.`);
|
|
7214
|
+
}
|
|
7215
|
+
if (options.maxLength !== undefined && trimmed.length > options.maxLength) {
|
|
7216
|
+
throw new BadRequestError(`"${field}" must be at most ${options.maxLength} characters.`);
|
|
7217
|
+
}
|
|
7218
|
+
if (options.pattern && !options.pattern.test(trimmed)) {
|
|
7219
|
+
throw new BadRequestError(`"${field}" has an invalid format.`);
|
|
7220
|
+
}
|
|
7221
|
+
return trimmed;
|
|
7222
|
+
}
|
|
7223
|
+
function readOptionalString(payload, field, options = {}) {
|
|
7224
|
+
if (!(field in payload) || payload[field] === undefined) {
|
|
7225
|
+
return;
|
|
7226
|
+
}
|
|
7227
|
+
return readRequiredString(payload, field, options);
|
|
7228
|
+
}
|
|
7229
|
+
function readRequiredEnum(payload, field, allowedValues) {
|
|
7230
|
+
const value = readRequiredString(payload, field);
|
|
7231
|
+
if (!allowedValues.includes(value)) {
|
|
7232
|
+
throw new BadRequestError(`"${field}" must be one of: ${allowedValues.join(", ")}.`);
|
|
7233
|
+
}
|
|
7234
|
+
return value;
|
|
7235
|
+
}
|
|
7236
|
+
function readOptionalEnum(payload, field, allowedValues) {
|
|
7237
|
+
if (!(field in payload) || payload[field] === undefined) {
|
|
7238
|
+
return;
|
|
7239
|
+
}
|
|
7240
|
+
return readRequiredEnum(payload, field, allowedValues);
|
|
7241
|
+
}
|
|
7242
|
+
function readRequiredPositiveInt(payload, field) {
|
|
7243
|
+
const value = payload[field];
|
|
7244
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
7245
|
+
throw new BadRequestError(`"${field}" is required and must be a positive integer.`);
|
|
7246
|
+
}
|
|
7247
|
+
return value;
|
|
7248
|
+
}
|
|
7249
|
+
function readOptionalPositiveInt(payload, field) {
|
|
7250
|
+
if (!(field in payload) || payload[field] === undefined) {
|
|
7251
|
+
return;
|
|
7252
|
+
}
|
|
7253
|
+
return readRequiredPositiveInt(payload, field);
|
|
7254
|
+
}
|
|
7080
7255
|
function parsePositiveIntParam(value, name = "id") {
|
|
7081
7256
|
const parsed = Number.parseInt(value, 10);
|
|
7082
7257
|
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
@@ -7097,6 +7272,12 @@ class FormRequest {
|
|
|
7097
7272
|
return await parseJsonBody(request, (payload) => this.parse(payload));
|
|
7098
7273
|
}
|
|
7099
7274
|
}
|
|
7275
|
+
|
|
7276
|
+
class QueryFormRequest {
|
|
7277
|
+
validate(request) {
|
|
7278
|
+
return this.parseQuery(request);
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7100
7281
|
// ../../src/core/http/authMiddleware.ts
|
|
7101
7282
|
function createAuthMiddleware(auth) {
|
|
7102
7283
|
return async (request, next) => {
|
|
@@ -7659,6 +7840,10 @@ function withErrorHandling(handler) {
|
|
|
7659
7840
|
}
|
|
7660
7841
|
};
|
|
7661
7842
|
}
|
|
7843
|
+
// ../../src/core/http/route.ts
|
|
7844
|
+
function getRouteParams(request) {
|
|
7845
|
+
return request.params;
|
|
7846
|
+
}
|
|
7662
7847
|
// ../../src/core/http/routeMiddleware.ts
|
|
7663
7848
|
function withMiddleware(...middleware) {
|
|
7664
7849
|
const wrap = composeMiddleware(...middleware);
|
|
@@ -7832,6 +8017,9 @@ function createLoginThrottleMiddleware(options) {
|
|
|
7832
8017
|
}
|
|
7833
8018
|
return createMemoryLoginThrottleMiddleware(options);
|
|
7834
8019
|
}
|
|
8020
|
+
function resetMemoryLoginThrottleForTests() {
|
|
8021
|
+
memoryLoginBuckets.clear();
|
|
8022
|
+
}
|
|
7835
8023
|
// ../../src/core/http/memoryThrottleMiddleware.ts
|
|
7836
8024
|
var throttleBucketRegistries = new Set;
|
|
7837
8025
|
function createMemoryThrottleMiddleware(options) {
|
|
@@ -8019,7 +8207,7 @@ function intendedUrlTtlSeconds() {
|
|
|
8019
8207
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_INTENDED_URL_TTL_SECONDS;
|
|
8020
8208
|
}
|
|
8021
8209
|
function cookieSecureFlag() {
|
|
8022
|
-
return
|
|
8210
|
+
return isProductionEnv() ? "; Secure" : "";
|
|
8023
8211
|
}
|
|
8024
8212
|
function pathnameOf(path) {
|
|
8025
8213
|
const pathname = path.split("?")[0] ?? path;
|
|
@@ -8140,7 +8328,7 @@ function createSecurityHeadersMiddleware(options = {}) {
|
|
|
8140
8328
|
// ../../src/core/http/signedUrl.ts
|
|
8141
8329
|
import { createHmac as createHmac3 } from "crypto";
|
|
8142
8330
|
function resolveSignedUrlSecret() {
|
|
8143
|
-
return
|
|
8331
|
+
return requireConfiguredSecret(["SIGNED_URL_SECRET", "SESSION_SECRET", "OAUTH_STATE_SECRET"], "signed-url-secret");
|
|
8144
8332
|
}
|
|
8145
8333
|
function resolveSignedUrlOrigin() {
|
|
8146
8334
|
return (process.env.APP_URL ?? "http://localhost:3000").replace(/\/$/, "");
|
|
@@ -8339,6 +8527,11 @@ function installGracefulShutdownSignals(signals = ["SIGINT", "SIGTERM"]) {
|
|
|
8339
8527
|
});
|
|
8340
8528
|
}
|
|
8341
8529
|
}
|
|
8530
|
+
function resetGracefulShutdownForTests() {
|
|
8531
|
+
shutdownHandlers.clear();
|
|
8532
|
+
shutdownInstalled = false;
|
|
8533
|
+
shuttingDown = false;
|
|
8534
|
+
}
|
|
8342
8535
|
// ../../src/core/logging/requestLoggingMiddleware.ts
|
|
8343
8536
|
function createRequestLoggingMiddleware() {
|
|
8344
8537
|
return async (request, next) => {
|
|
@@ -8584,6 +8777,42 @@ class AsyncQueue {
|
|
|
8584
8777
|
function createQueue(driver) {
|
|
8585
8778
|
return driver === "async" ? new AsyncQueue : new SyncQueue;
|
|
8586
8779
|
}
|
|
8780
|
+
// ../../src/core/queue/jobRegistry.ts
|
|
8781
|
+
class JobRegistry {
|
|
8782
|
+
factories = new Map;
|
|
8783
|
+
instances = new WeakMap;
|
|
8784
|
+
register(name, factory) {
|
|
8785
|
+
this.factories.set(name, factory);
|
|
8786
|
+
}
|
|
8787
|
+
resolveName(job) {
|
|
8788
|
+
return this.instances.get(job);
|
|
8789
|
+
}
|
|
8790
|
+
track(name, job) {
|
|
8791
|
+
this.instances.set(job, name);
|
|
8792
|
+
return job;
|
|
8793
|
+
}
|
|
8794
|
+
create(name) {
|
|
8795
|
+
const factory = this.factories.get(name);
|
|
8796
|
+
if (!factory) {
|
|
8797
|
+
return;
|
|
8798
|
+
}
|
|
8799
|
+
return factory();
|
|
8800
|
+
}
|
|
8801
|
+
names() {
|
|
8802
|
+
return [...this.factories.keys()];
|
|
8803
|
+
}
|
|
8804
|
+
}
|
|
8805
|
+
var JOB_REGISTRY_KEY = Symbol.for("@getstrata/jobRegistry");
|
|
8806
|
+
function readSharedJobRegistry() {
|
|
8807
|
+
const globalRegistry = globalThis[JOB_REGISTRY_KEY];
|
|
8808
|
+
if (globalRegistry) {
|
|
8809
|
+
return globalRegistry;
|
|
8810
|
+
}
|
|
8811
|
+
const registry = new JobRegistry;
|
|
8812
|
+
globalThis[JOB_REGISTRY_KEY] = registry;
|
|
8813
|
+
return registry;
|
|
8814
|
+
}
|
|
8815
|
+
var jobRegistry = readSharedJobRegistry();
|
|
8587
8816
|
// ../../src/core/queue/failedJobTable.ts
|
|
8588
8817
|
var failedJobTable = defineTable({
|
|
8589
8818
|
name: "failed_job",
|
|
@@ -8644,43 +8873,6 @@ class FailedJobService {
|
|
|
8644
8873
|
}
|
|
8645
8874
|
var failedJobService_default = FailedJobService;
|
|
8646
8875
|
|
|
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
8876
|
// ../../src/core/queue/queueConfig.ts
|
|
8685
8877
|
function resolveQueueConfig() {
|
|
8686
8878
|
const driver = process.env.QUEUE_DRIVER;
|
|
@@ -9027,20 +9219,131 @@ function isPublicReadsEnabled() {
|
|
|
9027
9219
|
function guestCanViewResource() {
|
|
9028
9220
|
return isPublicReadsEnabled();
|
|
9029
9221
|
}
|
|
9222
|
+
// ../../src/core/security/safeUrl.ts
|
|
9223
|
+
import { lookup as dnsLookupImpl } from "dns/promises";
|
|
9224
|
+
var dnsLookup = dnsLookupImpl;
|
|
9225
|
+
var BLOCKED_HOSTNAMES = new Set([
|
|
9226
|
+
"localhost",
|
|
9227
|
+
"127.0.0.1",
|
|
9228
|
+
"0.0.0.0",
|
|
9229
|
+
"::1",
|
|
9230
|
+
"metadata.google.internal"
|
|
9231
|
+
]);
|
|
9232
|
+
function isPrivateIpv4(hostname) {
|
|
9233
|
+
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(hostname);
|
|
9234
|
+
if (!match) {
|
|
9235
|
+
return false;
|
|
9236
|
+
}
|
|
9237
|
+
const octets = match.slice(1, 5).map((part) => Number.parseInt(part, 10));
|
|
9238
|
+
if (octets.some((octet) => octet < 0 || octet > 255)) {
|
|
9239
|
+
return true;
|
|
9240
|
+
}
|
|
9241
|
+
const [a = 0, b = 0] = octets;
|
|
9242
|
+
if (a === 10) {
|
|
9243
|
+
return true;
|
|
9244
|
+
}
|
|
9245
|
+
if (a === 127) {
|
|
9246
|
+
return true;
|
|
9247
|
+
}
|
|
9248
|
+
if (a === 0) {
|
|
9249
|
+
return true;
|
|
9250
|
+
}
|
|
9251
|
+
if (a === 169 && b === 254) {
|
|
9252
|
+
return true;
|
|
9253
|
+
}
|
|
9254
|
+
if (a === 172 && b >= 16 && b <= 31) {
|
|
9255
|
+
return true;
|
|
9256
|
+
}
|
|
9257
|
+
if (a === 192 && b === 168) {
|
|
9258
|
+
return true;
|
|
9259
|
+
}
|
|
9260
|
+
return false;
|
|
9261
|
+
}
|
|
9262
|
+
function isBlockedHostname(hostname) {
|
|
9263
|
+
const normalized = hostname.trim().toLowerCase();
|
|
9264
|
+
if (normalized.length === 0) {
|
|
9265
|
+
return true;
|
|
9266
|
+
}
|
|
9267
|
+
if (BLOCKED_HOSTNAMES.has(normalized)) {
|
|
9268
|
+
return true;
|
|
9269
|
+
}
|
|
9270
|
+
if (normalized.endsWith(".local") || normalized.endsWith(".internal")) {
|
|
9271
|
+
return true;
|
|
9272
|
+
}
|
|
9273
|
+
if (normalized.includes(":")) {
|
|
9274
|
+
return true;
|
|
9275
|
+
}
|
|
9276
|
+
return isPrivateIpv4(normalized);
|
|
9277
|
+
}
|
|
9278
|
+
function assertSafeOutboundUrl(rawUrl, options = {}) {
|
|
9279
|
+
let parsed;
|
|
9280
|
+
try {
|
|
9281
|
+
parsed = new URL(rawUrl);
|
|
9282
|
+
} catch {
|
|
9283
|
+
throw new BadRequestError("Webhook URL is invalid.");
|
|
9284
|
+
}
|
|
9285
|
+
if (parsed.protocol !== "https:" && !(options.allowHttp && parsed.protocol === "http:")) {
|
|
9286
|
+
throw new BadRequestError("Webhook URL must use HTTPS.");
|
|
9287
|
+
}
|
|
9288
|
+
if (parsed.username || parsed.password) {
|
|
9289
|
+
throw new BadRequestError("Webhook URL must not include credentials.");
|
|
9290
|
+
}
|
|
9291
|
+
if (isBlockedHostname(parsed.hostname)) {
|
|
9292
|
+
throw new BadRequestError("Webhook URL targets a blocked host.");
|
|
9293
|
+
}
|
|
9294
|
+
return parsed;
|
|
9295
|
+
}
|
|
9296
|
+
function isBlockedIpAddress(address) {
|
|
9297
|
+
return isBlockedHostname(address.trim().toLowerCase());
|
|
9298
|
+
}
|
|
9299
|
+
async function assertSafeOutboundUrlResolved(rawUrl, options = {}) {
|
|
9300
|
+
const parsed = assertSafeOutboundUrl(rawUrl, options);
|
|
9301
|
+
if (options.resolveDns === false) {
|
|
9302
|
+
return parsed;
|
|
9303
|
+
}
|
|
9304
|
+
const hostname = parsed.hostname.trim().toLowerCase();
|
|
9305
|
+
const results = await dnsLookup(hostname, { all: true, verbatim: true });
|
|
9306
|
+
if (results.some((result) => isBlockedIpAddress(result.address))) {
|
|
9307
|
+
throw new BadRequestError("Webhook URL targets a blocked host.");
|
|
9308
|
+
}
|
|
9309
|
+
return parsed;
|
|
9310
|
+
}
|
|
9311
|
+
function setDnsLookupForTests(lookupFn) {
|
|
9312
|
+
dnsLookup = lookupFn;
|
|
9313
|
+
}
|
|
9314
|
+
function resetDnsLookupForTests() {
|
|
9315
|
+
dnsLookup = dnsLookupImpl;
|
|
9316
|
+
}
|
|
9030
9317
|
// ../../src/core/tenant/tenantMiddleware.ts
|
|
9031
9318
|
import { createHash } from "crypto";
|
|
9032
9319
|
|
|
9033
9320
|
// ../../src/core/tenant/databaseTenantContext.ts
|
|
9321
|
+
async function applyBypassToTransaction(transaction, bypass) {
|
|
9322
|
+
await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, [
|
|
9323
|
+
bypass ? "true" : "false"
|
|
9324
|
+
]);
|
|
9325
|
+
}
|
|
9034
9326
|
async function runWithMigrationBypass(callback) {
|
|
9035
9327
|
if (!isRlsTenancy()) {
|
|
9036
9328
|
return await callback();
|
|
9037
9329
|
}
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9330
|
+
if (hasActiveDatabaseConnection()) {
|
|
9331
|
+
const activeConnection = getActiveDatabaseConnection(getDefaultDatabasePool());
|
|
9332
|
+
await applyBypassToTransaction(activeConnection, true);
|
|
9333
|
+
try {
|
|
9334
|
+
return await callback();
|
|
9335
|
+
} finally {
|
|
9336
|
+
await applyBypassToTransaction(activeConnection, false);
|
|
9337
|
+
}
|
|
9043
9338
|
}
|
|
9339
|
+
const pool = getDefaultDatabasePool();
|
|
9340
|
+
if (typeof pool.begin !== "function") {
|
|
9341
|
+
throw new Error("RLS migration bypass requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
|
|
9342
|
+
}
|
|
9343
|
+
return await pool.begin(async (transaction) => {
|
|
9344
|
+
await applyBypassToTransaction(transaction, true);
|
|
9345
|
+
return await runWithDatabaseConnection(transaction, callback);
|
|
9346
|
+
});
|
|
9044
9347
|
}
|
|
9045
9348
|
|
|
9046
9349
|
// ../../src/core/tenant/tenantMiddleware.ts
|
|
@@ -9608,6 +9911,7 @@ export {
|
|
|
9608
9911
|
CompositeGuard,
|
|
9609
9912
|
ConfigStore,
|
|
9610
9913
|
ConflictError,
|
|
9914
|
+
DEFAULT_PER_PAGE,
|
|
9611
9915
|
DEFAULT_TENANT,
|
|
9612
9916
|
DEFAULT_VIEWS_DIRECTORY,
|
|
9613
9917
|
DatabaseTokenGuard,
|
|
@@ -9620,15 +9924,19 @@ export {
|
|
|
9620
9924
|
ForeignIdColumnDefinition,
|
|
9621
9925
|
FormRequest,
|
|
9622
9926
|
GuestGuard,
|
|
9927
|
+
HTMX_2_0_4_INDICATOR_STYLE_HASH,
|
|
9623
9928
|
HasManyRelationQuery,
|
|
9929
|
+
HasManyThroughRelationQuery,
|
|
9624
9930
|
HasOneRelationQuery,
|
|
9625
9931
|
HttpError,
|
|
9626
9932
|
InternalServerError,
|
|
9627
9933
|
Job,
|
|
9934
|
+
JobRegistry,
|
|
9628
9935
|
JsonResource,
|
|
9629
9936
|
JwtGuard,
|
|
9630
9937
|
LocalStorageDriver,
|
|
9631
9938
|
LogMailDriver,
|
|
9939
|
+
MAX_PER_PAGE,
|
|
9632
9940
|
Mailer,
|
|
9633
9941
|
membershipService_default as MembershipService,
|
|
9634
9942
|
Model,
|
|
@@ -9646,6 +9954,7 @@ export {
|
|
|
9646
9954
|
PostgresGrammar,
|
|
9647
9955
|
PreconditionFailedError,
|
|
9648
9956
|
PrometheusRegistry,
|
|
9957
|
+
QueryFormRequest,
|
|
9649
9958
|
QueueWorker,
|
|
9650
9959
|
RedisQueue,
|
|
9651
9960
|
RepositoryQuery,
|
|
@@ -9664,7 +9973,15 @@ export {
|
|
|
9664
9973
|
WebFormRequest,
|
|
9665
9974
|
WhereBuilder,
|
|
9666
9975
|
absoluteTemporarySignedUrl,
|
|
9976
|
+
apiPrefix,
|
|
9977
|
+
appCookieName,
|
|
9978
|
+
appDevSecret,
|
|
9979
|
+
appDisplayName,
|
|
9980
|
+
appEnv,
|
|
9981
|
+
appKeyPrefix,
|
|
9667
9982
|
appSchedule,
|
|
9983
|
+
appUrl,
|
|
9984
|
+
appUserAgent,
|
|
9668
9985
|
appendOrganizationScope,
|
|
9669
9986
|
appendProjectScope,
|
|
9670
9987
|
applyCasts,
|
|
@@ -9673,6 +9990,8 @@ export {
|
|
|
9673
9990
|
assertIfMatch,
|
|
9674
9991
|
assertOrganizationReadable,
|
|
9675
9992
|
assertResourceInCurrentTenant,
|
|
9993
|
+
assertSafeOutboundUrl,
|
|
9994
|
+
assertSafeOutboundUrlResolved,
|
|
9676
9995
|
assertValidSignature,
|
|
9677
9996
|
auditChecksum,
|
|
9678
9997
|
auth,
|
|
@@ -9682,13 +10001,29 @@ export {
|
|
|
9682
10001
|
bindBunSql,
|
|
9683
10002
|
bindDatabaseConnection,
|
|
9684
10003
|
bindRouteModel,
|
|
10004
|
+
buildAdvancedWhereClause,
|
|
10005
|
+
buildCountQuery,
|
|
10006
|
+
buildDeleteByIdQuery,
|
|
10007
|
+
buildGroupedCountQuery,
|
|
10008
|
+
buildInsertQuery,
|
|
10009
|
+
buildJoinClause,
|
|
9685
10010
|
buildMarkdownMailMessage,
|
|
10011
|
+
buildOrderByClause,
|
|
10012
|
+
buildPaginationMeta,
|
|
10013
|
+
buildProjectionQuery,
|
|
10014
|
+
buildQueryWhereClause,
|
|
9686
10015
|
buildRequestCacheKey,
|
|
10016
|
+
buildRestoreByIdQuery,
|
|
10017
|
+
buildSelectQuery,
|
|
9687
10018
|
buildSmtpPayload,
|
|
10019
|
+
buildSoftDeleteByIdQuery,
|
|
10020
|
+
buildUpdateQuery,
|
|
10021
|
+
buildWhereClause,
|
|
9688
10022
|
cache,
|
|
9689
10023
|
collectQueueMetrics,
|
|
9690
10024
|
compileBlueprint,
|
|
9691
10025
|
composeMiddleware,
|
|
10026
|
+
computeEtagFromJson,
|
|
9692
10027
|
conditionalJsonResponse,
|
|
9693
10028
|
config,
|
|
9694
10029
|
configureContentSecurityPolicy,
|
|
@@ -9710,6 +10045,7 @@ export {
|
|
|
9710
10045
|
createFlashMiddleware,
|
|
9711
10046
|
createLoginThrottleMiddleware,
|
|
9712
10047
|
createMembershipMiddleware,
|
|
10048
|
+
createMemoryLoginThrottleMiddleware,
|
|
9713
10049
|
createMemoryThrottleMiddleware,
|
|
9714
10050
|
createMetricsMiddleware,
|
|
9715
10051
|
createMysqlConnection,
|
|
@@ -9750,10 +10086,14 @@ export {
|
|
|
9750
10086
|
dialectFor,
|
|
9751
10087
|
emailRule,
|
|
9752
10088
|
emptyPaginateResult,
|
|
10089
|
+
envFlagEnabled,
|
|
10090
|
+
errorResponse,
|
|
9753
10091
|
errorTemplateName,
|
|
9754
10092
|
etagFromResource,
|
|
10093
|
+
etagValuesMatch,
|
|
9755
10094
|
eventBus,
|
|
9756
10095
|
events,
|
|
10096
|
+
expectObject,
|
|
9757
10097
|
filterMassAssignable,
|
|
9758
10098
|
foreignKeyFromTable,
|
|
9759
10099
|
formatAdminValue,
|
|
@@ -9765,10 +10105,13 @@ export {
|
|
|
9765
10105
|
getDefaultDatabaseQuery,
|
|
9766
10106
|
getMigrationStatus,
|
|
9767
10107
|
getNamedConnection,
|
|
10108
|
+
getQueryParams,
|
|
10109
|
+
getRouteParams,
|
|
9768
10110
|
grammarForDriver,
|
|
9769
10111
|
guestCanViewResource,
|
|
9770
10112
|
hasActiveDatabaseConnection,
|
|
9771
10113
|
hasMany,
|
|
10114
|
+
hasManyThrough,
|
|
9772
10115
|
hasMinimumOrgRole2 as hasMinimumOrgRole,
|
|
9773
10116
|
hasNamedConnection,
|
|
9774
10117
|
hasOne,
|
|
@@ -9777,20 +10120,26 @@ export {
|
|
|
9777
10120
|
htmlErrorResponse,
|
|
9778
10121
|
htmlResponse,
|
|
9779
10122
|
hydrateValue,
|
|
10123
|
+
ifMatchSatisfied,
|
|
10124
|
+
ifNoneMatchSatisfied,
|
|
9780
10125
|
indexBelongsToManyRelation,
|
|
9781
10126
|
indexBelongsToRelation,
|
|
9782
10127
|
indexHasManyRelation,
|
|
10128
|
+
indexHasManyThroughRelation,
|
|
9783
10129
|
indexHasOneRelation,
|
|
9784
10130
|
indexMorphManyRelation,
|
|
9785
10131
|
indexMorphOneRelation,
|
|
9786
10132
|
indexMorphToRelation,
|
|
9787
10133
|
inferReferencedTable,
|
|
9788
10134
|
installGracefulShutdownSignals,
|
|
10135
|
+
isBlockedHostname,
|
|
10136
|
+
isBlockedIpAddress,
|
|
9789
10137
|
isEtagEnabled,
|
|
9790
10138
|
isGlobalAdmin,
|
|
9791
10139
|
isHtmxRequest,
|
|
9792
10140
|
isHttpErrorLike,
|
|
9793
10141
|
isInsideTenantDatabaseScope,
|
|
10142
|
+
isProductionEnv,
|
|
9794
10143
|
isPublicReadsEnabled,
|
|
9795
10144
|
isRlsTenancy,
|
|
9796
10145
|
isTenancyEnabled,
|
|
@@ -9801,32 +10150,54 @@ export {
|
|
|
9801
10150
|
loadSeedersFromDirectory,
|
|
9802
10151
|
log,
|
|
9803
10152
|
logSecurityEvent,
|
|
10153
|
+
logServerError,
|
|
9804
10154
|
loginRedirectLocation,
|
|
9805
10155
|
mail,
|
|
9806
10156
|
mailer,
|
|
10157
|
+
mapDatabaseError,
|
|
9807
10158
|
markdownToHtml,
|
|
9808
10159
|
maxLength,
|
|
10160
|
+
membershipContext,
|
|
10161
|
+
membershipRepository,
|
|
9809
10162
|
migrateDatabase,
|
|
9810
10163
|
minLength,
|
|
9811
10164
|
modelEventName,
|
|
9812
10165
|
morphMany,
|
|
9813
10166
|
morphOne,
|
|
9814
10167
|
morphTo,
|
|
10168
|
+
namespacedRedisKey,
|
|
9815
10169
|
noContentResponse,
|
|
10170
|
+
normalizeFieldErrors,
|
|
9816
10171
|
normalizeMetricPath,
|
|
9817
10172
|
notFoundHtmlResponse,
|
|
10173
|
+
notModifiedResponse,
|
|
10174
|
+
otelServiceName,
|
|
9818
10175
|
paginatedResponse,
|
|
10176
|
+
parseJsonBody,
|
|
9819
10177
|
parseMultipartUpload,
|
|
10178
|
+
parseOptionalBooleanQueryParam,
|
|
10179
|
+
parseOptionalEnumQueryParam,
|
|
10180
|
+
parseOptionalPositiveIntQueryParam,
|
|
9820
10181
|
parsePaginationQuery,
|
|
9821
10182
|
parsePositiveIntParam,
|
|
10183
|
+
parseQualifiedColumn,
|
|
9822
10184
|
pivotTableName,
|
|
9823
10185
|
policyGate,
|
|
9824
10186
|
prometheusRegistry,
|
|
10187
|
+
qualifyColumn,
|
|
9825
10188
|
queue,
|
|
10189
|
+
quoteIdentifier,
|
|
9826
10190
|
rateLimitMultiplierForPlan,
|
|
9827
10191
|
readBunRequestCookie,
|
|
9828
10192
|
readClientIp,
|
|
10193
|
+
readOptionalEnum,
|
|
10194
|
+
readOptionalPositiveInt,
|
|
10195
|
+
readOptionalString,
|
|
9829
10196
|
readRequestCookie,
|
|
10197
|
+
readRequiredEnum,
|
|
10198
|
+
readRequiredPositiveInt,
|
|
10199
|
+
readRequiredString,
|
|
10200
|
+
readSharedEventBus,
|
|
9830
10201
|
readSubmittedCsrfToken,
|
|
9831
10202
|
readSubmittedCsrfTokenFromBody,
|
|
9832
10203
|
readTenancyDriver,
|
|
@@ -9838,12 +10209,22 @@ export {
|
|
|
9838
10209
|
registerShutdownHandler,
|
|
9839
10210
|
renderKernelErrorChrome,
|
|
9840
10211
|
renderMarkdownMail,
|
|
10212
|
+
renderWebErrorHtml,
|
|
9841
10213
|
repositoryConnection,
|
|
9842
10214
|
requestIdMiddleware,
|
|
10215
|
+
requestMetaContext,
|
|
10216
|
+
requireConfiguredSecret,
|
|
9843
10217
|
required,
|
|
9844
10218
|
resetBoundDatabaseConnection,
|
|
10219
|
+
resetContentSecurityPolicyForTests,
|
|
10220
|
+
resetDefaultDatabasePoolForTests,
|
|
9845
10221
|
resetDefaultStorage,
|
|
10222
|
+
resetDnsLookupForTests,
|
|
10223
|
+
resetGracefulShutdownForTests,
|
|
10224
|
+
resetMembershipLookupForTests,
|
|
10225
|
+
resetMemoryLoginThrottleForTests,
|
|
9846
10226
|
resetMemoryThrottleForTests,
|
|
10227
|
+
resetMysqlLoaderForTests,
|
|
9847
10228
|
resetNamedConnections,
|
|
9848
10229
|
resetSqlDialect,
|
|
9849
10230
|
resolveApplicationAuth,
|
|
@@ -9859,11 +10240,15 @@ export {
|
|
|
9859
10240
|
resolveCsrfTokenForRequest,
|
|
9860
10241
|
resolveDatabaseDriver,
|
|
9861
10242
|
resolveHtmlContentSecurityPolicy,
|
|
10243
|
+
resolveLoginEmail,
|
|
10244
|
+
resolveLoginIdentity,
|
|
9862
10245
|
resolveMembershipLookup,
|
|
9863
10246
|
resolveMembershipService,
|
|
9864
10247
|
resolveOrganizationScope,
|
|
10248
|
+
resolveQualifiedColumn,
|
|
9865
10249
|
resolveRepositoryConnection,
|
|
9866
10250
|
resolveService,
|
|
10251
|
+
resolveSoftDeleteColumn,
|
|
9867
10252
|
resolveUserId,
|
|
9868
10253
|
resolveUserTenantId,
|
|
9869
10254
|
resolveWebLayoutData,
|
|
@@ -9886,16 +10271,21 @@ export {
|
|
|
9886
10271
|
safeInternalRedirectPath,
|
|
9887
10272
|
sanitizeInternalPath,
|
|
9888
10273
|
sanitizeMailHtml,
|
|
10274
|
+
sanitizeUploadFileName,
|
|
9889
10275
|
scopedOrganizationIds,
|
|
10276
|
+
sdkClientClassName,
|
|
9890
10277
|
securedBindRouteModel,
|
|
9891
10278
|
securedBindRouteModelByKey,
|
|
9892
10279
|
sendMarkdownMail,
|
|
9893
10280
|
serializeDate,
|
|
9894
10281
|
serverHtmxContentSecurityPolicy,
|
|
9895
10282
|
setActiveApplicationContext,
|
|
10283
|
+
setDnsLookupForTests,
|
|
10284
|
+
siemEventType,
|
|
9896
10285
|
signJwt,
|
|
9897
10286
|
signedUrl,
|
|
9898
10287
|
singularize,
|
|
10288
|
+
smtpEhloHost,
|
|
9899
10289
|
spaContentSecurityPolicy,
|
|
9900
10290
|
sqlTimestamp,
|
|
9901
10291
|
storageFacade as storage,
|
|
@@ -9903,17 +10293,22 @@ export {
|
|
|
9903
10293
|
stringRule,
|
|
9904
10294
|
stripMarkdown,
|
|
9905
10295
|
temporarySignedUrl,
|
|
10296
|
+
tenantContext,
|
|
9906
10297
|
textResponse,
|
|
9907
10298
|
toHttpError,
|
|
9908
10299
|
toPaginatedResourceCollection,
|
|
9909
10300
|
toResourceCollection,
|
|
10301
|
+
traceContextStorage,
|
|
9910
10302
|
trustForwardedFor,
|
|
9911
10303
|
unregisterNamedConnection,
|
|
9912
10304
|
useSqlDialect,
|
|
9913
10305
|
validateObject,
|
|
9914
10306
|
verifyCsrfToken,
|
|
9915
10307
|
verifyJwt,
|
|
10308
|
+
webErrorResponse,
|
|
10309
|
+
webhookSignatureHeader,
|
|
9916
10310
|
whenLoaded,
|
|
10311
|
+
withDatabaseErrorHandling,
|
|
9917
10312
|
withErrorHandling,
|
|
9918
10313
|
withMiddleware,
|
|
9919
10314
|
withMigrationLock,
|