66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
/**
|
|
* Playground mode route gating.
|
|
*
|
|
* Unlike preview mode (which blocks everything except read-only API routes),
|
|
* playground mode allows most routes including the admin UI and write APIs.
|
|
* Only auth, setup, and abuse-prone routes are blocked.
|
|
*
|
|
* Pure function -- no Worker or Cloudflare dependencies.
|
|
*/
|
|
|
|
/**
|
|
* Routes blocked in playground mode.
|
|
*
|
|
* These are either security-sensitive (auth, setup, tokens, OAuth),
|
|
* abuse-prone (media upload, plugin install), or pointless in a
|
|
* temporary playground (snapshot export, user management).
|
|
*/
|
|
/**
|
|
* Auth routes that ARE allowed in playground mode.
|
|
* /auth/me is needed by the admin UI to identify the current user.
|
|
*/
|
|
const AUTH_ALLOWLIST = new Set(["/_emdash/api/auth/me"]);
|
|
|
|
const BLOCKED_PREFIXES = [
|
|
// Auth -- playground has no real auth (except /auth/me for admin UI)
|
|
"/_emdash/api/auth/",
|
|
// Setup -- playground is pre-configured
|
|
"/_emdash/api/setup/",
|
|
// OAuth provider routes
|
|
"/_emdash/api/oauth/",
|
|
// API token management
|
|
"/_emdash/api/tokens/",
|
|
// User management (can't invite/create real users)
|
|
"/_emdash/api/users/invite",
|
|
// Plugin installation (security boundary)
|
|
"/_emdash/api/plugins/install",
|
|
"/_emdash/api/plugins/marketplace",
|
|
// Media uploads (abuse vector -- no storage in playground)
|
|
"/_emdash/api/media/upload",
|
|
// Snapshot export (no point exporting a playground)
|
|
"/_emdash/api/snapshot",
|
|
];
|
|
|
|
/**
|
|
* Check whether a request should be blocked in playground mode.
|
|
*
|
|
* Playground allows most CMS functionality: content CRUD, schema editing,
|
|
* taxonomies, menus, widgets, search, settings, and the full admin UI.
|
|
* Only auth, setup, user management, media uploads, and plugin
|
|
* installation are blocked.
|
|
*/
|
|
export function isBlockedInPlayground(pathname: string): boolean {
|
|
// Check allowlist first -- specific routes that must work despite
|
|
// their parent prefix being blocked (e.g. /auth/me for admin UI)
|
|
if (AUTH_ALLOWLIST.has(pathname)) {
|
|
return false;
|
|
}
|
|
|
|
for (const prefix of BLOCKED_PREFIXES) {
|
|
if (pathname === prefix || pathname.startsWith(prefix)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|