diff --git a/modules/rsocials/mod.ts b/modules/rsocials/mod.ts index 565eac4..4b66f63 100644 --- a/modules/rsocials/mod.ts +++ b/modules/rsocials/mod.ts @@ -917,6 +917,7 @@ function renderThreadBuilderPage(space: string, threadData?: ThreadData | null): }); } + if (!res.ok) throw new Error('Save failed: ' + res.status); const data = await res.json(); if (data.id) { currentThreadId = data.id; @@ -1786,6 +1787,7 @@ export const socialsModule: RSpaceModule = { description: "Federated social feed aggregator for communities", scoping: { defaultScope: 'global', userConfigurable: true }, routes, + publicWrite: true, standaloneDomain: "rsocials.online", landingPage: renderLanding, externalApp: { url: "https://social.jeffemmett.com", name: "Postiz" }, diff --git a/server/index.ts b/server/index.ts index 5c6b7c1..0195e6c 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1248,7 +1248,7 @@ for (const mod of getAllModules()) { // Resolve caller's role for write-method blocking const method = c.req.method; - if (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE") { + if (!mod.publicWrite && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) { const token = extractToken(c.req.raw.headers); let claims: EncryptIDClaims | null = null; if (token) { diff --git a/shared/module.ts b/shared/module.ts index 13b6214..2128f85 100644 --- a/shared/module.ts +++ b/shared/module.ts @@ -108,6 +108,10 @@ export interface RSpaceModule { /** Seed template/demo data for a space. Called by /template route. */ seedTemplate?: (space: string) => void; + + /** If true, write operations (POST/PUT/PATCH/DELETE) skip the space role check. + * Use for modules whose API endpoints are publicly accessible (e.g. thread builder). */ + publicWrite?: boolean; } /** Registry of all loaded modules */