Add editing existing integrations, so an expired secret can be rotated
Manage integrations only supported add/toggle/delete — fixing an expired API token meant deleting and recreating the whole integration. - New GET /api/integrations/:id/config returns only the non-secret config fields (never the decrypted secret) so an edit form can pre-fill URL/tailnet/etc. fields. - New POST /api/integrations/:id/test merges the stored, decrypted config with any freshly-typed overrides and pings the real adapter — lets "Test connection" work during an edit without ever sending the current secret back to the browser. - New IntegrationEditForm component: secret fields render blank with a "leave blank to keep the current value" placeholder; submitting only sends the fields that were actually filled in, so a name/URL edit can't accidentally wipe a secret and a secret rotation can't touch anything else. Reuses the existing PATCH /:id route, which already merged partial config updates correctly. Verified end-to-end against the real dev server: confirmed via direct DB decryption that a non-secret-only edit leaves the stored secret byte-for-byte unchanged, and that a secret-only edit rotates it without touching other config; the test route was confirmed to make a real network call (got a genuine "API token invalid" from Tailscale's API against a fake key). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b9409d3095
commit
f5d3c25c89
5 files changed
+253
-5
No files matched your search
@@ -576,6 +576,16 @@ export const api = {
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
getConfig: (id: number) =>
|
||||
request<{
|
||||
integration: { id: number; type: IntegrationType; name: string; enabled: boolean };
|
||||
config: Record<string, string | boolean>;
|
||||
}>(`/api/integrations/${id}/config`),
|
||||
testExisting: (id: number, config: Record<string, string | boolean>) =>
|
||||
request<{ ok: boolean; latencyMs?: number; error?: string }>(`/api/integrations/${id}/test`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ config }),
|
||||
}),
|
||||
tailscale: {
|
||||
devices: (integrationId: number) =>
|
||||
request<TailscaleDevicesResponse>(`/api/integrations/${integrationId}/tailscale/devices`),
|
||||
|
||||
Reference in new issue
Block a user