From 2734fa08b7f2388d99ee6d289795c7a67971ae38 Mon Sep 17 00:00:00 2001 From: Niklas Voss Date: Tue, 31 Mar 2026 20:32:34 +0200 Subject: [PATCH] feat: instead of exposing auth headers, offer a http proxy api for plugins --- lib/plugin-api.ts | 30 ++++++++++++++++++++---------- lib/plugin-types.ts | 3 ++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/plugin-api.ts b/lib/plugin-api.ts index 3c0411b9..f1293360 100644 --- a/lib/plugin-api.ts +++ b/lib/plugin-api.ts @@ -129,8 +129,8 @@ export interface PluginAPI { info: (message: string) => void; warning: (message: string) => void; }; - auth: { - getHeaders: () => Record; + http: { + post: (path: string, body: Record) => Promise<{ ok: boolean; status: number; data: unknown }>; }; storage: ReturnType; log: ReturnType; @@ -644,15 +644,25 @@ export function createPluginAPI(plugin: InstalledPlugin): PluginAPI { warning: (message: string) => appToast.warning(message), }, - auth: { - getHeaders: (): Record => { - requirePermission(plugin, 'auth:read'); + http: { + post: async (path: string, body: Record) => { + requirePermission(plugin, 'http:post'); + if (typeof path !== 'string' || !path.startsWith('/')) { + throw new Error('path must be an absolute path starting with /'); + } const { client } = useAuthStore.getState(); - if (!client) return {}; - return { - 'Authorization': client.getAuthHeader(), - 'X-JMAP-Username': client.getUsername(), - }; + const headers: Record = { 'Content-Type': 'application/json' }; + if (client) { + headers['Authorization'] = client.getAuthHeader(); + headers['X-JMAP-Username'] = client.getUsername(); + } + const res = await fetch(path, { + method: 'POST', + headers, + body: JSON.stringify(body), + }); + const data = await res.json().catch(() => null); + return { ok: res.ok, status: res.status, data }; }, }, diff --git a/lib/plugin-types.ts b/lib/plugin-types.ts index aebdfb90..804afeae 100644 --- a/lib/plugin-types.ts +++ b/lib/plugin-types.ts @@ -401,7 +401,8 @@ export const ALL_PERMISSIONS = [ 'vacation:read', 'vacation:write', 'settings:read', 'settings:write', 'security:read', - 'auth:observe', 'auth:read', + 'auth:observe', + 'http:post', 'ui:observe', 'ui:toolbar', 'ui:email-banner', 'ui:email-footer', 'ui:composer-toolbar', 'ui:sidebar-widget', 'ui:settings-section', 'ui:context-menu', 'ui:navigation-rail', 'ui:keyboard',