refactor(auth): replace @encryptid/sdk imports with local auth module
Consolidates token verification into server/auth.ts, removing the external SDK dependency. All modules now import from the local module. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2c0fbb76ac
commit
7618433498
|
|
@ -30,6 +30,7 @@ services:
|
||||||
- INFISICAL_PROJECT_SLUG=rspace
|
- INFISICAL_PROJECT_SLUG=rspace
|
||||||
- INFISICAL_ENV=prod
|
- INFISICAL_ENV=prod
|
||||||
- INFISICAL_URL=http://infisical:8080
|
- INFISICAL_URL=http://infisical:8080
|
||||||
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
- FLOW_SERVICE_URL=http://payment-flow:3010
|
- FLOW_SERVICE_URL=http://payment-flow:3010
|
||||||
- FLOW_ID=a79144ec-e6a2-4e30-a42a-6d8237a5953d
|
- FLOW_ID=a79144ec-e6a2-4e30-a42a-6d8237a5953d
|
||||||
- FUNNEL_ID=0ff6a9ac-1667-4fc7-9a01-b1620810509f
|
- FUNNEL_ID=0ff6a9ac-1667-4fc7-9a01-b1620810509f
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import * as Automerge from "@automerge/automerge";
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import { bnbSchema, bnbDocId } from './schemas';
|
import { bnbSchema, bnbDocId } from './schemas';
|
||||||
|
|
@ -573,7 +573,7 @@ routes.get("/api/listings", async (c) => {
|
||||||
routes.post("/api/listings", async (c) => {
|
routes.post("/api/listings", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -637,7 +637,7 @@ routes.get("/api/listings/:id", async (c) => {
|
||||||
routes.patch("/api/listings/:id", async (c) => {
|
routes.patch("/api/listings/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -721,7 +721,7 @@ routes.get("/api/listings/:id/availability", async (c) => {
|
||||||
routes.post("/api/listings/:id/availability", async (c) => {
|
routes.post("/api/listings/:id/availability", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -755,7 +755,7 @@ routes.post("/api/listings/:id/availability", async (c) => {
|
||||||
routes.patch("/api/availability/:id", async (c) => {
|
routes.patch("/api/availability/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -815,7 +815,7 @@ routes.get("/api/stays", async (c) => {
|
||||||
routes.post("/api/stays", async (c) => {
|
routes.post("/api/stays", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -888,7 +888,7 @@ function stayTransition(statusTarget: StayStatus, timestampField: 'respondedAt'
|
||||||
return async (c: any) => {
|
return async (c: any) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -918,7 +918,7 @@ routes.post("/api/stays/:id/complete", stayTransition('completed', 'completedAt'
|
||||||
routes.post("/api/stays/:id/messages", async (c) => {
|
routes.post("/api/stays/:id/messages", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -968,7 +968,7 @@ routes.get("/api/endorsements", async (c) => {
|
||||||
routes.post("/api/endorsements", async (c) => {
|
routes.post("/api/endorsements", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -1167,7 +1167,7 @@ routes.get("/api/config", async (c) => {
|
||||||
routes.patch("/api/config", async (c) => {
|
routes.patch("/api/config", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,7 @@ import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import {
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
verifyEncryptIDToken,
|
|
||||||
extractToken,
|
|
||||||
} from "@encryptid/sdk/server";
|
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import {
|
import {
|
||||||
booksCatalogSchema,
|
booksCatalogSchema,
|
||||||
|
|
@ -163,7 +160,7 @@ routes.post("/api/books", async (c) => {
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid token" }, 401);
|
return c.json({ error: "Invalid token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import * as Automerge from "@automerge/automerge";
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import { calendarSchema, calendarDocId } from './schemas';
|
import { calendarSchema, calendarDocId } from './schemas';
|
||||||
|
|
@ -315,7 +315,7 @@ routes.post("/api/events", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -404,7 +404,7 @@ routes.post("/api/events", async (c) => {
|
||||||
routes.post("/api/import-ics", async (c) => {
|
routes.post("/api/import-ics", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -573,7 +573,7 @@ routes.patch("/api/events/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -672,7 +672,7 @@ routes.get("/api/sources", async (c) => {
|
||||||
routes.post("/api/sources", async (c) => {
|
routes.post("/api/sources", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import { renderShell, buildSpaceUrl } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import { depositOrderRevenue } from "./flow";
|
import { depositOrderRevenue } from "./flow";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import {
|
import {
|
||||||
|
|
@ -484,7 +484,7 @@ routes.post("/api/orders", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
let buyerDid: string | null = null;
|
let buyerDid: string | null = null;
|
||||||
if (token) {
|
if (token) {
|
||||||
try { const claims = await verifyEncryptIDToken(token); buyerDid = claims.sub; } catch {}
|
try { const claims = await verifyToken(token); buyerDid = claims.sub; } catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
@ -567,7 +567,7 @@ routes.get("/api/orders", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
let authedBuyer: string | null = null;
|
let authedBuyer: string | null = null;
|
||||||
if (token) {
|
if (token) {
|
||||||
try { const claims = await verifyEncryptIDToken(token); authedBuyer = claims.sub; } catch {}
|
try { const claims = await verifyToken(token); authedBuyer = claims.sub; } catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { status, provider_id, buyer_id, limit = "50", offset = "0" } = c.req.query();
|
const { status, provider_id, buyer_id, limit = "50", offset = "0" } = c.req.query();
|
||||||
|
|
@ -1426,7 +1426,7 @@ routes.post("/api/payments", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const {
|
const {
|
||||||
|
|
@ -1512,7 +1512,7 @@ routes.get("/api/payments", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const paymentDocs = getSpacePaymentDocs(space);
|
const paymentDocs = getSpacePaymentDocs(space);
|
||||||
const payments = paymentDocs
|
const payments = paymentDocs
|
||||||
|
|
@ -2251,7 +2251,7 @@ routes.post("/api/group-buys", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { catalogEntryId, tiers, description, closesInDays } = body;
|
const { catalogEntryId, tiers, description, closesInDays } = body;
|
||||||
|
|
@ -2371,7 +2371,7 @@ routes.post("/api/group-buys/:id/pledge", async (c) => {
|
||||||
let buyerId: string | null = null;
|
let buyerId: string | null = null;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (token) {
|
if (token) {
|
||||||
try { const claims = await verifyEncryptIDToken(token); buyerId = claims.sub || null; } catch { /* public pledge */ }
|
try { const claims = await verifyToken(token); buyerId = claims.sub || null; } catch { /* public pledge */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
const pledgeId = crypto.randomUUID();
|
const pledgeId = crypto.randomUUID();
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import * as Automerge from "@automerge/automerge";
|
||||||
import { renderShell, renderExternalAppShell } from "../../server/shell";
|
import { renderShell, renderExternalAppShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import { filesSchema, filesDocId } from './schemas';
|
import { filesSchema, filesDocId } from './schemas';
|
||||||
|
|
@ -166,7 +166,7 @@ routes.post("/api/files", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
const file = formData.get("file") as File | null;
|
const file = formData.get("file") as File | null;
|
||||||
|
|
@ -300,7 +300,7 @@ routes.post("/api/files/:id/share", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const fileId = c.req.param("id");
|
const fileId = c.req.param("id");
|
||||||
const space = c.req.param("space") || c.req.query("space") || "default";
|
const space = c.req.param("space") || c.req.query("space") || "default";
|
||||||
|
|
@ -376,7 +376,7 @@ routes.post("/api/shares/:shareId/revoke", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const shareId = c.req.param("shareId");
|
const shareId = c.req.param("shareId");
|
||||||
const space = c.req.param("space") || c.req.query("space") || "default";
|
const space = c.req.param("space") || c.req.query("space") || "default";
|
||||||
|
|
@ -506,7 +506,7 @@ routes.post("/api/cards", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json<{ title: string; body?: string; card_type?: string; tags?: string[]; shared_space?: string }>();
|
const body = await c.req.json<{ title: string; body?: string; card_type?: string; tags?: string[]; shared_space?: string }>();
|
||||||
const space = c.req.param("space") || body.shared_space || "default";
|
const space = c.req.param("space") || body.shared_space || "default";
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import * as Automerge from "@automerge/automerge";
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import { getTransakEnv, getTransakWebhookSecret } from "../../shared/transak";
|
import { getTransakEnv, getTransakWebhookSecret } from "../../shared/transak";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
|
|
@ -151,7 +151,7 @@ routes.post("/api/flows", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.text();
|
const body = await c.req.text();
|
||||||
const res = await fetch(`${FLOW_SERVICE_URL}/api/flows`, {
|
const res = await fetch(`${FLOW_SERVICE_URL}/api/flows`, {
|
||||||
|
|
@ -386,7 +386,7 @@ const ENTRY_POINT = '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'; // v0.6
|
||||||
routes.post("/api/flows/submit-userop", async (c) => {
|
routes.post("/api/flows/submit-userop", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
if (!_pimlico) return c.json({ error: "Pimlico bundler not configured" }, 503);
|
if (!_pimlico) return c.json({ error: "Pimlico bundler not configured" }, 503);
|
||||||
|
|
||||||
|
|
@ -404,7 +404,7 @@ routes.post("/api/flows/submit-userop", async (c) => {
|
||||||
routes.post("/api/flows/send-userop", async (c) => {
|
routes.post("/api/flows/send-userop", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
if (!_pimlico) return c.json({ error: "Pimlico bundler not configured" }, 503);
|
if (!_pimlico) return c.json({ error: "Pimlico bundler not configured" }, 503);
|
||||||
|
|
||||||
|
|
@ -424,7 +424,7 @@ routes.post("/api/flows/send-userop", async (c) => {
|
||||||
routes.get("/api/flows/userop/:hash", async (c) => {
|
routes.get("/api/flows/userop/:hash", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
if (!_pimlico) return c.json({ error: "Pimlico bundler not configured" }, 503);
|
if (!_pimlico) return c.json({ error: "Pimlico bundler not configured" }, 503);
|
||||||
|
|
||||||
|
|
@ -540,7 +540,7 @@ routes.post("/api/space-flows", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const { space, flowId } = await c.req.json();
|
const { space, flowId } = await c.req.json();
|
||||||
if (!space || !flowId) return c.json({ error: "space and flowId required" }, 400);
|
if (!space || !flowId) return c.json({ error: "space and flowId required" }, 400);
|
||||||
|
|
@ -560,7 +560,7 @@ routes.delete("/api/space-flows/:flowId", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const flowId = c.req.param("flowId");
|
const flowId = c.req.param("flowId");
|
||||||
const space = c.req.query("space") || "";
|
const space = c.req.query("space") || "";
|
||||||
|
|
@ -636,7 +636,7 @@ routes.post("/api/mortgage/positions", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json() as Partial<MortgagePosition>;
|
const body = await c.req.json() as Partial<MortgagePosition>;
|
||||||
if (!body.principal || !body.termMonths || !body.interestRate) {
|
if (!body.principal || !body.termMonths || !body.interestRate) {
|
||||||
|
|
@ -710,7 +710,7 @@ routes.post("/api/budgets/allocate", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const { space, allocations } = await c.req.json() as { space?: string; allocations?: Record<string, number> };
|
const { space, allocations } = await c.req.json() as { space?: string; allocations?: Record<string, number> };
|
||||||
if (!allocations) return c.json({ error: "allocations required" }, 400);
|
if (!allocations) return c.json({ error: "allocations required" }, 400);
|
||||||
|
|
@ -745,7 +745,7 @@ routes.post("/api/budgets/segments", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const { space, action, segmentId, name, color } = await c.req.json() as {
|
const { space, action, segmentId, name, color } = await c.req.json() as {
|
||||||
space?: string; action: 'add' | 'remove'; segmentId?: string; name?: string; color?: string;
|
space?: string; action: 'add' | 'remove'; segmentId?: string; name?: string; color?: string;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { renderShell, renderExternalAppShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import { provisionInstance, destroyInstance } from "./lib/provisioner";
|
import { provisionInstance, destroyInstance } from "./lib/provisioner";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import {
|
import {
|
||||||
|
|
@ -44,7 +44,7 @@ routes.get("/api/instances", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const doc = ensureDoc();
|
const doc = ensureDoc();
|
||||||
const instances = Object.values(doc.instances).filter(
|
const instances = Object.values(doc.instances).filter(
|
||||||
|
|
@ -60,7 +60,7 @@ routes.post("/api/instances", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json<{
|
const body = await c.req.json<{
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -126,7 +126,7 @@ routes.get("/api/instances/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const doc = ensureDoc();
|
const doc = ensureDoc();
|
||||||
const instance = doc.instances[c.req.param("id")];
|
const instance = doc.instances[c.req.param("id")];
|
||||||
|
|
@ -142,7 +142,7 @@ routes.delete("/api/instances/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const doc = ensureDoc();
|
const doc = ensureDoc();
|
||||||
const instance = doc.instances[c.req.param("id")];
|
const instance = doc.instances[c.req.param("id")];
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import * as Automerge from "@automerge/automerge";
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import {
|
import {
|
||||||
|
|
@ -548,7 +548,7 @@ routes.post("/api/mailboxes", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { slug, name, email, description, visibility = "private", imap_user, imap_password } = body;
|
const { slug, name, email, description, visibility = "private", imap_user, imap_password } = body;
|
||||||
|
|
@ -710,7 +710,7 @@ routes.post("/api/threads/:id/comments", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const threadId = c.req.param("id");
|
const threadId = c.req.param("id");
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
@ -756,7 +756,7 @@ routes.post("/api/threads/:id/reply", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const threadId = c.req.param("id");
|
const threadId = c.req.param("id");
|
||||||
const found = findThreadById(threadId);
|
const found = findThreadById(threadId);
|
||||||
|
|
@ -805,7 +805,7 @@ routes.post("/api/threads/:id/reply-all", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const threadId = c.req.param("id");
|
const threadId = c.req.param("id");
|
||||||
const found = findThreadById(threadId);
|
const found = findThreadById(threadId);
|
||||||
|
|
@ -866,7 +866,7 @@ routes.post("/api/threads/:id/forward", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const threadId = c.req.param("id");
|
const threadId = c.req.param("id");
|
||||||
const found = findThreadById(threadId);
|
const found = findThreadById(threadId);
|
||||||
|
|
@ -963,7 +963,7 @@ routes.post("/api/approvals", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { mailbox_slug, thread_id, subject, body_text, to_addresses, cc_addresses, in_reply_to, references: refs, reply_type } = body;
|
const { mailbox_slug, thread_id, subject, body_text, to_addresses, cc_addresses, in_reply_to, references: refs, reply_type } = body;
|
||||||
|
|
@ -1009,7 +1009,7 @@ routes.post("/api/approvals/:id/sign", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const id = c.req.param("id");
|
const id = c.req.param("id");
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
@ -1083,7 +1083,7 @@ routes.post("/api/personal-inboxes", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { label, email, imap_host, imap_port, imap_user, imap_pass, smtp_host, smtp_port, smtp_user, smtp_pass } = body;
|
const { label, email, imap_host, imap_port, imap_user, imap_pass, smtp_host, smtp_port, smtp_user, smtp_pass } = body;
|
||||||
|
|
@ -1158,7 +1158,7 @@ routes.get("/api/personal-inboxes", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const inboxes: any[] = [];
|
const inboxes: any[] = [];
|
||||||
for (const { doc } of getAllMailboxDocs()) {
|
for (const { doc } of getAllMailboxDocs()) {
|
||||||
|
|
@ -1188,7 +1188,7 @@ routes.delete("/api/personal-inboxes/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const inboxId = c.req.param("id");
|
const inboxId = c.req.param("id");
|
||||||
_personalCredentials.delete(inboxId);
|
_personalCredentials.delete(inboxId);
|
||||||
|
|
@ -1214,7 +1214,7 @@ routes.post("/api/agent-inboxes", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { name, email, personality, auto_reply = false, auto_classify = false, rules = [] } = body;
|
const { name, email, personality, auto_reply = false, auto_classify = false, rules = [] } = body;
|
||||||
|
|
@ -1287,7 +1287,7 @@ routes.get("/api/agent-inboxes", async (c) => {
|
||||||
routes.delete("/api/agent-inboxes/:id", async (c) => {
|
routes.delete("/api/agent-inboxes/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const agentId = c.req.param("id");
|
const agentId = c.req.param("id");
|
||||||
|
|
||||||
|
|
@ -1328,7 +1328,7 @@ routes.post("/api/workspaces", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { slug, name, description } = body;
|
const { slug, name, description } = body;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
||||||
import { resolveDataSpace } from "../../shared/scope-resolver";
|
import { resolveDataSpace } from "../../shared/scope-resolver";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import { notebookSchema, notebookDocId, connectionsDocId, createNoteItem } from "./schemas";
|
import { notebookSchema, notebookDocId, connectionsDocId, createNoteItem } from "./schemas";
|
||||||
import type { NotebookDoc, NoteItem, ConnectionsDoc } from "./schemas";
|
import type { NotebookDoc, NoteItem, ConnectionsDoc } from "./schemas";
|
||||||
|
|
@ -285,7 +285,7 @@ routes.post("/api/notebooks", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { title, description, cover_color } = body;
|
const { title, description, cover_color } = body;
|
||||||
|
|
@ -339,7 +339,7 @@ routes.put("/api/notebooks/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const id = c.req.param("id");
|
const id = c.req.param("id");
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
@ -437,7 +437,7 @@ routes.post("/api/notes", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { notebook_id, title, content, content_format, type, url, language, file_url, mime_type, file_size, duration, tags } = body;
|
const { notebook_id, title, content, content_format, type, url, language, file_url, mime_type, file_size, duration, tags } = body;
|
||||||
|
|
@ -641,7 +641,7 @@ routes.post("/api/import/upload", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
const file = formData.get("file") as File | null;
|
const file = formData.get("file") as File | null;
|
||||||
|
|
@ -693,7 +693,7 @@ routes.post("/api/import/files", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
const notebookId = formData.get("notebookId") as string | null;
|
const notebookId = formData.get("notebookId") as string | null;
|
||||||
|
|
@ -745,7 +745,7 @@ routes.post("/api/import/notion", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { pageIds, notebookId, recursive } = body;
|
const { pageIds, notebookId, recursive } = body;
|
||||||
|
|
@ -791,7 +791,7 @@ routes.post("/api/import/google-docs", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { docIds, notebookId } = body;
|
const { docIds, notebookId } = body;
|
||||||
|
|
@ -996,7 +996,7 @@ routes.post("/api/export/notion", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { notebookId, noteIds, parentId } = body;
|
const { notebookId, noteIds, parentId } = body;
|
||||||
|
|
@ -1036,7 +1036,7 @@ routes.post("/api/export/google-docs", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { notebookId, noteIds, parentId } = body;
|
const { notebookId, noteIds, parentId } = body;
|
||||||
|
|
@ -1078,7 +1078,7 @@ routes.post("/api/sync/note/:noteId", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const noteId = c.req.param("noteId");
|
const noteId = c.req.param("noteId");
|
||||||
const found = findNote(dataSpace, noteId);
|
const found = findNote(dataSpace, noteId);
|
||||||
|
|
@ -1131,7 +1131,7 @@ routes.post("/api/sync/notebook/:id", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const notebookId = c.req.param("id");
|
const notebookId = c.req.param("id");
|
||||||
const docId = notebookDocId(dataSpace, notebookId);
|
const docId = notebookDocId(dataSpace, notebookId);
|
||||||
|
|
@ -1191,7 +1191,7 @@ routes.post("/api/sync/upload", async (c) => {
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
const file = formData.get("file") as File | null;
|
const file = formData.get("file") as File | null;
|
||||||
|
|
@ -1306,7 +1306,7 @@ const UPLOAD_DIR = "/data/files/generated";
|
||||||
routes.post("/api/uploads", async (c) => {
|
routes.post("/api/uploads", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
const file = formData.get("file") as File | null;
|
const file = formData.get("file") as File | null;
|
||||||
|
|
@ -1351,7 +1351,7 @@ routes.get("/api/uploads/:filename", async (c) => {
|
||||||
routes.post("/api/voice/transcribe", async (c) => {
|
routes.post("/api/voice/transcribe", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
|
|
@ -1372,7 +1372,7 @@ routes.post("/api/voice/transcribe", async (c) => {
|
||||||
routes.post("/api/voice/diarize", async (c) => {
|
routes.post("/api/voice/diarize", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const formData = await c.req.formData();
|
const formData = await c.req.formData();
|
||||||
|
|
@ -1397,7 +1397,7 @@ const NOTEBOOK_API_URL = process.env.NOTEBOOK_API_URL || "http://open-notebook:5
|
||||||
routes.post("/api/notes/summarize", async (c) => {
|
routes.post("/api/notes/summarize", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const { content, model = "gemini-flash", length = "medium" } = await c.req.json<{
|
const { content, model = "gemini-flash", length = "medium" } = await c.req.json<{
|
||||||
content: string; model?: string; length?: "short" | "medium" | "long";
|
content: string; model?: string; length?: "short" | "medium" | "long";
|
||||||
|
|
@ -1443,7 +1443,7 @@ routes.post("/api/notes/summarize", async (c) => {
|
||||||
routes.post("/api/notes/deep-summarize", async (c) => {
|
routes.post("/api/notes/deep-summarize", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const { noteIds, query } = await c.req.json<{ noteIds: string[]; query?: string }>();
|
const { noteIds, query } = await c.req.json<{ noteIds: string[]; query?: string }>();
|
||||||
if (!noteIds?.length) return c.json({ error: "noteIds required" }, 400);
|
if (!noteIds?.length) return c.json({ error: "noteIds required" }, 400);
|
||||||
|
|
@ -1498,7 +1498,7 @@ routes.post("/api/notes/deep-summarize", async (c) => {
|
||||||
routes.post("/api/notes/send-to-notebook", async (c) => {
|
routes.post("/api/notes/send-to-notebook", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const { noteId, title, content } = await c.req.json<{
|
const { noteId, title, content } = await c.req.json<{
|
||||||
noteId: string; title: string; content: string;
|
noteId: string; title: string; content: string;
|
||||||
|
|
@ -1535,7 +1535,7 @@ routes.post("/api/notes/send-to-notebook", async (c) => {
|
||||||
routes.post("/api/articles/unlock", async (c) => {
|
routes.post("/api/articles/unlock", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Unauthorized" }, 401);
|
if (!token) return c.json({ error: "Unauthorized" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const { url } = await c.req.json<{ url: string }>();
|
const { url } = await c.req.json<{ url: string }>();
|
||||||
if (!url) return c.json({ error: "Missing url" }, 400);
|
if (!url) return c.json({ error: "Missing url" }, 400);
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ import {
|
||||||
import { DEMO_FEED } from "./lib/types";
|
import { DEMO_FEED } from "./lib/types";
|
||||||
import { getListmonkConfig, listmonkFetch } from "./lib/listmonk-proxy";
|
import { getListmonkConfig, listmonkFetch } from "./lib/listmonk-proxy";
|
||||||
import { getPostizConfig, getIntegrations, createPost, createThread } from "./lib/postiz-client";
|
import { getPostizConfig, getIntegrations, createPost, createThread } from "./lib/postiz-client";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import type { EncryptIDClaims } from "@encryptid/sdk/server";
|
import type { EncryptIDClaims } from "../../server/auth";
|
||||||
import { resolveCallerRole, roleAtLeast } from "../../server/spaces";
|
import { resolveCallerRole, roleAtLeast } from "../../server/spaces";
|
||||||
import type { SpaceRoleString } from "../../server/spaces";
|
import type { SpaceRoleString } from "../../server/spaces";
|
||||||
|
|
||||||
|
|
@ -432,7 +432,7 @@ async function requireNewsletterRole(c: any, minRole: SpaceRoleString): Promise<
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const result = await resolveCallerRole(space, claims);
|
const result = await resolveCallerRole(space, claims);
|
||||||
|
|
@ -1951,7 +1951,7 @@ routes.get("/newsletter-list", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
const claims = await verifyEncryptIDToken(token);
|
const claims = await verifyToken(token);
|
||||||
const result = await resolveCallerRole(space, claims);
|
const result = await resolveCallerRole(space, claims);
|
||||||
if (result) role = result.role;
|
if (result) role = result.role;
|
||||||
} catch { /* keep viewer default */ }
|
} catch { /* keep viewer default */ }
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,7 @@ import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import {
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
verifyEncryptIDToken,
|
|
||||||
extractToken,
|
|
||||||
} from "@encryptid/sdk/server";
|
|
||||||
import { setupX402FromEnv } from "../../shared/x402/hono-middleware";
|
import { setupX402FromEnv } from "../../shared/x402/hono-middleware";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import {
|
import {
|
||||||
|
|
@ -300,7 +297,7 @@ routes.post("/api/splats", async (c) => {
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid token" }, 401);
|
return c.json({ error: "Invalid token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
@ -413,7 +410,7 @@ routes.post("/api/splats/from-media", async (c) => {
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid token" }, 401);
|
return c.json({ error: "Invalid token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
@ -557,7 +554,7 @@ routes.post("/api/splats/save-generated", async (c) => {
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid token" }, 401);
|
return c.json({ error: "Invalid token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
@ -646,7 +643,7 @@ routes.get("/api/splats/my-history", async (c) => {
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid token" }, 401);
|
return c.json({ error: "Invalid token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
@ -670,7 +667,7 @@ routes.delete("/api/splats/:id", async (c) => {
|
||||||
|
|
||||||
let claims;
|
let claims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid token" }, 401);
|
return c.json({ error: "Invalid token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import * as Automerge from '@automerge/automerge';
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import { boardSchema, boardDocId, createTaskItem } from './schemas';
|
import { boardSchema, boardDocId, createTaskItem } from './schemas';
|
||||||
|
|
@ -214,7 +214,7 @@ routes.post("/api/spaces", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { name, description, icon } = body;
|
const { name, description, icon } = body;
|
||||||
|
|
@ -322,7 +322,7 @@ routes.post("/api/spaces/:slug/tasks", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const slug = c.req.param("slug");
|
const slug = c.req.param("slug");
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
@ -367,7 +367,7 @@ routes.patch("/api/tasks/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
let updatedBy: string | null = null;
|
let updatedBy: string | null = null;
|
||||||
if (token) {
|
if (token) {
|
||||||
try { const claims = await verifyEncryptIDToken(token); updatedBy = claims.sub; } catch {}
|
try { const claims = await verifyToken(token); updatedBy = claims.sub; } catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = c.req.param("id");
|
const id = c.req.param("id");
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import * as Automerge from "@automerge/automerge";
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import {
|
import {
|
||||||
|
|
@ -96,7 +96,7 @@ routes.post("/api/trips", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { title, description, start_date, end_date, budget_total, budget_currency } = body;
|
const { title, description, start_date, end_date, budget_total, budget_currency } = body;
|
||||||
|
|
@ -199,7 +199,7 @@ routes.put("/api/trips/:id", async (c) => {
|
||||||
routes.post("/api/trips/:id/destinations", async (c) => {
|
routes.post("/api/trips/:id/destinations", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -236,7 +236,7 @@ routes.post("/api/trips/:id/destinations", async (c) => {
|
||||||
routes.post("/api/trips/:id/itinerary", async (c) => {
|
routes.post("/api/trips/:id/itinerary", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -273,7 +273,7 @@ routes.post("/api/trips/:id/itinerary", async (c) => {
|
||||||
routes.post("/api/trips/:id/bookings", async (c) => {
|
routes.post("/api/trips/:id/bookings", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -311,7 +311,7 @@ routes.post("/api/trips/:id/bookings", async (c) => {
|
||||||
routes.post("/api/trips/:id/expenses", async (c) => {
|
routes.post("/api/trips/:id/expenses", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -362,7 +362,7 @@ routes.get("/api/trips/:id/packing", async (c) => {
|
||||||
routes.post("/api/trips/:id/packing", async (c) => {
|
routes.post("/api/trips/:id/packing", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { Hono } from "hono";
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import { S3Client, ListObjectsV2Command, GetObjectCommand, HeadObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
|
import { S3Client, ListObjectsV2Command, GetObjectCommand, HeadObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
|
||||||
|
|
||||||
|
|
@ -152,7 +152,7 @@ routes.get("/api/v/*", async (c) => {
|
||||||
routes.post("/api/videos", async (c) => {
|
routes.post("/api/videos", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const client = getS3();
|
const client = getS3();
|
||||||
if (!client) return c.json({ error: "R2 not configured" }, 503);
|
if (!client) return c.json({ error: "R2 not configured" }, 503);
|
||||||
|
|
@ -198,7 +198,7 @@ routes.get("/api/health", (c) => c.json({ ok: true }));
|
||||||
routes.post("/api/360split", async (c) => {
|
routes.post("/api/360split", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
||||||
|
|
||||||
|
|
@ -255,7 +255,7 @@ routes.get("/api/360split/status/:jobId", async (c) => {
|
||||||
routes.post("/api/360split/import/:jobId", async (c) => {
|
routes.post("/api/360split/import/:jobId", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
||||||
const client = getS3();
|
const client = getS3();
|
||||||
|
|
@ -312,7 +312,7 @@ routes.post("/api/360split/import/:jobId", async (c) => {
|
||||||
routes.post("/api/live-split", async (c) => {
|
routes.post("/api/live-split", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
||||||
|
|
||||||
|
|
@ -363,7 +363,7 @@ routes.get("/api/live-split/status/:sessionId", async (c) => {
|
||||||
routes.post("/api/live-split/stop/:sessionId", async (c) => {
|
routes.post("/api/live-split/stop/:sessionId", async (c) => {
|
||||||
const authToken = extractToken(c.req.raw.headers);
|
const authToken = extractToken(c.req.raw.headers);
|
||||||
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
if (!authToken) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
if (!SPLIT_360_URL) return c.json({ error: "360split service not configured" }, 503);
|
||||||
const sessionId = c.req.param("sessionId");
|
const sessionId = c.req.param("sessionId");
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import * as Automerge from "@automerge/automerge";
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import { vnbSchema, vnbDocId } from './schemas';
|
import { vnbSchema, vnbDocId } from './schemas';
|
||||||
|
|
@ -612,7 +612,7 @@ routes.get("/api/vehicles", async (c) => {
|
||||||
routes.post("/api/vehicles", async (c) => {
|
routes.post("/api/vehicles", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -691,7 +691,7 @@ routes.get("/api/vehicles/:id", async (c) => {
|
||||||
routes.patch("/api/vehicles/:id", async (c) => {
|
routes.patch("/api/vehicles/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -782,7 +782,7 @@ routes.get("/api/vehicles/:id/availability", async (c) => {
|
||||||
routes.post("/api/vehicles/:id/availability", async (c) => {
|
routes.post("/api/vehicles/:id/availability", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -822,7 +822,7 @@ routes.post("/api/vehicles/:id/availability", async (c) => {
|
||||||
routes.patch("/api/availability/:id", async (c) => {
|
routes.patch("/api/availability/:id", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -888,7 +888,7 @@ routes.get("/api/rentals", async (c) => {
|
||||||
routes.post("/api/rentals", async (c) => {
|
routes.post("/api/rentals", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -967,7 +967,7 @@ function rentalTransition(statusTarget: RentalStatus, timestampField: 'responded
|
||||||
return async (c: any) => {
|
return async (c: any) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -997,7 +997,7 @@ routes.post("/api/rentals/:id/complete", rentalTransition('completed', 'complete
|
||||||
routes.post("/api/rentals/:id/messages", async (c) => {
|
routes.post("/api/rentals/:id/messages", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -1047,7 +1047,7 @@ routes.get("/api/endorsements", async (c) => {
|
||||||
routes.post("/api/endorsements", async (c) => {
|
routes.post("/api/endorsements", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
@ -1250,7 +1250,7 @@ routes.get("/api/config", async (c) => {
|
||||||
routes.patch("/api/config", async (c) => {
|
routes.patch("/api/config", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const space = c.req.param("space") || "demo";
|
const space = c.req.param("space") || "demo";
|
||||||
const dataSpace = c.get("effectiveSpace") || space;
|
const dataSpace = c.get("effectiveSpace") || space;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import * as Automerge from '@automerge/automerge';
|
||||||
import { renderShell } from "../../server/shell";
|
import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import type { SyncServer } from '../../server/local-first/sync-server';
|
import type { SyncServer } from '../../server/local-first/sync-server';
|
||||||
import { proposalSchema, proposalDocId, computeElo, ELO_DEFAULT } from './schemas';
|
import { proposalSchema, proposalDocId, computeElo, ELO_DEFAULT } from './schemas';
|
||||||
|
|
@ -286,7 +286,7 @@ routes.post("/api/spaces", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { name, slug, description, visibility = "public" } = body;
|
const { name, slug, description, visibility = "public" } = body;
|
||||||
|
|
@ -359,7 +359,7 @@ routes.post("/api/proposals", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { space_slug, title, description } = body;
|
const { space_slug, title, description } = body;
|
||||||
|
|
@ -407,7 +407,7 @@ routes.post("/api/proposals/:id/vote", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const id = c.req.param("id");
|
const id = c.req.param("id");
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
@ -470,7 +470,7 @@ routes.post("/api/proposals/:id/final-vote", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims;
|
let claims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const id = c.req.param("id");
|
const id = c.req.param("id");
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
@ -564,7 +564,7 @@ routes.get("/api/proposals/pair", (c) => {
|
||||||
routes.post("/api/proposals/compare", async (c) => {
|
routes.post("/api/proposals/compare", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
try { await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
const { winnerId, loserId } = body;
|
const { winnerId, loserId } = body;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { renderShell } from "../../server/shell";
|
||||||
import { getModuleInfoList } from "../../shared/module";
|
import { getModuleInfoList } from "../../shared/module";
|
||||||
import type { RSpaceModule } from "../../shared/module";
|
import type { RSpaceModule } from "../../shared/module";
|
||||||
import { renderLanding } from "./landing";
|
import { renderLanding } from "./landing";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "../../server/auth";
|
||||||
|
|
||||||
const routes = new Hono();
|
const routes = new Hono();
|
||||||
|
|
||||||
|
|
@ -271,7 +271,7 @@ async function verifyWalletAuth(c: any): Promise<{ sub: string; did?: string; us
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return null;
|
if (!token) return null;
|
||||||
try {
|
try {
|
||||||
const claims = await verifyEncryptIDToken(token);
|
const claims = await verifyToken(token);
|
||||||
return claims as any;
|
return claims as any;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* Auth wrapper — local JWT verification for rSpace server.
|
||||||
|
*
|
||||||
|
* When JWT_SECRET is available, verifies tokens locally via HMAC-SHA256 (<1ms).
|
||||||
|
* Otherwise falls back to internal HTTP call to EncryptID service.
|
||||||
|
* Re-exports extractToken and types for convenience.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
||||||
|
import type { EncryptIDClaims, VerifyOptions } from "@encryptid/sdk/server";
|
||||||
|
|
||||||
|
export { extractToken };
|
||||||
|
export type { EncryptIDClaims };
|
||||||
|
|
||||||
|
const JWT_SECRET = process.env.JWT_SECRET;
|
||||||
|
const ENCRYPTID_INTERNAL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000";
|
||||||
|
|
||||||
|
const verifyOpts: VerifyOptions = JWT_SECRET
|
||||||
|
? { secret: JWT_SECRET }
|
||||||
|
: { serverUrl: ENCRYPTID_INTERNAL };
|
||||||
|
|
||||||
|
export function verifyToken(token: string): Promise<EncryptIDClaims> {
|
||||||
|
return verifyEncryptIDToken(token, verifyOpts);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
declare module '@encryptid/sdk/server' {
|
declare module '@encryptid/sdk/server' {
|
||||||
export function verifyEncryptIDToken(token: string): Promise<EncryptIDClaims>;
|
export interface VerifyOptions {
|
||||||
|
/** JWT secret for local HMAC-SHA256 verification */
|
||||||
|
secret?: string;
|
||||||
|
/** EncryptID server URL for remote verification */
|
||||||
|
serverUrl?: string;
|
||||||
|
/** Expected audience */
|
||||||
|
audience?: string;
|
||||||
|
/** Clock tolerance in seconds */
|
||||||
|
clockTolerance?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function verifyEncryptIDToken(token: string, options?: VerifyOptions): Promise<EncryptIDClaims>;
|
||||||
export function evaluateSpaceAccess(
|
export function evaluateSpaceAccess(
|
||||||
slug: string,
|
slug: string,
|
||||||
token: string | null,
|
token: string | null,
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,8 @@
|
||||||
|
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import type { Context, Next } from "hono";
|
import type { Context, Next } from "hono";
|
||||||
import {
|
import { verifyToken, extractToken } from "../auth";
|
||||||
verifyEncryptIDToken,
|
import type { EncryptIDClaims } from "../auth";
|
||||||
extractToken,
|
|
||||||
} from "@encryptid/sdk/server";
|
|
||||||
import type { EncryptIDClaims } from "@encryptid/sdk/server";
|
|
||||||
import {
|
import {
|
||||||
putBackup,
|
putBackup,
|
||||||
getBackup,
|
getBackup,
|
||||||
|
|
@ -40,7 +37,7 @@ backupRouter.use("*", async (c: Context<BackupEnv>, next: Next) => {
|
||||||
}
|
}
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid or expired token" }, 401);
|
return c.json({ error: "Invalid or expired token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ import type { MiMessage } from "./mi-provider";
|
||||||
import { getModuleInfoList, getAllModules } from "../shared/module";
|
import { getModuleInfoList, getAllModules } from "../shared/module";
|
||||||
import { resolveCallerRole, roleAtLeast } from "./spaces";
|
import { resolveCallerRole, roleAtLeast } from "./spaces";
|
||||||
import type { SpaceRoleString } from "./spaces";
|
import type { SpaceRoleString } from "./spaces";
|
||||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
import { verifyToken, extractToken } from "./auth";
|
||||||
import type { EncryptIDClaims } from "@encryptid/sdk/server";
|
import type { EncryptIDClaims } from "./auth";
|
||||||
import { buildModuleCapabilities, MODULE_ROUTES } from "../lib/mi-module-routes";
|
import { buildModuleCapabilities, MODULE_ROUTES } from "../lib/mi-module-routes";
|
||||||
import type { MiAction } from "../lib/mi-actions";
|
import type { MiAction } from "../lib/mi-actions";
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ mi.post("/ask", async (c) => {
|
||||||
try {
|
try {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (token) {
|
if (token) {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
}
|
}
|
||||||
} catch { /* unauthenticated → viewer */ }
|
} catch { /* unauthenticated → viewer */ }
|
||||||
|
|
||||||
|
|
@ -369,7 +369,7 @@ mi.post("/validate-actions", async (c) => {
|
||||||
try {
|
try {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (token) {
|
if (token) {
|
||||||
const claims = await verifyEncryptIDToken(token);
|
const claims = await verifyToken(token);
|
||||||
if (space && claims) {
|
if (space && claims) {
|
||||||
const resolved = await resolveCallerRole(space, claims);
|
const resolved = await resolveCallerRole(space, claims);
|
||||||
if (resolved) callerRole = resolved.role;
|
if (resolved) callerRole = resolved.role;
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import {
|
import { verifyToken, extractToken } from "./auth";
|
||||||
verifyEncryptIDToken,
|
|
||||||
extractToken,
|
|
||||||
} from "@encryptid/sdk/server";
|
|
||||||
import {
|
import {
|
||||||
getUserNotifications,
|
getUserNotifications,
|
||||||
getUnreadCount,
|
getUnreadCount,
|
||||||
|
|
@ -28,7 +25,7 @@ async function requireAuth(req: Request) {
|
||||||
const token = extractToken(req.headers);
|
const token = extractToken(req.headers);
|
||||||
if (!token) return null;
|
if (!token) return null;
|
||||||
try {
|
try {
|
||||||
return await verifyEncryptIDToken(token);
|
return await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,8 @@ import {
|
||||||
invertDirection,
|
invertDirection,
|
||||||
computeMembranePermeability,
|
computeMembranePermeability,
|
||||||
} from "../lib/connection-types";
|
} from "../lib/connection-types";
|
||||||
import {
|
import { verifyToken, extractToken } from "./auth";
|
||||||
verifyEncryptIDToken,
|
import type { EncryptIDClaims } from "./auth";
|
||||||
extractToken,
|
|
||||||
} from "@encryptid/sdk/server";
|
|
||||||
import type { EncryptIDClaims } from "@encryptid/sdk/server";
|
|
||||||
import { getAllModules, getModule } from "../shared/module";
|
import { getAllModules, getModule } from "../shared/module";
|
||||||
import type { SpaceLifecycleContext } from "../shared/module";
|
import type { SpaceLifecycleContext } from "../shared/module";
|
||||||
import { syncServer } from "./sync-instance";
|
import { syncServer } from "./sync-instance";
|
||||||
|
|
@ -222,7 +219,7 @@ spaces.get("/", async (c) => {
|
||||||
let claims: EncryptIDClaims | null = null;
|
let claims: EncryptIDClaims | null = null;
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
// Invalid token — treat as unauthenticated
|
// Invalid token — treat as unauthenticated
|
||||||
}
|
}
|
||||||
|
|
@ -320,7 +317,7 @@ spaces.post("/", async (c) => {
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try {
|
try {
|
||||||
claims = await verifyEncryptIDToken(token);
|
claims = await verifyToken(token);
|
||||||
} catch {
|
} catch {
|
||||||
return c.json({ error: "Invalid or expired token" }, 401);
|
return c.json({ error: "Invalid or expired token" }, 401);
|
||||||
}
|
}
|
||||||
|
|
@ -397,7 +394,7 @@ spaces.patch("/:slug/modules", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const doc = getDocumentData(slug);
|
const doc = getDocumentData(slug);
|
||||||
|
|
@ -484,7 +481,7 @@ spaces.get("/admin", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
if (!isAdmin(claims.sub)) return c.json({ error: "Admin access required" }, 403);
|
if (!isAdmin(claims.sub)) return c.json({ error: "Admin access required" }, 403);
|
||||||
|
|
||||||
const STORAGE_DIR = process.env.STORAGE_DIR || "./data/communities";
|
const STORAGE_DIR = process.env.STORAGE_DIR || "./data/communities";
|
||||||
|
|
@ -550,7 +547,7 @@ spaces.delete("/admin/:slug", async (c) => {
|
||||||
const token = extractToken(c.req.raw.headers);
|
const token = extractToken(c.req.raw.headers);
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
if (!isAdmin(claims.sub)) return c.json({ error: "Admin access required" }, 403);
|
if (!isAdmin(claims.sub)) return c.json({ error: "Admin access required" }, 403);
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
|
|
@ -598,7 +595,7 @@ spaces.get("/notifications", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const slugs = await listCommunities();
|
const slugs = await listCommunities();
|
||||||
const ownedSlugs = new Set<string>();
|
const ownedSlugs = new Set<string>();
|
||||||
|
|
@ -647,7 +644,7 @@ spaces.delete("/:slug", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
// Protect core spaces
|
// Protect core spaces
|
||||||
if (slug === "demo" || slug === "commonshub") {
|
if (slug === "demo" || slug === "commonshub") {
|
||||||
|
|
@ -696,7 +693,7 @@ spaces.patch("/:slug", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -736,7 +733,7 @@ spaces.get("/:slug/members", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -765,7 +762,7 @@ spaces.patch("/:slug/members/:did", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -815,7 +812,7 @@ spaces.delete("/:slug/members/:did", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -856,7 +853,7 @@ spaces.get("/:slug/access-requests", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -896,7 +893,7 @@ spaces.patch("/:slug/nest-policy", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -935,7 +932,7 @@ spaces.post("/:slug/nest", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json<{
|
const body = await c.req.json<{
|
||||||
sourceSlug: string;
|
sourceSlug: string;
|
||||||
|
|
@ -1072,7 +1069,7 @@ spaces.patch("/:slug/nest/:refId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1104,7 +1101,7 @@ spaces.delete("/:slug/nest/:refId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1146,7 +1143,7 @@ spaces.get("/:slug/nested-in", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
// Must be admin/owner of the space to see where it's nested
|
// Must be admin/owner of the space to see where it's nested
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
|
|
@ -1175,7 +1172,7 @@ spaces.get("/:slug/nest-requests", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1203,7 +1200,7 @@ spaces.patch("/:slug/nest-requests/:reqId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1290,7 +1287,7 @@ spaces.patch("/:slug/connection-policy", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1316,7 +1313,7 @@ spaces.get("/:slug/connections", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1341,7 +1338,7 @@ spaces.post("/:slug/connections", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json<{
|
const body = await c.req.json<{
|
||||||
toSlug: string;
|
toSlug: string;
|
||||||
|
|
@ -1496,7 +1493,7 @@ spaces.get("/:slug/connections/:connId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1523,7 +1520,7 @@ spaces.patch("/:slug/connections/:connId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1592,7 +1589,7 @@ spaces.delete("/:slug/connections/:connId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1641,7 +1638,7 @@ spaces.get("/:slug/connection-requests", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1669,7 +1666,7 @@ spaces.patch("/:slug/connection-requests/:reqId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1759,7 +1756,7 @@ spaces.get("/:slug/membrane", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1803,7 +1800,7 @@ spaces.patch("/:slug/encryption", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1843,7 +1840,7 @@ spaces.post("/:slug/access-requests", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1904,7 +1901,7 @@ spaces.patch("/:slug/access-requests/:reqId", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -1985,7 +1982,7 @@ spaces.post("/:slug/copy-shapes", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
// Verify target space exists and user has write access
|
// Verify target space exists and user has write access
|
||||||
await loadCommunity(targetSlug);
|
await loadCommunity(targetSlug);
|
||||||
|
|
@ -2098,7 +2095,7 @@ spaces.post("/:slug/invite", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -2218,7 +2215,7 @@ spaces.post("/:slug/members/add", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
@ -2325,7 +2322,7 @@ spaces.post("/:slug/invite/accept", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required — sign in first" }, 401);
|
if (!token) return c.json({ error: "Authentication required — sign in first" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
const body = await c.req.json<{ inviteToken: string }>();
|
const body = await c.req.json<{ inviteToken: string }>();
|
||||||
if (!body.inviteToken) return c.json({ error: "inviteToken is required" }, 400);
|
if (!body.inviteToken) return c.json({ error: "inviteToken is required" }, 400);
|
||||||
|
|
@ -2359,7 +2356,7 @@ spaces.get("/:slug/invites", async (c) => {
|
||||||
if (!token) return c.json({ error: "Authentication required" }, 401);
|
if (!token) return c.json({ error: "Authentication required" }, 401);
|
||||||
|
|
||||||
let claims: EncryptIDClaims;
|
let claims: EncryptIDClaims;
|
||||||
try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
try { claims = await verifyToken(token); } catch { return c.json({ error: "Invalid token" }, 401); }
|
||||||
|
|
||||||
await loadCommunity(slug);
|
await loadCommunity(slug);
|
||||||
const data = getDocumentData(slug);
|
const data = getDocumentData(slug);
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ export class RStackSpaceSettings extends HTMLElement {
|
||||||
private _addMode: "username" | "email" = "username";
|
private _addMode: "username" | "email" = "username";
|
||||||
private _lookupResult: { did: string; username: string; displayName: string } | null = null;
|
private _lookupResult: { did: string; username: string; displayName: string } | null = null;
|
||||||
private _lookupError = "";
|
private _lookupError = "";
|
||||||
|
private _searchResults: { id: string; did: string; username: string; displayName: string }[] = [];
|
||||||
private _moduleId = "";
|
private _moduleId = "";
|
||||||
private _moduleConfig: ModuleConfig | null = null;
|
private _moduleConfig: ModuleConfig | null = null;
|
||||||
private _moduleSettingsValues: Record<string, string | boolean> = {};
|
private _moduleSettingsValues: Record<string, string | boolean> = {};
|
||||||
|
|
@ -167,20 +168,25 @@ export class RStackSpaceSettings extends HTMLElement {
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve missing displayNames from EncryptID
|
// Resolve displayNames from EncryptID for all members + owner
|
||||||
const unresolvedDids = this._members.filter(m => !m.displayName).map(m => m.did);
|
const allDids = [...new Set([
|
||||||
if (unresolvedDids.length) {
|
...this._members.map(m => m.did),
|
||||||
|
...(this._ownerDID ? [this._ownerDID] : []),
|
||||||
|
])];
|
||||||
|
if (allDids.length) {
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/users/resolve-dids", {
|
const res = await fetch("/api/users/resolve-dids", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ dids: unresolvedDids }),
|
body: JSON.stringify({ dids: allDids }),
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const resolved = await res.json() as Record<string, { username: string; displayName: string }>;
|
const resolved = await res.json() as Record<string, { username: string; displayName: string }>;
|
||||||
for (const m of this._members) {
|
for (const m of this._members) {
|
||||||
if (!m.displayName && resolved[m.did]) {
|
// Match by did or by id (members may be stored as userId)
|
||||||
m.displayName = resolved[m.did].displayName || resolved[m.did].username;
|
const info = resolved[m.did];
|
||||||
|
if (info) {
|
||||||
|
m.displayName = info.displayName || info.username;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +297,7 @@ export class RStackSpaceSettings extends HTMLElement {
|
||||||
|
|
||||||
const membersHTML = this._members.map(m => {
|
const membersHTML = this._members.map(m => {
|
||||||
const isOwnerRow = m.did === this._ownerDID;
|
const isOwnerRow = m.did === this._ownerDID;
|
||||||
const displayName = m.displayName || m.did.slice(0, 16) + "…";
|
const displayName = m.displayName || "Unknown user";
|
||||||
const initial = displayName.charAt(0).toUpperCase();
|
const initial = displayName.charAt(0).toUpperCase();
|
||||||
const roleBadge = isOwnerRow
|
const roleBadge = isOwnerRow
|
||||||
? `<span class="role-badge role-owner">Owner</span>`
|
? `<span class="role-badge role-owner">Owner</span>`
|
||||||
|
|
@ -404,8 +410,20 @@ export class RStackSpaceSettings extends HTMLElement {
|
||||||
|
|
||||||
${this._addMode === "username" ? `
|
${this._addMode === "username" ? `
|
||||||
<div class="add-form">
|
<div class="add-form">
|
||||||
<input type="text" class="input" id="add-username" placeholder="Username…" />
|
<div class="search-wrapper">
|
||||||
${this._lookupResult ? `<div class="lookup-result">Found: <strong>${this._esc(this._lookupResult.displayName)}</strong> (@${this._esc(this._lookupResult.username)})</div>` : ""}
|
<input type="text" class="input" id="add-username" placeholder="Search username…" autocomplete="off" />
|
||||||
|
${this._searchResults.length > 0 ? `
|
||||||
|
<div class="search-dropdown">
|
||||||
|
${this._searchResults.map((u, i) => `
|
||||||
|
<div class="search-item" data-idx="${i}">
|
||||||
|
<span class="search-item-name">${this._esc(u.displayName)}</span>
|
||||||
|
<span class="search-item-username">@${this._esc(u.username)}</span>
|
||||||
|
</div>
|
||||||
|
`).join("")}
|
||||||
|
</div>
|
||||||
|
` : ""}
|
||||||
|
</div>
|
||||||
|
${this._lookupResult ? `<div class="lookup-result">Selected: <strong>${this._esc(this._lookupResult.displayName)}</strong> (@${this._esc(this._lookupResult.username)})</div>` : ""}
|
||||||
${this._lookupError ? `<div class="error-msg">${this._esc(this._lookupError)}</div>` : ""}
|
${this._lookupError ? `<div class="error-msg">${this._esc(this._lookupError)}</div>` : ""}
|
||||||
<div class="add-row">
|
<div class="add-row">
|
||||||
<select class="input role-input" id="add-role">
|
<select class="input role-input" id="add-role">
|
||||||
|
|
@ -414,7 +432,7 @@ export class RStackSpaceSettings extends HTMLElement {
|
||||||
<option value="moderator">moderator</option>
|
<option value="moderator">moderator</option>
|
||||||
<option value="admin">admin</option>
|
<option value="admin">admin</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="add-btn" id="add-by-username">Add</button>
|
<button class="add-btn" id="add-by-username" ${!this._lookupResult ? "disabled" : ""}>Add</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
` : `
|
` : `
|
||||||
|
|
@ -473,6 +491,14 @@ export class RStackSpaceSettings extends HTMLElement {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search result selection
|
||||||
|
sr.querySelectorAll(".search-item").forEach(item => {
|
||||||
|
item.addEventListener("click", () => {
|
||||||
|
const idx = parseInt((item as HTMLElement).dataset.idx || "0");
|
||||||
|
if (this._searchResults[idx]) this._selectSearchResult(this._searchResults[idx]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Add by username
|
// Add by username
|
||||||
sr.getElementById("add-by-username")?.addEventListener("click", () => this._addByUsername());
|
sr.getElementById("add-by-username")?.addEventListener("click", () => this._addByUsername());
|
||||||
|
|
||||||
|
|
@ -522,27 +548,48 @@ export class RStackSpaceSettings extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _lookupUser(username: string) {
|
private async _lookupUser(username: string) {
|
||||||
if (!username || username.length < 2) return;
|
if (!username || username.length < 2) {
|
||||||
|
this._searchResults = [];
|
||||||
|
this._lookupResult = null;
|
||||||
|
this._lookupError = "";
|
||||||
|
this._render();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`https://auth.rspace.online/api/users/lookup?username=${encodeURIComponent(username)}`, {
|
const res = await fetch(`/api/users/search?q=${encodeURIComponent(username)}&limit=5`, {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
this._lookupResult = await res.json();
|
this._searchResults = await res.json();
|
||||||
this._lookupError = "";
|
this._lookupError = this._searchResults.length === 0 && username.length > 2 ? "No users found" : "";
|
||||||
|
// Auto-select if exact match
|
||||||
|
const exact = this._searchResults.find(u => u.username.toLowerCase() === username.toLowerCase());
|
||||||
|
this._lookupResult = exact ? { did: exact.id, username: exact.username, displayName: exact.displayName } : null;
|
||||||
} else {
|
} else {
|
||||||
|
this._searchResults = [];
|
||||||
this._lookupResult = null;
|
this._lookupResult = null;
|
||||||
this._lookupError = username.length > 2 ? "User not found" : "";
|
this._lookupError = username.length > 2 ? "No users found" : "";
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
this._lookupError = "Lookup failed";
|
this._lookupError = "Lookup failed";
|
||||||
|
this._searchResults = [];
|
||||||
}
|
}
|
||||||
this._render();
|
this._render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _selectSearchResult(user: { id: string; did: string; username: string; displayName: string }) {
|
||||||
|
this._lookupResult = { did: user.id, username: user.username, displayName: user.displayName };
|
||||||
|
this._searchResults = [];
|
||||||
|
this._lookupError = "";
|
||||||
|
this._render();
|
||||||
|
// Set the input value to the selected username
|
||||||
|
const input = this.shadowRoot?.getElementById("add-username") as HTMLInputElement;
|
||||||
|
if (input) input.value = user.username;
|
||||||
|
}
|
||||||
|
|
||||||
private async _addByUsername() {
|
private async _addByUsername() {
|
||||||
const sr = this.shadowRoot!;
|
const sr = this.shadowRoot!;
|
||||||
const input = sr.getElementById("add-username") as HTMLInputElement;
|
const input = sr.getElementById("add-username") as HTMLInputElement;
|
||||||
|
|
@ -914,12 +961,58 @@ const PANEL_CSS = `
|
||||||
}
|
}
|
||||||
.add-btn:hover { opacity: 0.9; }
|
.add-btn:hover { opacity: 0.9; }
|
||||||
|
|
||||||
|
.search-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: var(--rs-bg-surface);
|
||||||
|
border: 1px solid var(--rs-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-top: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 10;
|
||||||
|
box-shadow: 0 4px 16px rgba(0,0,0,0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.1s;
|
||||||
|
}
|
||||||
|
.search-item:hover {
|
||||||
|
background: var(--rs-bg-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item-name {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--rs-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item-username {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
color: var(--rs-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
.lookup-result {
|
.lookup-result {
|
||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
color: #14b8a6;
|
color: #14b8a6;
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.add-btn:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
.error-msg {
|
.error-msg {
|
||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
color: #f87171;
|
color: #f87171;
|
||||||
|
|
|
||||||
|
|
@ -3819,6 +3819,35 @@ app.get('/api/users/lookup', async (c) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// GET /api/users/search?q=<partial>&limit=5 — fuzzy username/display_name search
|
||||||
|
app.get('/api/users/search', async (c) => {
|
||||||
|
const claims = await verifyTokenFromRequest(c.req.header('Authorization'));
|
||||||
|
if (!claims) return c.json({ error: 'Authentication required' }, 401);
|
||||||
|
|
||||||
|
const q = (c.req.query('q') || '').trim();
|
||||||
|
if (q.length < 2) return c.json({ error: 'Query must be at least 2 characters' }, 400);
|
||||||
|
|
||||||
|
const limit = Math.min(Math.max(parseInt(c.req.query('limit') || '5'), 1), 10);
|
||||||
|
const pattern = `${q}%`;
|
||||||
|
|
||||||
|
const rows = await sql`
|
||||||
|
SELECT id, did, username, display_name
|
||||||
|
FROM users
|
||||||
|
WHERE username ILIKE ${pattern} OR display_name ILIKE ${pattern}
|
||||||
|
ORDER BY
|
||||||
|
CASE WHEN username ILIKE ${q} THEN 0 ELSE 1 END,
|
||||||
|
username
|
||||||
|
LIMIT ${limit}
|
||||||
|
`;
|
||||||
|
|
||||||
|
return c.json(rows.map((r: any) => ({
|
||||||
|
id: r.id,
|
||||||
|
did: r.did,
|
||||||
|
username: r.username,
|
||||||
|
displayName: r.display_name || r.username,
|
||||||
|
})));
|
||||||
|
});
|
||||||
|
|
||||||
// POST /api/users/resolve-dids — batch-resolve DIDs/userIds to usernames (public profile data)
|
// POST /api/users/resolve-dids — batch-resolve DIDs/userIds to usernames (public profile data)
|
||||||
app.post('/api/users/resolve-dids', async (c) => {
|
app.post('/api/users/resolve-dids', async (c) => {
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue