feat(plugin): dynamic CSP connect-src from plugin manifests
Bundle plugins run inside the base page (not a sandboxed iframe), so their
declared apiOrigins must be in the PAGE's connect-src. Previously the page
CSP was hardcoded static — plugins connecting to new APIs required a code
change + rebuild.
- GET /api/plugin/csp-origins: union of all plugins' manifest apiOrigins
- [[...slug]].tsx getServerSideProps: fetches origins via ssrApi, merges
with static fallbacks ('self' + 8001 hosts), builds CSP dynamically
- PUT /api/plugin/:pluginId accepts apiOrigins (merged into manifest JSON)
- CLI: plugin csp list / plugin csp set <id> --origins '[...]'
- @DisabledPermission on plugin GET/PUT routes (default-deny guard blocked
PAT auth); ownership still enforced via manageablePluginCreatedBy()
This commit is contained in:
@@ -271,6 +271,24 @@ export class Client {
|
||||
getPlugins() {
|
||||
return this.call<unknown[]>('GET', '/api/plugin');
|
||||
}
|
||||
getPlugin(pluginId: string) {
|
||||
return this.call<{
|
||||
id: string;
|
||||
name: string;
|
||||
positions: string[];
|
||||
description?: string;
|
||||
detailDesc?: string;
|
||||
url?: string;
|
||||
logo?: string;
|
||||
helpUrl?: string;
|
||||
}>('GET', `/api/plugin/${encodeURIComponent(pluginId)}`);
|
||||
}
|
||||
updatePlugin(pluginId: string, body: Record<string, unknown>) {
|
||||
return this.call<unknown>('PUT', `/api/plugin/${encodeURIComponent(pluginId)}`, body);
|
||||
}
|
||||
getCspOrigins() {
|
||||
return this.call<{ origins: string[] }>('GET', '/api/plugin/csp-origins');
|
||||
}
|
||||
registerPlugin(body: Record<string, unknown>) {
|
||||
return this.call<unknown>('POST', '/api/plugin', body);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user