diff options
Diffstat (limited to 'src/components/templates/signature/Summary.astro')
-rw-r--r-- | src/components/templates/signature/Summary.astro | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/src/components/templates/signature/Summary.astro b/src/components/templates/signature/Summary.astro new file mode 100644 index 0000000..3469a0f --- /dev/null +++ b/src/components/templates/signature/Summary.astro @@ -0,0 +1,279 @@ +--- +import { + createVerificationsSummary, + logLevel, + type Summary, + VerificationResult, +} from "@lib/pgp/summary"; +import type { Verification } from "@lib/pgp/verify"; +import { Level } from "@utils/index"; +import type { NonEmptyArray } from "@utils/iterator"; + +interface Props extends Verification {} + +let [errors, keys] = await createVerificationsSummary(Astro.props); +const failed = errors.filter((summary) => "reason" in summary); + +if (failed.length > 0) { + errors = failed as NonEmptyArray<Summary>; +} + +let worst; + +for (const summary of errors) { + if (worst === undefined) { + worst = summary; + } + + const { result } = summary; + const a = logLevel(worst.result); + const b = logLevel(result); + if (a[0] === b[0] && !a[1] && b[1]) { + worst = summary; + } else if (b[0] === Level.ERROR) { + worst = summary; + } else if (a[0] === Level.OK && b[0] === Level.WARN) { + worst = summary; + } +} + +let lvl: [Level, boolean] | undefined = undefined; + +let label; + +let title = ""; +let content; +const error = worst && "reason" in worst ? worst.reason : undefined; + +if (worst) { + lvl = logLevel(worst.result); + switch (lvl[0]) { + case Level.OK: { + label = "OK"; + break; + } + case Level.WARN: { + label = "Aviso"; + break; + } + case Level.ERROR: { + label = "Erro"; + break; + } + default: { + throw new Error("Unreachable"); + } + } + + switch (worst.result) { + case VerificationResult.NO_SIGNATURE: { + title = "Assinatura não encontrada"; + content = `<p> +Este blog post não foi assinado. +</p> +<p> +<strong>Não existe forma de verificar a autentacidade do autor ou a integridade do texto escrito</strong>. +</p> +`; + break; + } + case VerificationResult.MISSING_KEY: { + title = "Chave não encontrada"; + content = `<p> +Este blog post está assinado digitalmente, porém a chave pública com <code>KeyID</code> <samp>0x${worst.keyID}</samp> com que foi assinado não foi encontrada no chaveiro sendo <strong>impossível verificar a assinatura, quer dizer, não existe forma de verificar a autentacidade do autor ou a integridade do texto escrito</strong>. +</p> +<p> +Procure a chave noutro sítio da internet para conseguir fazer a verificação manualmente. +</p> +`; + break; + } + case VerificationResult.SIGNATURE_CORRUPTED: { + title = "Assinatura corrumpida"; + content = `<p> +Exite um ficheiro que supostamente é a assinatura, mas ele está corrompido ou com um formato inválido. +</p> +<p> +<strong>Não existe forma de verificar a autentacidade do autor ou a integridade do texto escrito</strong>. +</p> +`; + break; + } + case VerificationResult.SIGNATURE_COULD_NOT_BE_CHECKED: { + title = "Erro desconhecido"; + content = `<p> +A assinatura foi encontrada mas ocorreu um erro inesperado durante a verificação. +</p> +<p> +<strong>Não existe forma de verificar a autentacidade do autor ou a integridade do texto escrito</strong>. +</p> +`; + break; + } + case VerificationResult.BAD_SIGNATURE: { + title = "Assinatura inválida"; + content = `<p> +Existe uma assinatura digital porém o conteúdo da blog post não corresponde à assinatura. Talvez o texto tenha sido alterado sem ter sido criada uma nova assinatura. +</p> +<p> +Pode tentar verificar a assinatura com versões antigas do blog post, mas esta versão <strong> não pode ser verificada quanto à autentacidade do autor ou à integridade do texto escrito</strong>. +</p> +`; + break; + } + case VerificationResult.UNTRUSTED_KEY: { + title = "Assinatura válida (chave não confiada)"; + content = `<p> +A assinatura digital é criptograficamente válida, porém a chave utilizada não é suficientemente confiada pelo servidor. Mas podes ter a certeza que <strong>o dono da chave pública é a mesma pessoa que assinou este blog post</strong>. +</p> +`; + break; + } + case VerificationResult.TRUSTED_KEY: { + title = "Assinatura válida"; + content = `<p> +A assinatura digital é criptograficamente válida. <strong>O dono da chave pública é a mesma pessoa que assinou este blog post exatamente como ele está, sem alterações</strong>. +</p> +`; + break; + } + case VerificationResult.EXPIRATION_AFTER_SIGNATURE: { + break; + } + case VerificationResult.EXPIRATION_BEFORE_SIGNATURE: { + break; + } + case VerificationResult.REVOCATION_AFTER_SIGNATURE: { + break; + } + case VerificationResult.REVOCATION_BEFORE_SIGNATURE: { + break; + } + case VerificationResult.KEY_DOES_NOT_SIGN: { + break; + } + default: { + throw new Error("Unreachable"); + } + } +} +--- + +{ + lvl && + ( + <details + class:list={{ + ok: lvl[0] === Level.OK, + warn: lvl[0] === Level.WARN, + error: lvl[0] === Level.ERROR, + super: lvl[1], + }} + > + <summary>{label?.toUpperCase()}: {title.toUpperCase()}</summary> + <Fragment set:html={content} /> + {error && <pre><samp>{error}</samp></pre>} + </details> + ) +} + +<style> + pre { + overflow-x: auto; + } + details { + &.error { + --bg: #fff; + --fg: var(--color-active); + + &.super { + --bg: var(--color-active); + --fg: #fff; + } + } + + &.warn { + --bg: #fff; + --fg: #f46d43; + + &.super { + --bg: #f46d43; + --fg: #fff; + } + } + + &.ok { + --bg: #fff; + --fg: var(--color-visited); + + &.super { + --bg: var(--color-visited); + --fg: #fff; + } + } + + padding-inline: 0.5em; + padding-block: 0.5em; + + & > summary { + background-color: var(--bg); + padding-inline: 0.5em; + padding-block: calc(1em / 3); + color: var(--fg); + border-color: var(--fg); + border-width: 1px; + border-style: solid; + border-radius: calc(1em / 3); + font-weight: bolder; + + &:focus { + outline-color: var(--fg); + } + + &::marker { + color: var(--fg); + } + } + + & > :not(summary) { + padding-inline: 1em; + /* font-size: smaller; */ + } + + & > summary + * { + margin-block: 0.5em; + padding-block-start: 1em; + border-block-start: 1px solid var(--fg); + } + } + + @media (prefers-color-scheme: dark) { + details { + &.error { + --bg: #000; + + &.super { + --fg: #000; + } + } + + &.warn { + --bg: #000; + --fg: #f46d43; + + &.super { + --bg: #f46d43; + --fg: #000; + } + } + + &.ok { + --bg: #000; + + &.super { + --fg: #000; + } + } + } + } +</style> |