fix: allow unauthenticated thread builder save/share operations

The space role middleware was blocking all POST/PUT requests from
unauthenticated users with a 403, preventing the thread builder's
save draft and share buttons from working. Added publicWrite module
flag to bypass the role check for modules with public API endpoints.
Also fixed saveDraft() to properly surface server errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-04 09:57:59 -08:00
parent 676aaa7b3a
commit 495baa5935
3 changed files with 7 additions and 1 deletions

View File

@ -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" },

View File

@ -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) {

View File

@ -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 */