@digitalpaws/starr 0.0.1
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/README.rst +75 -0
- package/data/.nfs.811bbb0d.43c34.4 +0 -0
- package/data/.nfs.81ba4cd0.ffff87804.4 +0 -0
- package/data/.nfs.82d127f7.fffff5704.4 +0 -0
- package/data/.nfs.82d127fe.fffff5704.4 +0 -0
- package/data/.nfs.82d159a5.fffff5aa4.4 +0 -0
- package/data/.nfs.82d159aa.fffff5aa4.4 +0 -0
- package/data/.nfs.82d15a9c.fffff5bb4.4 +0 -0
- package/data/.nfs.82d15aa1.fffff5bb4.4 +0 -0
- package/data/.nfs.82d15c65.fffff5c24.4 +0 -0
- package/data/.nfs.82d1852c.fffff5e24.4 +0 -0
- package/data/.nfs.82d18536.fffff5e24.4 +0 -0
- package/data/.nfs.82d18dbe.fffff5e44.4 +0 -0
- package/data/.nfs.82d18dc6.fffff5e44.4 +0 -0
- package/data/.nfs.8309a3f5.fffff82f4.4 +0 -0
- package/data/.nfs.8309a3fe.fffff82f4.4 +0 -0
- package/data/.nfs.8314122e.fffffb044.4 +0 -0
- package/data/.nfs.83141236.fffffb044.4 +0 -0
- package/data/.nfs.833c4fe9.fffffbc34.4 +0 -0
- package/data/.nfs.833c4ff3.fffffbc34.4 +0 -0
- package/data/logs/starr.log +66244 -0
- package/data/starr.db +0 -0
- package/data/starr.db-shm +0 -0
- package/data/starr.db-wal +0 -0
- package/data/starr.jwt +1 -0
- package/data/starr.key +1 -0
- package/dist/auth/auth-service.d.ts +42 -0
- package/dist/auth/auth-service.d.ts.map +1 -0
- package/dist/auth/auth-service.js +226 -0
- package/dist/auth/auth-service.js.map +1 -0
- package/dist/auth/http-server.d.ts +16 -0
- package/dist/auth/http-server.d.ts.map +1 -0
- package/dist/auth/http-server.js +207 -0
- package/dist/auth/http-server.js.map +1 -0
- package/dist/auth/jwt-secret.d.ts +6 -0
- package/dist/auth/jwt-secret.d.ts.map +1 -0
- package/dist/auth/jwt-secret.js +51 -0
- package/dist/auth/jwt-secret.js.map +1 -0
- package/dist/auth/oidc/oidc-flow.d.ts +60 -0
- package/dist/auth/oidc/oidc-flow.d.ts.map +1 -0
- package/dist/auth/oidc/oidc-flow.js +201 -0
- package/dist/auth/oidc/oidc-flow.js.map +1 -0
- package/dist/auth/oidc/oidc-provider-service.d.ts +59 -0
- package/dist/auth/oidc/oidc-provider-service.d.ts.map +1 -0
- package/dist/auth/oidc/oidc-provider-service.js +124 -0
- package/dist/auth/oidc/oidc-provider-service.js.map +1 -0
- package/dist/auth/oidc/user-service.d.ts +67 -0
- package/dist/auth/oidc/user-service.d.ts.map +1 -0
- package/dist/auth/oidc/user-service.js +177 -0
- package/dist/auth/oidc/user-service.js.map +1 -0
- package/dist/auth/rate-limiter.d.ts +31 -0
- package/dist/auth/rate-limiter.d.ts.map +1 -0
- package/dist/auth/rate-limiter.js +70 -0
- package/dist/auth/rate-limiter.js.map +1 -0
- package/dist/config/config-service.d.ts +83 -0
- package/dist/config/config-service.d.ts.map +1 -0
- package/dist/config/config-service.js +309 -0
- package/dist/config/config-service.js.map +1 -0
- package/dist/config/validate.d.ts +12 -0
- package/dist/config/validate.d.ts.map +1 -0
- package/dist/config/validate.js +140 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/content-types/registry.d.ts +75 -0
- package/dist/content-types/registry.d.ts.map +1 -0
- package/dist/content-types/registry.js +171 -0
- package/dist/content-types/registry.js.map +1 -0
- package/dist/datastore/db.d.ts +9 -0
- package/dist/datastore/db.d.ts.map +1 -0
- package/dist/datastore/db.js +27 -0
- package/dist/datastore/db.js.map +1 -0
- package/dist/datastore/encrypt.d.ts +9 -0
- package/dist/datastore/encrypt.d.ts.map +1 -0
- package/dist/datastore/encrypt.js +84 -0
- package/dist/datastore/encrypt.js.map +1 -0
- package/dist/datastore/migrations.d.ts +10 -0
- package/dist/datastore/migrations.d.ts.map +1 -0
- package/dist/datastore/migrations.js +340 -0
- package/dist/datastore/migrations.js.map +1 -0
- package/dist/datastore/storage.d.ts +4 -0
- package/dist/datastore/storage.d.ts.map +1 -0
- package/dist/datastore/storage.js +60 -0
- package/dist/datastore/storage.js.map +1 -0
- package/dist/events/event-bus.d.ts +15 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +140 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/spine.d.ts +31 -0
- package/dist/events/spine.d.ts.map +1 -0
- package/dist/events/spine.js +68 -0
- package/dist/events/spine.js.map +1 -0
- package/dist/events/trace.d.ts +24 -0
- package/dist/events/trace.d.ts.map +1 -0
- package/dist/events/trace.js +33 -0
- package/dist/events/trace.js.map +1 -0
- package/dist/host.d.ts +65 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +94 -0
- package/dist/host.js.map +1 -0
- package/dist/library/importer.d.ts +29 -0
- package/dist/library/importer.d.ts.map +1 -0
- package/dist/library/importer.js +145 -0
- package/dist/library/importer.js.map +1 -0
- package/dist/library/library-cache.d.ts +46 -0
- package/dist/library/library-cache.d.ts.map +1 -0
- package/dist/library/library-cache.js +152 -0
- package/dist/library/library-cache.js.map +1 -0
- package/dist/library/library-config.d.ts +12 -0
- package/dist/library/library-config.d.ts.map +1 -0
- package/dist/library/library-config.js +10 -0
- package/dist/library/library-config.js.map +1 -0
- package/dist/library/library-scanner.d.ts +62 -0
- package/dist/library/library-scanner.d.ts.map +1 -0
- package/dist/library/library-scanner.js +336 -0
- package/dist/library/library-scanner.js.map +1 -0
- package/dist/library/library-service.d.ts +65 -0
- package/dist/library/library-service.d.ts.map +1 -0
- package/dist/library/library-service.js +197 -0
- package/dist/library/library-service.js.map +1 -0
- package/dist/library/metadata-matcher.d.ts +56 -0
- package/dist/library/metadata-matcher.d.ts.map +1 -0
- package/dist/library/metadata-matcher.js +207 -0
- package/dist/library/metadata-matcher.js.map +1 -0
- package/dist/library/naming.d.ts +8 -0
- package/dist/library/naming.d.ts.map +1 -0
- package/dist/library/naming.js +47 -0
- package/dist/library/naming.js.map +1 -0
- package/dist/library/scan-controller.d.ts +95 -0
- package/dist/library/scan-controller.d.ts.map +1 -0
- package/dist/library/scan-controller.js +379 -0
- package/dist/library/scan-controller.js.map +1 -0
- package/dist/library/source-resolver.d.ts +17 -0
- package/dist/library/source-resolver.d.ts.map +1 -0
- package/dist/library/source-resolver.js +75 -0
- package/dist/library/source-resolver.js.map +1 -0
- package/dist/logging/logger.d.ts +3 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +107 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/main.d.ts +36 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +229 -0
- package/dist/main.js.map +1 -0
- package/dist/plugins/context.d.ts +10 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +110 -0
- package/dist/plugins/context.js.map +1 -0
- package/dist/plugins/discovery.d.ts +2 -0
- package/dist/plugins/discovery.d.ts.map +1 -0
- package/dist/plugins/discovery.js +32 -0
- package/dist/plugins/discovery.js.map +1 -0
- package/dist/plugins/loader.d.ts +9 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +245 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/state/request-intake.d.ts +26 -0
- package/dist/state/request-intake.d.ts.map +1 -0
- package/dist/state/request-intake.js +74 -0
- package/dist/state/request-intake.js.map +1 -0
- package/dist/state/state-store.d.ts +146 -0
- package/dist/state/state-store.d.ts.map +1 -0
- package/dist/state/state-store.js +465 -0
- package/dist/state/state-store.js.map +1 -0
- package/dist/state/trace-store.d.ts +12 -0
- package/dist/state/trace-store.d.ts.map +1 -0
- package/dist/state/trace-store.js +24 -0
- package/dist/state/trace-store.js.map +1 -0
- package/dist/types/plugin.d.ts +93 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +4 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/web/index.d.ts +10 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +153 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/routes/activity.d.ts +6 -0
- package/dist/web/routes/activity.d.ts.map +1 -0
- package/dist/web/routes/activity.js +31 -0
- package/dist/web/routes/activity.js.map +1 -0
- package/dist/web/routes/auth.d.ts +6 -0
- package/dist/web/routes/auth.d.ts.map +1 -0
- package/dist/web/routes/auth.js +142 -0
- package/dist/web/routes/auth.js.map +1 -0
- package/dist/web/routes/config.d.ts +7 -0
- package/dist/web/routes/config.d.ts.map +1 -0
- package/dist/web/routes/config.js +204 -0
- package/dist/web/routes/config.js.map +1 -0
- package/dist/web/routes/content-types.d.ts +6 -0
- package/dist/web/routes/content-types.d.ts.map +1 -0
- package/dist/web/routes/content-types.js +29 -0
- package/dist/web/routes/content-types.js.map +1 -0
- package/dist/web/routes/discovery.d.ts +6 -0
- package/dist/web/routes/discovery.d.ts.map +1 -0
- package/dist/web/routes/discovery.js +111 -0
- package/dist/web/routes/discovery.js.map +1 -0
- package/dist/web/routes/library-import.d.ts +6 -0
- package/dist/web/routes/library-import.d.ts.map +1 -0
- package/dist/web/routes/library-import.js +120 -0
- package/dist/web/routes/library-import.js.map +1 -0
- package/dist/web/routes/library-management.d.ts +6 -0
- package/dist/web/routes/library-management.d.ts.map +1 -0
- package/dist/web/routes/library-management.js +120 -0
- package/dist/web/routes/library-management.js.map +1 -0
- package/dist/web/routes/library.d.ts +6 -0
- package/dist/web/routes/library.d.ts.map +1 -0
- package/dist/web/routes/library.js +28 -0
- package/dist/web/routes/library.js.map +1 -0
- package/dist/web/routes/oidc.d.ts +9 -0
- package/dist/web/routes/oidc.d.ts.map +1 -0
- package/dist/web/routes/oidc.js +203 -0
- package/dist/web/routes/oidc.js.map +1 -0
- package/dist/web/routes/requests.d.ts +6 -0
- package/dist/web/routes/requests.d.ts.map +1 -0
- package/dist/web/routes/requests.js +183 -0
- package/dist/web/routes/requests.js.map +1 -0
- package/dist/web/routes/sse.d.ts +6 -0
- package/dist/web/routes/sse.d.ts.map +1 -0
- package/dist/web/routes/sse.js +54 -0
- package/dist/web/routes/sse.js.map +1 -0
- package/package.json +33 -0
- package/package.json.license +2 -0
- package/src/auth/auth-service.ts +333 -0
- package/src/auth/http-server.ts +249 -0
- package/src/auth/jwt-secret.ts +65 -0
- package/src/auth/oidc/oidc-flow.ts +266 -0
- package/src/auth/oidc/oidc-provider-service.ts +174 -0
- package/src/auth/oidc/user-service.ts +227 -0
- package/src/auth/rate-limiter.ts +85 -0
- package/src/config/config-service.ts +434 -0
- package/src/config/validate.ts +153 -0
- package/src/content-types/registry.ts +194 -0
- package/src/datastore/db.ts +38 -0
- package/src/datastore/encrypt.ts +107 -0
- package/src/datastore/migrations.ts +367 -0
- package/src/datastore/storage.ts +83 -0
- package/src/events/event-bus.ts +180 -0
- package/src/events/spine.ts +87 -0
- package/src/events/trace.ts +38 -0
- package/src/host.ts +130 -0
- package/src/library/importer.ts +174 -0
- package/src/library/library-cache.ts +212 -0
- package/src/library/library-config.ts +22 -0
- package/src/library/library-scanner.ts +404 -0
- package/src/library/library-service.ts +282 -0
- package/src/library/metadata-matcher.ts +285 -0
- package/src/library/naming.ts +59 -0
- package/src/library/scan-controller.ts +490 -0
- package/src/library/source-resolver.ts +92 -0
- package/src/logging/logger.ts +115 -0
- package/src/main.ts +364 -0
- package/src/plugins/context.ts +138 -0
- package/src/plugins/discovery.ts +29 -0
- package/src/plugins/loader.ts +309 -0
- package/src/state/request-intake.ts +101 -0
- package/src/state/state-store.ts +621 -0
- package/src/state/trace-store.ts +27 -0
- package/src/types/plugin.ts +110 -0
- package/src/web/index.ts +182 -0
- package/src/web/routes/activity.ts +41 -0
- package/src/web/routes/auth.ts +170 -0
- package/src/web/routes/config.ts +282 -0
- package/src/web/routes/content-types.ts +42 -0
- package/src/web/routes/discovery.ts +156 -0
- package/src/web/routes/library-import.ts +196 -0
- package/src/web/routes/library-management.ts +140 -0
- package/src/web/routes/library.ts +46 -0
- package/src/web/routes/oidc.ts +260 -0
- package/src/web/routes/requests.ts +250 -0
- package/src/web/routes/sse.ts +92 -0
- package/tests/auth.test.ts +510 -0
- package/tests/config-route.test.ts +345 -0
- package/tests/config.test.ts +612 -0
- package/tests/content-types.test.ts +376 -0
- package/tests/datastore.test.ts +345 -0
- package/tests/e2e.test.ts +430 -0
- package/tests/event-bus.test.ts +925 -0
- package/tests/host.test.ts +449 -0
- package/tests/library-cache.test.ts +171 -0
- package/tests/library-scanner.test.ts +177 -0
- package/tests/library.test.ts +210 -0
- package/tests/loader-context.test.ts +644 -0
- package/tests/logger-jsonl.test.ts +154 -0
- package/tests/metadata-matcher.test.ts +198 -0
- package/tests/oidc.test.ts +218 -0
- package/tests/scan-controller.test.ts +328 -0
- package/tests/source-resolver.test.ts +100 -0
- package/tests/starr-video-integration.test.ts +153 -0
- package/tests/state-store.test.ts +700 -0
- package/tests/trace-history.test.ts +356 -0
- package/tsconfig.json +8 -0
- package/tsconfig.json.license +2 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// SPDX-License-Identifier: 0BSD
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Digi <digitalpaws@proton.me>
|
|
3
|
+
import Fastify from "fastify";
|
|
4
|
+
import fastifyStatic from "@fastify/static";
|
|
5
|
+
import fastifyCookie from "@fastify/cookie";
|
|
6
|
+
import fastifyFormbody from "@fastify/formbody";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
// ── Deferred AuthService reference ───────────────────────
|
|
11
|
+
// Set by main.ts via initAuthService() after AuthService is created.
|
|
12
|
+
let authService = null;
|
|
13
|
+
export function initAuthService(auth) {
|
|
14
|
+
authService = auth;
|
|
15
|
+
}
|
|
16
|
+
// ── Deferred OIDC service references ─────────────────────
|
|
17
|
+
let oidcProviderService = null;
|
|
18
|
+
let oidcFlow = null;
|
|
19
|
+
let userService = null;
|
|
20
|
+
export function initOidcServices(oidcProviders, flow, users) {
|
|
21
|
+
oidcProviderService = oidcProviders;
|
|
22
|
+
oidcFlow = flow;
|
|
23
|
+
userService = users;
|
|
24
|
+
}
|
|
25
|
+
// ── Server factory ───────────────────────────────────────
|
|
26
|
+
export async function createWebServer(logger) {
|
|
27
|
+
// forceCloseConnections ensures SSE and other persistent connections
|
|
28
|
+
// are forcefully torn down on close(), preventing shutdown hangs
|
|
29
|
+
// that keep the port bound (the root cause of EADDRINUSE on restart).
|
|
30
|
+
const server = Fastify({ logger: false, forceCloseConnections: true });
|
|
31
|
+
// Parse cookies (needed for session)
|
|
32
|
+
await server.register(fastifyCookie);
|
|
33
|
+
// Parse form/multipart bodies (needed for auth, config)
|
|
34
|
+
await server.register(fastifyFormbody);
|
|
35
|
+
// ---- AUTH HOOK ----
|
|
36
|
+
// All /api/* routes require a valid session, except an explicit
|
|
37
|
+
// allowlist of public endpoints (login, setup, OIDC initiation, etc.).
|
|
38
|
+
// Non-API routes (static files) are always public.
|
|
39
|
+
server.addHook("onRequest", async (request, reply) => {
|
|
40
|
+
// Non-API routes (static files) are always public
|
|
41
|
+
if (!request.url.startsWith("/api/")) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Public paths that don't require authentication
|
|
45
|
+
const publicPaths = [
|
|
46
|
+
"/api/auth/login",
|
|
47
|
+
"/api/auth/setup",
|
|
48
|
+
"/api/auth/needs-setup",
|
|
49
|
+
"/api/auth/status",
|
|
50
|
+
"/api/auth/logout", // safe — only clears cookie
|
|
51
|
+
"/api/oidc/providers", // login page needs this before auth
|
|
52
|
+
"/api/oidc/login/", // initiates OIDC flow
|
|
53
|
+
"/api/oidc/callback/", // OIDC provider redirects here
|
|
54
|
+
];
|
|
55
|
+
for (const pub of publicPaths) {
|
|
56
|
+
if (request.url === pub || request.url.startsWith(pub)) {
|
|
57
|
+
return; // skip auth for public paths
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// All other /api/* routes require a valid session
|
|
61
|
+
const sid = request.cookies["starr_sid"];
|
|
62
|
+
if (!sid) {
|
|
63
|
+
reply.status(401).send({ error: "Unauthorized" });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!authService) {
|
|
67
|
+
reply.status(500).send({ error: "auth service not available" });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const result = authService.validateToken(sid);
|
|
71
|
+
if (!result) {
|
|
72
|
+
reply.status(401).send({ error: "Invalid session" });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Attach user info including role and id
|
|
76
|
+
request.user = {
|
|
77
|
+
id: result.userId,
|
|
78
|
+
username: result.userId,
|
|
79
|
+
role: result.role ?? "user",
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
// ---- REGISTER API ROUTES ----
|
|
83
|
+
// Each route module is registered as a Fastify plugin.
|
|
84
|
+
// Dynamic import with try/catch means a missing route module won't crash the server.
|
|
85
|
+
const routeModules = [
|
|
86
|
+
"./routes/auth.js",
|
|
87
|
+
"./routes/discovery.js",
|
|
88
|
+
"./routes/content-types.js",
|
|
89
|
+
"./routes/requests.js",
|
|
90
|
+
"./routes/config.js",
|
|
91
|
+
"./routes/activity.js",
|
|
92
|
+
"./routes/sse.js",
|
|
93
|
+
"./routes/oidc.js",
|
|
94
|
+
"./routes/library.js",
|
|
95
|
+
"./routes/library-management.js",
|
|
96
|
+
"./routes/library-import.js",
|
|
97
|
+
];
|
|
98
|
+
for (const modPath of routeModules) {
|
|
99
|
+
try {
|
|
100
|
+
const mod = await import(modPath);
|
|
101
|
+
await server.register(mod.default);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (err.code === "ERR_MODULE_NOT_FOUND") {
|
|
105
|
+
logger.warn(`route module not found (skipping): ${modPath}`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
logger.error(`failed to register route module: ${modPath}`, { error: String(err) });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// ---- INIT OIDC ROUTES ----
|
|
113
|
+
// OIDC routes need the services hooked up after registration
|
|
114
|
+
try {
|
|
115
|
+
const { initOidcRoutes } = await import("./routes/oidc.js");
|
|
116
|
+
if (authService && oidcProviderService && oidcFlow && userService) {
|
|
117
|
+
initOidcRoutes(authService, oidcProviderService, oidcFlow, userService);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
logger.warn("OIDC services not fully initialized — skipping OIDC route init");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
logger.error("failed to init OIDC routes", { error: String(err) });
|
|
125
|
+
}
|
|
126
|
+
// ---- STATIC FILE SERVING (SPA) ----
|
|
127
|
+
// In production, the Svelte build output is at ../../web-ui/dist
|
|
128
|
+
// In development, the Vite dev server proxies to the host; static files aren't served.
|
|
129
|
+
const spaDist = path.resolve(__dirname, "../../../web-ui/dist");
|
|
130
|
+
try {
|
|
131
|
+
await server.register(fastifyStatic, {
|
|
132
|
+
root: spaDist,
|
|
133
|
+
prefix: "/",
|
|
134
|
+
wildcard: false,
|
|
135
|
+
});
|
|
136
|
+
// SPA fallback: serve index.html for any non-API, non-file route
|
|
137
|
+
server.setNotFoundHandler(async (request, reply) => {
|
|
138
|
+
if (request.url.startsWith("/api/")) {
|
|
139
|
+
reply.status(404).send({ error: "not found" });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// Serve index.html for client-side routing
|
|
143
|
+
await reply.sendFile("index.html");
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
logger.warn("SPA static files not found (web-ui/dist missing); " +
|
|
148
|
+
"run `pnpm --filter starr-web-ui build` first");
|
|
149
|
+
}
|
|
150
|
+
logger.info("web server created");
|
|
151
|
+
return server;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from "fastify";
|
|
2
|
+
import type { Starr } from "../../host.js";
|
|
3
|
+
export declare function initActivityRoutes(starr: Starr): void;
|
|
4
|
+
declare const activityRoutes: FastifyPluginAsync;
|
|
5
|
+
export default activityRoutes;
|
|
6
|
+
//# sourceMappingURL=activity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/web/routes/activity.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAI3C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAErD;AAED,QAAA,MAAM,cAAc,EAAE,kBA0BrB,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: 0BSD
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Digi <digitalpaws@proton.me>
|
|
3
|
+
let starrInstance = null;
|
|
4
|
+
export function initActivityRoutes(starr) {
|
|
5
|
+
starrInstance = starr;
|
|
6
|
+
}
|
|
7
|
+
const activityRoutes = async (server) => {
|
|
8
|
+
server.get("/api/requests/:id/activity", async (request, reply) => {
|
|
9
|
+
if (!starrInstance) {
|
|
10
|
+
reply.status(500).send({ error: "host not available" });
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const req = starrInstance.getStateStore().getByRequestId(request.params.id);
|
|
14
|
+
if (!req) {
|
|
15
|
+
reply.status(404).send({ error: "request not found" });
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// Use the trace-store wrapper module (Task 020 data surface).
|
|
19
|
+
// Gracefully degrades to empty array if the wrapper isn't wired yet.
|
|
20
|
+
try {
|
|
21
|
+
const { getTraceEvents } = await import("../../state/trace-store.js");
|
|
22
|
+
const events = getTraceEvents(req.requestId);
|
|
23
|
+
return { requestId: req.requestId, events };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { requestId: req.requestId, events: [] };
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
export default activityRoutes;
|
|
31
|
+
//# sourceMappingURL=activity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../../../src/web/routes/activity.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,4DAA4D;AAK5D,IAAI,aAAa,GAAiB,IAAI,CAAC;AAEvC,MAAM,UAAU,kBAAkB,CAAC,KAAY;IAC7C,aAAa,GAAG,KAAK,CAAC;AACxB,CAAC;AAED,MAAM,cAAc,GAAuB,KAAK,EAAE,MAAM,EAAE,EAAE;IAC1D,MAAM,CAAC,GAAG,CACR,4BAA4B,EAC5B,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,aAAa,CAAC,aAAa,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,8DAA8D;QAC9D,qEAAqE;QACrE,IAAI,CAAC;YACH,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;YACtE,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC7C,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAClD,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from "fastify";
|
|
2
|
+
import type { AuthService } from "../../auth/auth-service.js";
|
|
3
|
+
export declare function initAuthRoutes(auth: AuthService): void;
|
|
4
|
+
declare const authRoutes: FastifyPluginAsync;
|
|
5
|
+
export default authRoutes;
|
|
6
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/web/routes/auth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAS9D,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAEtD;AAYD,QAAA,MAAM,UAAU,EAAE,kBA4IjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// SPDX-License-Identifier: 0BSD
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Digi <digitalpaws@proton.me>
|
|
3
|
+
import { rateLimit } from "../../auth/rate-limiter.js";
|
|
4
|
+
/**
|
|
5
|
+
* This module needs access to the AuthService.
|
|
6
|
+
* We provide it via a module-level setter called from main.ts.
|
|
7
|
+
*/
|
|
8
|
+
let authService = null;
|
|
9
|
+
export function initAuthRoutes(auth) {
|
|
10
|
+
authService = auth;
|
|
11
|
+
}
|
|
12
|
+
const SESSION_COOKIE = "starr_sid";
|
|
13
|
+
const COOKIE_OPTS = {
|
|
14
|
+
httpOnly: true,
|
|
15
|
+
sameSite: "strict",
|
|
16
|
+
path: "/",
|
|
17
|
+
secure: false,
|
|
18
|
+
// TTL from env or default 7 days (matches AuthService default)
|
|
19
|
+
maxAge: parseInt(process.env.STARR_SESSION_TTL_HOURS ?? "168", 10) * 3600,
|
|
20
|
+
};
|
|
21
|
+
const authRoutes = async (server) => {
|
|
22
|
+
// GET /api/auth/needs-setup — check if admin account exists
|
|
23
|
+
server.get("/api/auth/needs-setup", async (_request, _reply) => {
|
|
24
|
+
const needsSetup = authService?.needsSetup() ?? true;
|
|
25
|
+
return { needsSetup };
|
|
26
|
+
});
|
|
27
|
+
// GET /api/auth/status — check if logged in
|
|
28
|
+
server.get("/api/auth/status", async (request, reply) => {
|
|
29
|
+
const sid = request.cookies[SESSION_COOKIE];
|
|
30
|
+
if (!sid || !authService) {
|
|
31
|
+
reply.status(401).send({ error: "Unauthorized" });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const result = authService.validateToken(sid);
|
|
35
|
+
if (!result) {
|
|
36
|
+
reply.status(401).send({ error: "Invalid session" });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Return richer user info (display name, avatar, role)
|
|
40
|
+
const userInfo = authService.getUserInfo(result.userId);
|
|
41
|
+
return {
|
|
42
|
+
user: result.userId,
|
|
43
|
+
displayName: userInfo?.displayName ?? result.userId,
|
|
44
|
+
avatarUrl: userInfo?.avatarUrl ?? null,
|
|
45
|
+
role: result.role ?? "user",
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
// POST /api/auth/setup — first-run admin creation
|
|
49
|
+
server.post("/api/auth/setup", async (request, reply) => {
|
|
50
|
+
if (!authService) {
|
|
51
|
+
reply.status(500).send({ error: "auth service not available" });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const { username, password } = request.body;
|
|
55
|
+
if (!username || !password) {
|
|
56
|
+
reply.status(400).send({ error: "username and password are required" });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
await authService.setup(username, password);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const msg = err instanceof Error ? err.message : "Setup failed";
|
|
64
|
+
if (msg.includes("already exists")) {
|
|
65
|
+
reply.status(403).send({ error: msg });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
reply.status(400).send({ error: msg });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// Log in immediately after setup
|
|
72
|
+
const jwt = await authService.login(username, password);
|
|
73
|
+
if (jwt) {
|
|
74
|
+
reply.setCookie(SESSION_COOKIE, jwt, COOKIE_OPTS);
|
|
75
|
+
return { ok: true };
|
|
76
|
+
}
|
|
77
|
+
reply.status(500).send({ error: "Account created but login failed" });
|
|
78
|
+
});
|
|
79
|
+
// POST /api/auth/login — rate-limited (5 attempts per minute per IP)
|
|
80
|
+
server.post("/api/auth/login", { preHandler: rateLimit(5, 1) }, async (request, reply) => {
|
|
81
|
+
if (!authService) {
|
|
82
|
+
reply.status(500).send({ error: "auth service not available" });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const { username, password } = request.body;
|
|
86
|
+
if (!username || !password) {
|
|
87
|
+
reply.status(400).send({ error: "username and password are required" });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const jwt = await authService.login(username, password);
|
|
91
|
+
if (!jwt) {
|
|
92
|
+
reply.status(401).send({ error: "Invalid credentials" });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
reply.setCookie(SESSION_COOKIE, jwt, COOKIE_OPTS);
|
|
96
|
+
return { ok: true };
|
|
97
|
+
});
|
|
98
|
+
// POST /api/auth/logout
|
|
99
|
+
server.post("/api/auth/logout", async (request, reply) => {
|
|
100
|
+
const sid = request.cookies[SESSION_COOKIE];
|
|
101
|
+
if (sid && authService) {
|
|
102
|
+
const result = authService.validateToken(sid);
|
|
103
|
+
if (result) {
|
|
104
|
+
authService.logout(result.sessionId);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
reply.clearCookie(SESSION_COOKIE, { path: "/" });
|
|
108
|
+
return { ok: true };
|
|
109
|
+
});
|
|
110
|
+
// POST /api/auth/change-password
|
|
111
|
+
server.post("/api/auth/change-password", async (request, reply) => {
|
|
112
|
+
if (!authService) {
|
|
113
|
+
reply.status(500).send({ error: "auth service not available" });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const { currentPassword, newPassword } = request.body;
|
|
117
|
+
if (!currentPassword || !newPassword) {
|
|
118
|
+
reply.status(400).send({ error: "currentPassword and newPassword are required" });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const user = request.user;
|
|
122
|
+
const username = user?.username;
|
|
123
|
+
if (!username) {
|
|
124
|
+
reply.status(401).send({ error: "Unauthorized" });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
await authService.changePassword(username, currentPassword, newPassword);
|
|
129
|
+
// Create a new session with the new password context
|
|
130
|
+
const newJwt = await authService.login(username, newPassword);
|
|
131
|
+
if (newJwt) {
|
|
132
|
+
reply.setCookie(SESSION_COOKIE, newJwt, COOKIE_OPTS);
|
|
133
|
+
}
|
|
134
|
+
return { ok: true };
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
reply.status(400).send({ error: err instanceof Error ? err.message : "Password change failed" });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
export default authRoutes;
|
|
142
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/web/routes/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from "fastify";
|
|
2
|
+
import type { ConfigService } from "../../config/config-service.js";
|
|
3
|
+
import type { PluginRuntime } from "../../host.js";
|
|
4
|
+
export declare function initConfigRoutes(cs: ConfigService, runtimeGetter: () => readonly PluginRuntime[]): void;
|
|
5
|
+
declare const configRoutes: FastifyPluginAsync;
|
|
6
|
+
export default configRoutes;
|
|
7
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/web/routes/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAKnD,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,aAAa,EACjB,aAAa,EAAE,MAAM,SAAS,aAAa,EAAE,GAC5C,IAAI,CAGN;AAWD,QAAA,MAAM,YAAY,EAAE,kBA0PnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// SPDX-License-Identifier: 0BSD
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Digi <digitalpaws@proton.me>
|
|
3
|
+
import { SECRET_UNCHANGED_SENTINEL } from "../../config/config-service.js";
|
|
4
|
+
let configService = null;
|
|
5
|
+
let getRuntimes = null;
|
|
6
|
+
export function initConfigRoutes(cs, runtimeGetter) {
|
|
7
|
+
configService = cs;
|
|
8
|
+
getRuntimes = runtimeGetter;
|
|
9
|
+
}
|
|
10
|
+
function requireAdmin(request, reply) {
|
|
11
|
+
const user = request.user;
|
|
12
|
+
if (!user || user.role !== "admin") {
|
|
13
|
+
reply.status(403).send({ error: "Forbidden: admin role required" });
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
const configRoutes = async (server) => {
|
|
19
|
+
// GET /api/config — list all plugin config summaries
|
|
20
|
+
server.get("/api/config", async (request, reply) => {
|
|
21
|
+
if (!requireAdmin(request, reply))
|
|
22
|
+
return;
|
|
23
|
+
if (!configService) {
|
|
24
|
+
return { plugins: [] };
|
|
25
|
+
}
|
|
26
|
+
return { plugins: configService.list() };
|
|
27
|
+
});
|
|
28
|
+
// GET /api/config/:pluginId — get single plugin config (or instance if ?instanceId=)
|
|
29
|
+
server.get("/api/config/:pluginId", async (request, reply) => {
|
|
30
|
+
if (!requireAdmin(request, reply))
|
|
31
|
+
return;
|
|
32
|
+
if (!configService) {
|
|
33
|
+
reply.status(500).send({ error: "config service not available" });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const instanceId = request.query.instanceId ?? "default";
|
|
37
|
+
const entry = configService.get(request.params.pluginId, instanceId);
|
|
38
|
+
if (!entry) {
|
|
39
|
+
reply.status(404).send({ error: "plugin/instance not found" });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Find runtime for this instance
|
|
43
|
+
const fullId = instanceId === "default"
|
|
44
|
+
? request.params.pluginId
|
|
45
|
+
: `${request.params.pluginId}::${instanceId}`;
|
|
46
|
+
const runtime = getRuntimes?.().find((r) => r.meta.id === fullId);
|
|
47
|
+
return {
|
|
48
|
+
...entry,
|
|
49
|
+
instanceId,
|
|
50
|
+
supportsTest: !!runtime?.lifecycle.testConnection,
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
// PUT /api/config/:pluginId — update config (optional ?instanceId=)
|
|
54
|
+
server.put("/api/config/:pluginId", async (request, reply) => {
|
|
55
|
+
if (!requireAdmin(request, reply))
|
|
56
|
+
return;
|
|
57
|
+
if (!configService) {
|
|
58
|
+
reply.status(500).send({ error: "config service not available" });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const instanceId = request.query.instanceId ?? "default";
|
|
62
|
+
const entry = configService.get(request.params.pluginId, instanceId);
|
|
63
|
+
if (!entry) {
|
|
64
|
+
reply.status(404).send({ error: "plugin/instance not found" });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const result = configService.update(request.params.pluginId, entry.schema, request.body, instanceId);
|
|
68
|
+
if (!result.valid) {
|
|
69
|
+
reply.status(400).send({ errors: result.errors });
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
return { ok: true };
|
|
73
|
+
});
|
|
74
|
+
// GET /api/config/:pluginId/instances — list all instances for a plugin
|
|
75
|
+
server.get("/api/config/:pluginId/instances", async (request, reply) => {
|
|
76
|
+
if (!requireAdmin(request, reply))
|
|
77
|
+
return;
|
|
78
|
+
if (!configService) {
|
|
79
|
+
reply.status(500).send({ error: "config service not available" });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const instances = configService.listInstances(request.params.pluginId);
|
|
83
|
+
return { instances };
|
|
84
|
+
});
|
|
85
|
+
// POST /api/config/:pluginId/instances — create a new instance
|
|
86
|
+
server.post("/api/config/:pluginId/instances", async (request, reply) => {
|
|
87
|
+
if (!requireAdmin(request, reply))
|
|
88
|
+
return;
|
|
89
|
+
if (!configService) {
|
|
90
|
+
reply.status(500).send({ error: "config service not available" });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const { pluginId } = request.params;
|
|
94
|
+
const { instanceId, values } = request.body;
|
|
95
|
+
if (!instanceId || typeof instanceId !== "string") {
|
|
96
|
+
reply.status(400).send({ error: "instanceId is required" });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Get the schema from the default instance (or any existing instance)
|
|
100
|
+
const defaultEntry = configService.get(pluginId, "default");
|
|
101
|
+
if (!defaultEntry) {
|
|
102
|
+
reply.status(404).send({ error: "plugin not found; configure the default instance first" });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const result = configService.createInstance(pluginId, instanceId, defaultEntry.schema, values);
|
|
106
|
+
if (!result.valid) {
|
|
107
|
+
reply.status(400).send({ errors: result.errors });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
reply.status(201).send({
|
|
111
|
+
pluginId,
|
|
112
|
+
instanceId,
|
|
113
|
+
values: result.values,
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
// DELETE /api/config/:pluginId/instances/:instanceId — delete an instance
|
|
117
|
+
server.delete("/api/config/:pluginId/instances/:instanceId", async (request, reply) => {
|
|
118
|
+
if (!requireAdmin(request, reply))
|
|
119
|
+
return;
|
|
120
|
+
if (!configService) {
|
|
121
|
+
reply.status(500).send({ error: "config service not available" });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const { pluginId, instanceId } = request.params;
|
|
125
|
+
try {
|
|
126
|
+
// If not force, check if instance has libraryId set (downloader connection)
|
|
127
|
+
if (request.query.force !== "true") {
|
|
128
|
+
const entry = configService.get(pluginId, instanceId);
|
|
129
|
+
if (entry?.values?.libraryId) {
|
|
130
|
+
reply.status(400).send({
|
|
131
|
+
error: `Instance "${instanceId}" is connected to library "${entry.values.libraryId}". Use ?force=true to disconnect and delete, or clear the libraryId first.`,
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
configService.deleteInstance(pluginId, instanceId);
|
|
137
|
+
return { deleted: true };
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
reply.status(400).send({ error: err.message });
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
// POST /api/config/:pluginId/test — test connection without saving (optional ?instanceId=)
|
|
144
|
+
server.post("/api/config/:pluginId/test", async (request, reply) => {
|
|
145
|
+
if (!requireAdmin(request, reply))
|
|
146
|
+
return;
|
|
147
|
+
if (!configService) {
|
|
148
|
+
reply.status(500).send({ error: "config service not available" });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const instanceId = request.query.instanceId ?? "default";
|
|
152
|
+
const entry = configService.get(request.params.pluginId, instanceId);
|
|
153
|
+
if (!entry) {
|
|
154
|
+
reply.status(404).send({ error: "plugin/instance not found" });
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Resolve secret sentinels without validating the body
|
|
158
|
+
const decrypted = configService.getDecryptedValues(request.params.pluginId, instanceId);
|
|
159
|
+
const testValues = { ...request.body };
|
|
160
|
+
for (const [key, rawField] of Object.entries(entry.schema)) {
|
|
161
|
+
const field = rawField;
|
|
162
|
+
if (field.type === "secret" && testValues[key] === SECRET_UNCHANGED_SENTINEL) {
|
|
163
|
+
if (!decrypted || decrypted[key] === undefined) {
|
|
164
|
+
reply.status(400).send({
|
|
165
|
+
error: `Secret field "${key}" is required to run the test`,
|
|
166
|
+
});
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
testValues[key] = decrypted[key];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Find the plugin runtime for this instance
|
|
173
|
+
const fullId = instanceId === "default"
|
|
174
|
+
? request.params.pluginId
|
|
175
|
+
: `${request.params.pluginId}::${instanceId}`;
|
|
176
|
+
const runtime = getRuntimes?.().find((r) => r.meta.id === fullId);
|
|
177
|
+
if (!runtime?.lifecycle.testConnection) {
|
|
178
|
+
reply.status(400).send({
|
|
179
|
+
error: "Plugin does not support connection tests",
|
|
180
|
+
});
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const result = await runtime.lifecycle.testConnection(testValues);
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
// Sanitize: mask any secret values in the error message
|
|
189
|
+
let sanitizedError = err instanceof Error ? err.message : String(err);
|
|
190
|
+
for (const val of Object.values(testValues)) {
|
|
191
|
+
if (typeof val === "string" && val.length > 0) {
|
|
192
|
+
sanitizedError = sanitizedError.replaceAll(val, "***");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
reply.status(500).send({
|
|
196
|
+
ok: false,
|
|
197
|
+
message: sanitizedError,
|
|
198
|
+
});
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
export default configRoutes;
|
|
204
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/web/routes/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FastifyPluginAsync } from "fastify";
|
|
2
|
+
import type { ContentTypeDescriptor } from "@digitalpaws/starr-types-core";
|
|
3
|
+
export declare function initContentTypeRoutes(listFn: () => ContentTypeDescriptor[], getFn: (id: string) => ContentTypeDescriptor | undefined): void;
|
|
4
|
+
declare const contentTypeRoutes: FastifyPluginAsync;
|
|
5
|
+
export default contentTypeRoutes;
|
|
6
|
+
//# sourceMappingURL=content-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-types.d.ts","sourceRoot":"","sources":["../../../src/web/routes/content-types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAS3E,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,qBAAqB,EAAE,EACrC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,qBAAqB,GAAG,SAAS,GACvD,IAAI,CAGN;AAED,QAAA,MAAM,iBAAiB,EAAE,kBAkBxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// SPDX-License-Identifier: 0BSD
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Digi <digitalpaws@proton.me>
|
|
3
|
+
/**
|
|
4
|
+
* This module needs access to the host's content-type registry.
|
|
5
|
+
* We provide it via module-level setters called from main.ts.
|
|
6
|
+
*/
|
|
7
|
+
let getDescriptors = () => [];
|
|
8
|
+
let getDescriptor = () => undefined;
|
|
9
|
+
export function initContentTypeRoutes(listFn, getFn) {
|
|
10
|
+
getDescriptors = listFn;
|
|
11
|
+
getDescriptor = getFn;
|
|
12
|
+
}
|
|
13
|
+
const contentTypeRoutes = async (server) => {
|
|
14
|
+
// GET /api/content-types
|
|
15
|
+
server.get("/api/content-types", async (_request, _reply) => {
|
|
16
|
+
return { types: getDescriptors() };
|
|
17
|
+
});
|
|
18
|
+
// GET /api/content-types/:id
|
|
19
|
+
server.get("/api/content-types/:id", async (request, reply) => {
|
|
20
|
+
const desc = getDescriptor(request.params.id);
|
|
21
|
+
if (!desc) {
|
|
22
|
+
reply.status(404).send({ error: "content type not found" });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
return desc;
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export default contentTypeRoutes;
|
|
29
|
+
//# sourceMappingURL=content-types.js.map
|