Remove caller-managed CardDAV secret references

This commit is contained in:
2026-07-21 12:12:49 +02:00
parent 8b4cf362ca
commit 5d560d4c58
3 changed files with 10 additions and 50 deletions

View File

@@ -6,10 +6,12 @@ import {
ConfirmDialog,
Dialog,
DisabledActionTooltip,
DismissibleAlert,
ExplorerTree,
fetchAuthGroups,
FormField,
LoadingFrame,
PasswordField,
StatusBadge,
ToggleSwitch,
hasScope,
@@ -141,7 +143,6 @@ type CardDavFormState = {
username: string;
password: string;
bearer_token: string;
credential_ref: string;
sync_direction: "read_only" | "import" | "export" | "two_way";
};
@@ -198,7 +199,6 @@ const EMPTY_CARDDAV_FORM: CardDavFormState = {
username: "",
password: "",
bearer_token: "",
credential_ref: "",
sync_direction: "read_only"
};
@@ -1528,8 +1528,7 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
auth_type: cardDavForm.auth_type,
username: cardDavForm.username || null,
password: cardDavForm.password || null,
bearer_token: cardDavForm.bearer_token || null,
credential_ref: cardDavForm.credential_ref || null
bearer_token: cardDavForm.bearer_token || null
};
}
@@ -1570,7 +1569,6 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
username: cardDavForm.username || null,
password: cardDavForm.password || null,
bearer_token: cardDavForm.bearer_token || null,
credential_ref: cardDavForm.credential_ref || null,
sync_direction: cardDavForm.sync_direction,
read_only: cardDavForm.sync_direction === "read_only" || cardDavForm.sync_direction === "import"
});
@@ -1927,8 +1925,8 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
return (
<div className="workspace-data-page module-entry-page address-book-page address-book-fullscreen">
{error && <div className="alert alert-error address-error">{error}</div>}
{notice && !error && <div className="alert alert-success address-error">{notice}</div>}
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
{notice && !error && <DismissibleAlert tone="success" resetKey={notice}>{notice}</DismissibleAlert>}
<LoadingFrame loading={loading} label="Loading address books..." className="address-workspace-frame">
<div className="address-book-workspace">
@@ -2273,18 +2271,15 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
<input value={cardDavForm.username} onChange={(event) => setCardDavForm((current) => ({ ...current, username: event.target.value }))} />
</FormField>
<FormField label="Password">
<input type="password" value={cardDavForm.password} onChange={(event) => setCardDavForm((current) => ({ ...current, password: event.target.value }))} />
<PasswordField value={cardDavForm.password} onValueChange={(value) => setCardDavForm((current) => ({ ...current, password: value }))} autoComplete="new-password" />
</FormField>
</div>
}
{cardDavForm.auth_type === "bearer" &&
<FormField label="Bearer token">
<input type="password" value={cardDavForm.bearer_token} onChange={(event) => setCardDavForm((current) => ({ ...current, bearer_token: event.target.value }))} />
<PasswordField value={cardDavForm.bearer_token} onValueChange={(value) => setCardDavForm((current) => ({ ...current, bearer_token: value }))} autoComplete="new-password" />
</FormField>
}
<FormField label="Credential reference">
<input value={cardDavForm.credential_ref} onChange={(event) => setCardDavForm((current) => ({ ...current, credential_ref: event.target.value }))} placeholder="env:GOVOPLAN_CARDDAV_PASSWORD" />
</FormField>
{cardDavDiscovery.length > 0 &&
<div className="address-sync-result-list">
{cardDavDiscovery.map((item) => (
@@ -2325,7 +2320,7 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
{syncInspector.source.read_only && <StatusBadge status="read-only" />}
</div>
<p className="muted">Last attempt: {formatDateTime(syncInspector.source.last_attempted_at)} · Last success: {formatDateTime(syncInspector.source.last_success_at)}</p>
{syncInspector.source.last_error && <p className="alert alert-error">{syncInspector.source.last_error}</p>}
{syncInspector.source.last_error && <DismissibleAlert tone="danger" resetKey={syncInspector.source.last_error}>{syncInspector.source.last_error}</DismissibleAlert>}
<div className="button-row compact-actions">
<ReasonedButton
type="button"
@@ -2457,7 +2452,7 @@ export default function AddressBookPage({ settings, auth, onAuthChange }: Props)
{conflictDialog.resolution && <StatusBadge status={conflictDialog.resolution} />}
</div>
{conflictDialog.metadata?.message && <p className="muted">{String(conflictDialog.metadata.message)}</p>}
{!canApplyRemoteConflict(conflictDialog) && <p className="alert alert-warning">This conflict predates stored field payloads or came from a stale write. It can be marked resolved or ignored, but the remote value cannot be applied automatically.</p>}
{!canApplyRemoteConflict(conflictDialog) && <DismissibleAlert tone="warning" dismissible={false}>This conflict predates stored field payloads or came from a stale write. It can be marked resolved or ignored, but the remote value cannot be applied automatically.</DismissibleAlert>}
</div>
<div className="address-conflict-grid">
<div className="address-conflict-grid-header">Field</div>