diff --git a/src/stores/certs.ts b/src/stores/certs.ts new file mode 100644 index 0000000..ea3f8ee --- /dev/null +++ b/src/stores/certs.ts @@ -0,0 +1,30 @@ +import {writable} from "svelte/store"; + +export interface Cert { + id: number; + auto_renew: boolean; + active: boolean; + renewing: boolean; + renew_failed: boolean; + not_after: string; + updated_at: string; + domains: string[]; +} + +export function siteEqual(a: Cert | null, b: Cert | null) { + if (a == null || b == null) return false; + a.domains.sort(); + b.domains.sort(); + return ( + a.id == b.id && + a.auto_renew == b.auto_renew && + a.active == b.active && + a.renewing == b.renewing && + a.renew_failed == b.renew_failed && + a.not_after == b.not_after && + a.updated_at == b.updated_at && + JSON.stringify(a.domains) == JSON.stringify(b.domains) + ); +} + +export const certsTable = writable<{[key: string]: Cert}>({}); diff --git a/src/views/CertificatesView.svelte b/src/views/CertificatesView.svelte index 6c5f777..594107a 100644 --- a/src/views/CertificatesView.svelte +++ b/src/views/CertificatesView.svelte @@ -1 +1,122 @@ -
Warning: This is currently still under development
+ + +
+
Warning: This is currently still under development
+ +
+ {#await promiseForTable} +
+
Loading...
+
+ {:then} + + + + + + + + + + + + + + {#each tableKeys as key (key)} + {@const cert = $certsTable[key]} + + + + + + + + + + {/each} + +
IDAuto RenewActiveRenewingRenew FailedNot AfterDomains
{cert.id}{cert.auto_renew}{cert.active}{cert.renewing}{cert.renew_failed} +
{cert.not_after}
+
{Math.round((new Date(cert.not_after).getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24))} days until expiry
+
+ {#each cert.domains as domain} +
{domain}
+ {/each} +
+ {:catch err} +
+
Administrator... I hardly know her?
+
{err}
+
+ {/await} +
+
+ + diff --git a/test-server/main.go b/test-server/main.go index 5481fae..7815ef1 100644 --- a/test-server/main.go +++ b/test-server/main.go @@ -150,6 +150,56 @@ func apiServer(verify mjwt.Verifier) { } json.NewEncoder(rw).Encode(m) })) + r.Handle("/v1/orchid/owned", hasPerm(verify, "orchid:cert", func(rw http.ResponseWriter, req *http.Request) { + m := make(map[int]any, 41) + for i := 0; i < 20; i++ { + u := uuid.NewString() + m[i] = map[string]any{ + "id": i + 1, + "auto_renew": true, + "active": true, + "renewing": false, + "renew_failed": false, + "not_after": "2024-02-06T11:52:05Z", + "updated_at": "2023-11-08T07:32:08Z", + "domains": []string{ + u + ".example.com", + "*." + u + ".example.com", + }, + } + } + for i := 0; i < 20; i++ { + u := uuid.NewString() + m[i+20] = map[string]any{ + "id": i + 21, + "auto_renew": false, + "active": false, + "renewing": false, + "renew_failed": false, + "not_after": "2024-02-06T11:52:05Z", + "updated_at": "2023-11-08T07:32:08Z", + "domains": []string{ + u + ".example.org", + "*." + u + ".example.org", + }, + } + } + u := uuid.NewString() + m[40] = map[string]any{ + "id": 41, + "auto_renew": false, + "active": false, + "renewing": false, + "renew_failed": true, + "not_after": "2024-02-06T11:52:05Z", + "updated_at": "2023-11-08T07:32:08Z", + "domains": []string{ + u + ".example.org", + "*." + u + ".example.org", + }, + } + json.NewEncoder(rw).Encode(m) + })) r.Handle("/v1/sites", hasPerm(verify, "sites:manage", func(rw http.ResponseWriter, req *http.Request) { if req.Method == http.MethodPost { defer req.Body.Close()