hide tls certificate fields for backends that never use tls
This commit is contained in:
3 files changed
+60
-5
No files matched your search
@@ -13,6 +13,22 @@ export function isLocalRepo(repository: string): boolean {
|
||||
return repository.startsWith('/') || repository.startsWith('./');
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a backup destination's TLS-certificate fields (CA / client cert) are
|
||||
* meaningful for a given backend type. Only backends that can be self-hosted over
|
||||
* HTTPS with a private/self-signed CA qualify: `s3` (MinIO/Ceph) and `rest`. A
|
||||
* local path has no network, and `b2`/`azure`/`gs` are managed clouds served from
|
||||
* public CAs, so the TLS fields are noise there. When editing a destination that
|
||||
* already has a cert stored, return true regardless so its data is never hidden.
|
||||
*/
|
||||
export function backendSupportsTls(
|
||||
backendType: string,
|
||||
opts?: { isEditing?: boolean; hasStoredCert?: boolean }
|
||||
): boolean {
|
||||
if (backendType === 's3' || backendType === 'rest') return true;
|
||||
return !!(opts?.isEditing && opts?.hasStoredCert);
|
||||
}
|
||||
|
||||
/** An environment reachable over the network (hawser or direct-with-host). */
|
||||
export function isRemoteEnvironment(env?: { connectionType?: string | null; host?: string | null } | null): boolean {
|
||||
if (!env) return false;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import { FieldLabel } from '$lib/components/ui/field-label';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { focusFirstInput } from '$lib/utils';
|
||||
import { backendSupportsTls } from '$lib/shared/repo-predicates';
|
||||
|
||||
interface Destination {
|
||||
id: number;
|
||||
@@ -265,6 +266,12 @@
|
||||
const repoFields = $derived(selectedBackend.fields.filter(f => !f.envKey));
|
||||
const credentialFields = $derived(selectedBackend.fields.filter(f => f.envKey));
|
||||
|
||||
// TLS certs only apply to backends self-hostable over HTTPS with a private CA
|
||||
// (S3/REST); hidden for local/B2/Azure/Google Cloud. See backendSupportsTls.
|
||||
const showTlsSection = $derived(
|
||||
backendSupportsTls(formBackendType, { isEditing, hasStoredCert: hadCacert || hadTlsClientCert })
|
||||
);
|
||||
|
||||
// A field is mandatory unless it opts out (optional) or is a toggle (skipHostKey).
|
||||
function fieldRequired(f: FormField): boolean {
|
||||
return !f.optional && f.key !== 'skipHostKey';
|
||||
@@ -727,10 +734,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TLS certificates: for any backend that speaks TLS with a private CA (self-hosted
|
||||
rest-server, MinIO/S3, rclone-over-https). Optional; blank = use the system trust
|
||||
store, no client cert. Shown for all backend types (someone may run MinIO with a
|
||||
private CA). PEM content, uploaded or pasted. -->
|
||||
<!-- TLS certificates: only for backends that can be self-hosted over HTTPS with a
|
||||
private CA - S3 (MinIO/Ceph) and a REST server. A local path has no network, and
|
||||
B2/Azure/Google Cloud are managed clouds with public CAs, so the section is hidden
|
||||
there. Optional; blank = use the system trust store. PEM content, uploaded or pasted. -->
|
||||
{#if showTlsSection}
|
||||
<div class="border-t pt-3 mt-2 space-y-3">
|
||||
<span class="text-xs font-medium text-muted-foreground uppercase tracking-wide">TLS certificates (optional)</span>
|
||||
<p class="text-xs text-muted-foreground -mt-1">
|
||||
@@ -783,6 +791,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
<!-- Policies section -->
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* now advisory-only for the UI hint.
|
||||
*/
|
||||
import { describe, test, expect } from 'bun:test';
|
||||
import { isLocalRepo, isRemoteEnvironment, localRepoNeedsSameHost } from '../src/lib/shared/repo-predicates';
|
||||
import { isLocalRepo, isRemoteEnvironment, localRepoNeedsSameHost, backendSupportsTls } from '../src/lib/shared/repo-predicates';
|
||||
|
||||
describe('isLocalRepo', () => {
|
||||
test('absolute and relative filesystem paths are local', () => {
|
||||
@@ -55,3 +55,33 @@ describe('localRepoNeedsSameHost (#1316 advisory)', () => {
|
||||
expect(localRepoNeedsSameHost(localDest, undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('backendSupportsTls (destination TLS fields visibility)', () => {
|
||||
test('s3 and rest support TLS (self-hostable over HTTPS with a private CA)', () => {
|
||||
expect(backendSupportsTls('s3')).toBe(true);
|
||||
expect(backendSupportsTls('rest')).toBe(true);
|
||||
});
|
||||
|
||||
test('local path and managed clouds do NOT show TLS fields', () => {
|
||||
expect(backendSupportsTls('local')).toBe(false);
|
||||
expect(backendSupportsTls('b2')).toBe(false);
|
||||
expect(backendSupportsTls('azure')).toBe(false);
|
||||
expect(backendSupportsTls('gs')).toBe(false);
|
||||
});
|
||||
|
||||
test('editing a non-TLS backend that already has a cert stored still shows the section', () => {
|
||||
// A destination created before this filter that carries a CA must not have its
|
||||
// stored cert hidden on edit.
|
||||
expect(backendSupportsTls('gs', { isEditing: true, hasStoredCert: true })).toBe(true);
|
||||
expect(backendSupportsTls('local', { isEditing: true, hasStoredCert: true })).toBe(true);
|
||||
});
|
||||
|
||||
test('editing without a stored cert keeps the section hidden for non-TLS backends', () => {
|
||||
expect(backendSupportsTls('gs', { isEditing: true, hasStoredCert: false })).toBe(false);
|
||||
expect(backendSupportsTls('azure', { isEditing: true, hasStoredCert: false })).toBe(false);
|
||||
});
|
||||
|
||||
test('creating (not editing) never shows TLS for a non-TLS backend regardless of flags', () => {
|
||||
expect(backendSupportsTls('local', { isEditing: false, hasStoredCert: true })).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user