@setzkasten-cms/astro-admin 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-routes/_auth-guard.d.ts +27 -3
- package/dist/api-routes/_auth-guard.js +5 -2
- package/dist/api-routes/_dev-session-secret.d.ts +8 -0
- package/dist/api-routes/_dev-session-secret.js +8 -0
- package/dist/api-routes/_github-token.js +1 -1
- package/dist/api-routes/_role-resolver.js +6 -3
- package/dist/api-routes/_session-secret.d.ts +19 -0
- package/dist/api-routes/_session-secret.js +7 -0
- package/dist/api-routes/_session-signing.d.ts +45 -0
- package/dist/api-routes/_session-signing.js +8 -0
- package/dist/api-routes/_webhook-dispatcher.js +4 -4
- package/dist/api-routes/asset-proxy.js +1 -1
- package/dist/api-routes/auth-callback.js +12 -5
- package/dist/api-routes/auth-logout.d.ts +4 -4
- package/dist/api-routes/auth-logout.js +8 -2
- package/dist/api-routes/auth-session.d.ts +6 -0
- package/dist/api-routes/auth-session.js +19 -19
- package/dist/api-routes/auth-setzkasten-login.js +14 -7
- package/dist/api-routes/catalog-add.js +59 -17
- package/dist/api-routes/catalog-export.js +14 -4
- package/dist/api-routes/config.d.ts +10 -3
- package/dist/api-routes/config.js +26 -4
- package/dist/api-routes/deploy-hook.js +8 -8
- package/dist/api-routes/editors.d.ts +1 -1
- package/dist/api-routes/editors.js +5 -2
- package/dist/api-routes/github-proxy.js +30 -8
- package/dist/api-routes/global-config.js +6 -3
- package/dist/api-routes/history-rollback.js +31 -14
- package/dist/api-routes/history-version.js +8 -6
- package/dist/api-routes/history.js +5 -2
- package/dist/api-routes/icons-local.js +1 -1
- package/dist/api-routes/init-add-section.js +150 -48
- package/dist/api-routes/init-apply.js +56 -42
- package/dist/api-routes/init-migrate.js +43 -36
- package/dist/api-routes/init-scan-page.d.ts +1 -1
- package/dist/api-routes/init-scan-page.js +59 -13
- package/dist/api-routes/init-scan.js +22 -7
- package/dist/api-routes/migrate-to-multi.js +5 -2
- package/dist/api-routes/pages.js +15 -4
- package/dist/api-routes/section-add.js +68 -16
- package/dist/api-routes/section-commit-pending.js +70 -22
- package/dist/api-routes/section-delete.js +49 -14
- package/dist/api-routes/section-duplicate.js +65 -16
- package/dist/api-routes/section-prepare-copy.js +15 -2
- package/dist/api-routes/section-prepare.js +25 -4
- package/dist/api-routes/setup-github-app-bounce.js +15 -1
- package/dist/api-routes/setup-github-app-branches.js +9 -6
- package/dist/api-routes/setup-github-app-callback.js +24 -1
- package/dist/api-routes/setup-github-app-credentials.d.ts +27 -0
- package/dist/api-routes/setup-github-app-credentials.js +43 -0
- package/dist/api-routes/setup-github-app-installed.js +22 -1
- package/dist/api-routes/setup-github-app-repos.js +5 -2
- package/dist/api-routes/setup-github-app.d.ts +4 -0
- package/dist/api-routes/setup-github-app.js +19 -2
- package/dist/api-routes/updater-register.js +7 -1
- package/dist/api-routes/webhooks-status.js +5 -2
- package/dist/api-routes/webhooks-test.js +9 -8
- package/dist/api-routes/webhooks.js +12 -14
- package/dist/api-routes/websites-add.js +5 -2
- package/dist/api-routes/websites-remove.js +5 -2
- package/dist/{chunk-ZQDGGWJP.js → chunk-5KMGSFCZ.js} +2 -2
- package/dist/{chunk-RHJONMLK.js → chunk-CDXCYYQR.js} +222 -5
- package/dist/{chunk-NKDATSPA.js → chunk-DP6RTINQ.js} +1 -1
- package/dist/chunk-KENFINT4.js +76 -0
- package/dist/chunk-ONP6BRZO.js +47 -0
- package/dist/{chunk-INIWFKQ3.js → chunk-Q5HV47DW.js} +33 -19
- package/dist/chunk-QVCW6EF3.js +26 -0
- package/dist/{chunk-K22A4ZBS.js → chunk-UHI6323G.js} +293 -174
- package/dist/{chunk-AM4DZXXM.js → chunk-UJAFZEX2.js} +76 -9
- package/package.json +12 -6
- package/src/api-routes/__tests__/_session-signing.test.ts +114 -0
- package/src/api-routes/__tests__/_session-test-helper.ts +27 -0
- package/src/api-routes/__tests__/add-section-helpers.test.ts +91 -97
- package/src/api-routes/__tests__/auth-guard.test.ts +46 -7
- package/src/api-routes/__tests__/catalog-api.test.ts +14 -6
- package/src/api-routes/__tests__/commit-trailers.test.ts +5 -5
- package/src/api-routes/__tests__/deferred-operations.test.ts +9 -12
- package/src/api-routes/__tests__/deploy-hook.test.ts +3 -8
- package/src/api-routes/__tests__/feature-gate.test.ts +1 -1
- package/src/api-routes/__tests__/github-cache.test.ts +1 -1
- package/src/api-routes/__tests__/github-token.test.ts +1 -1
- package/src/api-routes/__tests__/global-config-theme.test.ts +4 -4
- package/src/api-routes/__tests__/history-rollback.test.ts +6 -3
- package/src/api-routes/__tests__/history.test.ts +9 -6
- package/src/api-routes/__tests__/init-scan-page-resolve-config.test.ts +11 -3
- package/src/api-routes/__tests__/migrate-to-multi.test.ts +5 -1
- package/src/api-routes/__tests__/pages-meta-store.test.ts +10 -5
- package/src/api-routes/__tests__/pages.test.ts +7 -2
- package/src/api-routes/__tests__/patch-page-file.test.ts +71 -19
- package/src/api-routes/__tests__/route-registry.test.ts +11 -18
- package/src/api-routes/__tests__/scan-page-helpers.test.ts +13 -10
- package/src/api-routes/__tests__/section-management.test.ts +28 -28
- package/src/api-routes/__tests__/setup-github-app-callback.test.ts +58 -16
- package/src/api-routes/__tests__/setup-github-app-repos.test.ts +4 -5
- package/src/api-routes/__tests__/setup-github-app.test.ts +27 -7
- package/src/api-routes/__tests__/storage-config-for-request.test.ts +83 -0
- package/src/api-routes/__tests__/updater-register.test.ts +230 -0
- package/src/api-routes/__tests__/webhook-signing.test.ts +1 -1
- package/src/api-routes/__tests__/webhooks.test.ts +19 -7
- package/src/api-routes/__tests__/websites-add.test.ts +2 -1
- package/src/api-routes/__tests__/websites-remove.test.ts +2 -1
- package/src/api-routes/_auth-guard.ts +47 -15
- package/src/api-routes/_commit-trailers.ts +3 -2
- package/src/api-routes/_dev-session-secret.ts +79 -0
- package/src/api-routes/_github-token.ts +1 -1
- package/src/api-routes/_pages-meta-store.ts +2 -2
- package/src/api-routes/_role-resolver.ts +7 -5
- package/src/api-routes/_session-secret.ts +46 -0
- package/src/api-routes/_session-signing.ts +135 -0
- package/src/api-routes/_vercel-origin.ts +2 -6
- package/src/api-routes/_webhook-dispatcher.ts +12 -16
- package/src/api-routes/_website-resolver.ts +3 -10
- package/src/api-routes/auth-callback.ts +9 -5
- package/src/api-routes/auth-login.ts +5 -3
- package/src/api-routes/auth-logout.ts +18 -1
- package/src/api-routes/auth-session.ts +13 -21
- package/src/api-routes/auth-setzkasten-login.ts +12 -9
- package/src/api-routes/catalog-add.ts +89 -31
- package/src/api-routes/catalog-export.ts +30 -10
- package/src/api-routes/config.ts +39 -6
- package/src/api-routes/deploy-hook.ts +13 -11
- package/src/api-routes/editors.ts +33 -22
- package/src/api-routes/github-proxy.ts +25 -11
- package/src/api-routes/global-config.ts +103 -18
- package/src/api-routes/history-rollback.ts +41 -14
- package/src/api-routes/history-version.ts +5 -6
- package/src/api-routes/history.ts +3 -3
- package/src/api-routes/icons-local.ts +2 -2
- package/src/api-routes/init-add-section.ts +218 -88
- package/src/api-routes/init-apply.ts +71 -56
- package/src/api-routes/init-migrate.ts +54 -48
- package/src/api-routes/init-scan-page.ts +77 -30
- package/src/api-routes/init-scan.ts +19 -11
- package/src/api-routes/pages.ts +16 -11
- package/src/api-routes/section-add.ts +98 -27
- package/src/api-routes/section-commit-pending.ts +87 -34
- package/src/api-routes/section-delete.ts +76 -27
- package/src/api-routes/section-duplicate.ts +95 -28
- package/src/api-routes/section-management.ts +3 -7
- package/src/api-routes/section-prepare-copy.ts +29 -8
- package/src/api-routes/section-prepare.ts +38 -10
- package/src/api-routes/setup-github-app-bounce.ts +7 -1
- package/src/api-routes/setup-github-app-branches.ts +6 -7
- package/src/api-routes/setup-github-app-callback.ts +18 -1
- package/src/api-routes/setup-github-app-credentials.ts +55 -0
- package/src/api-routes/setup-github-app-installed.ts +12 -1
- package/src/api-routes/setup-github-app-repos.ts +2 -3
- package/src/api-routes/setup-github-app.ts +14 -5
- package/src/api-routes/updater-check.ts +6 -4
- package/src/api-routes/updater-register.ts +34 -20
- package/src/api-routes/updater-transfer.ts +8 -6
- package/src/api-routes/updater-unbind.ts +14 -10
- package/src/api-routes/webhooks-test.ts +9 -11
- package/src/api-routes/webhooks.ts +15 -19
- package/src/init/__tests__/page-level.test.ts +279 -105
- package/src/init/__tests__/page-list-coverage.test.ts +70 -70
- package/src/init/__tests__/patcher-child-component.test.ts +126 -0
- package/src/init/__tests__/patcher-edge-cases.test.ts +47 -23
- package/src/init/__tests__/patcher-mixed-content-wrapper.test.ts +16 -6
- package/src/init/__tests__/patcher-page-mode.test.ts +30 -20
- package/src/init/__tests__/section-pipeline.test.ts +102 -16
- package/src/init/astro-config-patcher.ts +4 -18
- package/src/init/astro-detector.ts +2 -7
- package/src/init/astro-section-analyzer-v2.ts +475 -193
- package/src/init/field-label-enricher.ts +6 -6
- package/src/init/template-patcher-v2.ts +490 -56
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// src/api-routes/_session-signing.ts
|
|
2
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
3
|
+
var SEPARATOR = ".";
|
|
4
|
+
function base64urlEncode(input) {
|
|
5
|
+
const buf = typeof input === "string" ? Buffer.from(input, "utf-8") : input;
|
|
6
|
+
return buf.toString("base64url");
|
|
7
|
+
}
|
|
8
|
+
function base64urlDecode(input) {
|
|
9
|
+
if (!/^[A-Za-z0-9_-]+$/.test(input)) return null;
|
|
10
|
+
try {
|
|
11
|
+
return Buffer.from(input, "base64url");
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function hmac(payload, secret) {
|
|
17
|
+
return createHmac("sha256", secret).update(payload).digest();
|
|
18
|
+
}
|
|
19
|
+
function signSession(session, secret) {
|
|
20
|
+
if (typeof secret !== "string" || secret.trim().length === 0) {
|
|
21
|
+
throw new Error("signSession: missing secret");
|
|
22
|
+
}
|
|
23
|
+
const json = JSON.stringify(session);
|
|
24
|
+
const payloadB64 = base64urlEncode(json);
|
|
25
|
+
const sigB64 = hmac(payloadB64, secret).toString("base64url");
|
|
26
|
+
return `${payloadB64}${SEPARATOR}${sigB64}`;
|
|
27
|
+
}
|
|
28
|
+
function verifySessionCookie(raw, secret, now = Date.now()) {
|
|
29
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
30
|
+
return { ok: false, reason: "malformed" };
|
|
31
|
+
}
|
|
32
|
+
if (typeof secret !== "string" || secret.trim().length === 0) {
|
|
33
|
+
return { ok: false, reason: "malformed" };
|
|
34
|
+
}
|
|
35
|
+
const segments = raw.split(SEPARATOR);
|
|
36
|
+
if (segments.length !== 2) return { ok: false, reason: "malformed" };
|
|
37
|
+
const [payloadB64, sigB64] = segments;
|
|
38
|
+
if (!payloadB64 || !sigB64) return { ok: false, reason: "malformed" };
|
|
39
|
+
const expected = hmac(payloadB64, secret);
|
|
40
|
+
const actual = base64urlDecode(sigB64);
|
|
41
|
+
if (!actual) return { ok: false, reason: "malformed" };
|
|
42
|
+
if (actual.length !== expected.length) return { ok: false, reason: "bad-signature" };
|
|
43
|
+
if (!timingSafeEqual(actual, expected)) return { ok: false, reason: "bad-signature" };
|
|
44
|
+
const payloadBuf = base64urlDecode(payloadB64);
|
|
45
|
+
if (!payloadBuf) return { ok: false, reason: "malformed" };
|
|
46
|
+
let parsed;
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(payloadBuf.toString("utf-8"));
|
|
49
|
+
} catch {
|
|
50
|
+
return { ok: false, reason: "invalid-payload" };
|
|
51
|
+
}
|
|
52
|
+
if (!isAuthSessionShape(parsed)) {
|
|
53
|
+
return { ok: false, reason: "invalid-payload" };
|
|
54
|
+
}
|
|
55
|
+
if (typeof parsed.expiresAt !== "number" || !Number.isFinite(parsed.expiresAt)) {
|
|
56
|
+
return { ok: false, reason: "missing-expiry" };
|
|
57
|
+
}
|
|
58
|
+
if (parsed.expiresAt <= now) {
|
|
59
|
+
return { ok: false, reason: "expired" };
|
|
60
|
+
}
|
|
61
|
+
return { ok: true, value: parsed };
|
|
62
|
+
}
|
|
63
|
+
function isAuthSessionShape(value) {
|
|
64
|
+
if (!value || typeof value !== "object") return false;
|
|
65
|
+
const v = value;
|
|
66
|
+
if (!v.user || typeof v.user !== "object") return false;
|
|
67
|
+
const u = v.user;
|
|
68
|
+
if (typeof u.email !== "string" || u.email.length === 0) return false;
|
|
69
|
+
if (u.role !== "admin" && u.role !== "editor") return false;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
signSession,
|
|
75
|
+
verifySessionCookie
|
|
76
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/api-routes/_dev-session-secret.ts
|
|
2
|
+
import { randomBytes } from "crypto";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
var DEV_SECRET_DIR = ".setzkasten";
|
|
6
|
+
var DEV_SECRET_FILE = "dev-secret";
|
|
7
|
+
var cachedSecret = null;
|
|
8
|
+
function ensureDevSessionSecret() {
|
|
9
|
+
if (cachedSecret) return cachedSecret;
|
|
10
|
+
const dir = join(process.cwd(), DEV_SECRET_DIR);
|
|
11
|
+
const file = join(dir, DEV_SECRET_FILE);
|
|
12
|
+
if (existsSync(file)) {
|
|
13
|
+
const content = readFileSync(file, "utf-8").trim();
|
|
14
|
+
if (content.length >= 32) {
|
|
15
|
+
cachedSecret = content;
|
|
16
|
+
return content;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
mkdirSync(dir, { recursive: true });
|
|
20
|
+
const fresh = randomBytes(32).toString("hex");
|
|
21
|
+
try {
|
|
22
|
+
writeFileSync(file, `${fresh}
|
|
23
|
+
`, { flag: "wx", mode: 384 });
|
|
24
|
+
} catch (cause) {
|
|
25
|
+
if (cause?.code === "EEXIST") {
|
|
26
|
+
const content = readFileSync(file, "utf-8").trim();
|
|
27
|
+
if (content.length >= 32) {
|
|
28
|
+
cachedSecret = content;
|
|
29
|
+
return content;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
throw cause;
|
|
33
|
+
}
|
|
34
|
+
console.warn(
|
|
35
|
+
`[setzkasten] Generated dev session secret at ${file} (mode 0600). Set SETZKASTEN_SESSION_SECRET in production. Delete the file to rotate.`
|
|
36
|
+
);
|
|
37
|
+
cachedSecret = fresh;
|
|
38
|
+
return fresh;
|
|
39
|
+
}
|
|
40
|
+
function __setDevSessionSecretForTests(secret) {
|
|
41
|
+
cachedSecret = secret;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
ensureDevSessionSecret,
|
|
46
|
+
__setDevSessionSecretForTests
|
|
47
|
+
};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveSessionSecret
|
|
3
|
+
} from "./chunk-QVCW6EF3.js";
|
|
4
|
+
import {
|
|
5
|
+
verifySessionCookie
|
|
6
|
+
} from "./chunk-KENFINT4.js";
|
|
1
7
|
import {
|
|
2
8
|
resolveStorageConfig
|
|
3
9
|
} from "./chunk-6UIKVKED.js";
|
|
@@ -10,17 +16,21 @@ import {
|
|
|
10
16
|
} from "./chunk-45ARVNT3.js";
|
|
11
17
|
import {
|
|
12
18
|
resolveConfigRepoToken
|
|
13
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-DP6RTINQ.js";
|
|
14
20
|
import {
|
|
15
21
|
withTrailers
|
|
16
22
|
} from "./chunk-KH22FJO5.js";
|
|
17
23
|
|
|
24
|
+
// src/api-routes/editors.ts
|
|
25
|
+
import { validateEditorsUpdate } from "@setzkasten-cms/core";
|
|
26
|
+
|
|
18
27
|
// src/api-routes/_auth-guard.ts
|
|
19
28
|
import { canEditPage } from "@setzkasten-cms/auth";
|
|
20
29
|
function parseSession(raw) {
|
|
21
30
|
if (!raw) return null;
|
|
22
31
|
try {
|
|
23
|
-
|
|
32
|
+
const result = verifySessionCookie(raw, resolveSessionSecret());
|
|
33
|
+
return result.ok ? result.value : null;
|
|
24
34
|
} catch {
|
|
25
35
|
return null;
|
|
26
36
|
}
|
|
@@ -45,10 +55,9 @@ async function guardPageAccess(session, pageKey, fullConfig, request) {
|
|
|
45
55
|
if (!session) return new Response("Unauthorized", { status: 401 });
|
|
46
56
|
const editorsLookup = await resolveDynamicEditors();
|
|
47
57
|
if (!editorsLookup.ok) {
|
|
48
|
-
return new Response(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
);
|
|
58
|
+
return new Response(`Forbidden: editor permissions unavailable (${editorsLookup.error})`, {
|
|
59
|
+
status: 503
|
|
60
|
+
});
|
|
52
61
|
}
|
|
53
62
|
if (!canEditPage(session, pageKey, editorsLookup.editors)) {
|
|
54
63
|
return new Response("Forbidden: you do not have access to this page", { status: 403 });
|
|
@@ -65,13 +74,15 @@ async function guardWebsiteAccess(session, request) {
|
|
|
65
74
|
const website = await resolveCurrentWebsite(request);
|
|
66
75
|
if (!website.ok) return null;
|
|
67
76
|
const allowed = website.value.allowedEmails;
|
|
68
|
-
if (!allowed || allowed.length === 0)
|
|
69
|
-
if (!allowed.includes(session.user.email)) {
|
|
77
|
+
if (!allowed || allowed.length === 0) {
|
|
70
78
|
return new Response(
|
|
71
|
-
`Forbidden:
|
|
79
|
+
`Forbidden: website "${website.value.id}" has no editor allow-list \u2014 add the editor's email to allowedEmails or grant admin role`,
|
|
72
80
|
{ status: 403 }
|
|
73
81
|
);
|
|
74
82
|
}
|
|
83
|
+
if (!allowed.includes(session.user.email)) {
|
|
84
|
+
return new Response(`Forbidden: not allowed on website "${website.value.id}"`, { status: 403 });
|
|
85
|
+
}
|
|
75
86
|
return null;
|
|
76
87
|
}
|
|
77
88
|
async function resolveDynamicEditors() {
|
|
@@ -96,7 +107,6 @@ async function resolveDynamicEditors() {
|
|
|
96
107
|
}
|
|
97
108
|
|
|
98
109
|
// src/api-routes/editors.ts
|
|
99
|
-
import { validateEditorsUpdate } from "@setzkasten-cms/core";
|
|
100
110
|
var EDITORS_FILE = (contentPath) => `${contentPath}/_editors.json`;
|
|
101
111
|
function configRepoStorage() {
|
|
102
112
|
const storage = resolveStorageConfig();
|
|
@@ -138,10 +148,7 @@ var PUT = async ({ request, cookies }) => {
|
|
|
138
148
|
}
|
|
139
149
|
const validation = validateEditorsUpdate(editors, session.user.email);
|
|
140
150
|
if (!validation.ok) {
|
|
141
|
-
return Response.json(
|
|
142
|
-
{ error: validation.message, code: validation.code },
|
|
143
|
-
{ status: 400 }
|
|
144
|
-
);
|
|
151
|
+
return Response.json({ error: validation.message, code: validation.code }, { status: 400 });
|
|
145
152
|
}
|
|
146
153
|
const filePath = EDITORS_FILE(contentPath);
|
|
147
154
|
const fileContent = JSON.stringify(editors, null, 2);
|
|
@@ -158,10 +165,11 @@ var PUT = async ({ request, cookies }) => {
|
|
|
158
165
|
branch
|
|
159
166
|
};
|
|
160
167
|
if (existing) body.sha = existing;
|
|
161
|
-
const res = await fetch(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
168
|
+
const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${filePath}`, {
|
|
169
|
+
method: "PUT",
|
|
170
|
+
headers,
|
|
171
|
+
body: JSON.stringify(body)
|
|
172
|
+
});
|
|
165
173
|
if (!res.ok) {
|
|
166
174
|
const text = await res.text();
|
|
167
175
|
return Response.json({ error: `GitHub write failed: ${text}` }, { status: 502 });
|
|
@@ -187,7 +195,13 @@ async function readEditorsFile(owner, repo, branch, contentPath, token) {
|
|
|
187
195
|
return cachedFetch(key, 2 * 6e4, async () => {
|
|
188
196
|
const res = await fetch(
|
|
189
197
|
`https://api.github.com/repos/${owner}/${repo}/contents/${EDITORS_FILE(contentPath)}?ref=${branch}`,
|
|
190
|
-
{
|
|
198
|
+
{
|
|
199
|
+
headers: {
|
|
200
|
+
Authorization: `Bearer ${token}`,
|
|
201
|
+
Accept: "application/vnd.github+json",
|
|
202
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
203
|
+
}
|
|
204
|
+
}
|
|
191
205
|
);
|
|
192
206
|
if (!res.ok) return null;
|
|
193
207
|
const data = await res.json();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureDevSessionSecret
|
|
3
|
+
} from "./chunk-ONP6BRZO.js";
|
|
4
|
+
|
|
5
|
+
// src/api-routes/_session-secret.ts
|
|
6
|
+
var MIN_SECRET_LENGTH = 32;
|
|
7
|
+
function resolveSessionSecret() {
|
|
8
|
+
const fromEnv = process.env.SETZKASTEN_SESSION_SECRET;
|
|
9
|
+
if (typeof fromEnv === "string" && fromEnv.trim().length >= MIN_SECRET_LENGTH) {
|
|
10
|
+
return fromEnv.trim();
|
|
11
|
+
}
|
|
12
|
+
const fromBuild = globalThis.__SETZKASTEN_BUILD_CONFIG__;
|
|
13
|
+
if (typeof fromBuild?.sessionSecret === "string" && fromBuild.sessionSecret.trim().length >= MIN_SECRET_LENGTH) {
|
|
14
|
+
return fromBuild.sessionSecret.trim();
|
|
15
|
+
}
|
|
16
|
+
if (process.env.NODE_ENV === "production") {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"SETZKASTEN_SESSION_SECRET is missing or too short (need \u226532 chars). Generate one with `openssl rand -hex 32` and set it as an env var."
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
return ensureDevSessionSecret();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
resolveSessionSecret
|
|
26
|
+
};
|