summaryrefslogtreecommitdiff
path: root/src/components/templates/signature/Summary.astro
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/templates/signature/Summary.astro')
-rw-r--r--src/components/templates/signature/Summary.astro279
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>