add frontend error pages
This commit is contained in:
parent
e24e4e19cb
commit
d735237e8f
Binary file not shown.
@ -28,7 +28,7 @@ app.listen(process.env.PORT, () => {
|
|||||||
app.post("/note/", async (req: Request<{}, {}, EncryptedNote>, res) => {
|
app.post("/note/", async (req: Request<{}, {}, EncryptedNote>, res) => {
|
||||||
const note = req.body;
|
const note = req.body;
|
||||||
const savedNote = await prisma.encryptedNote.create({
|
const savedNote = await prisma.encryptedNote.create({
|
||||||
data: { ...note, expire_time: addDays(new Date(), 14) },
|
data: { ...note, expire_time: addDays(new Date(), 30) },
|
||||||
});
|
});
|
||||||
res.json({
|
res.json({
|
||||||
view_url: `${process.env.FRONTEND_URL}/note/${savedNote.id}`,
|
view_url: `${process.env.FRONTEND_URL}/note/${savedNote.id}`,
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { AES, enc, HmacSHA256 } from 'crypto-js';
|
import { AES, enc, HmacSHA256 } from 'crypto-js';
|
||||||
|
|
||||||
// TODO: should be same source code as used in the plugin!!
|
// TODO: should be same source code as used in the plugin!!
|
||||||
export default function decrypt(cryptData: {
|
export default async function decrypt(cryptData: {
|
||||||
ciphertext: string;
|
ciphertext: string;
|
||||||
hmac: string;
|
hmac: string;
|
||||||
key: string;
|
key: string;
|
||||||
}): string {
|
}): Promise<string> {
|
||||||
const hmac_calculated = HmacSHA256(cryptData.ciphertext, cryptData.key).toString();
|
const hmac_calculated = HmacSHA256(cryptData.ciphertext, cryptData.key).toString();
|
||||||
const is_authentic = hmac_calculated == cryptData.hmac;
|
const is_authentic = hmac_calculated == cryptData.hmac;
|
||||||
|
|
||||||
if (!is_authentic) {
|
if (!is_authentic) {
|
||||||
throw Error('Cannot decrypt ciphertext with this key.');
|
throw Error('Failed HMAC check');
|
||||||
}
|
}
|
||||||
const md = AES.decrypt(cryptData.ciphertext, cryptData.key).toString(enc.Utf8);
|
const md = AES.decrypt(cryptData.ciphertext, cryptData.key).toString(enc.Utf8);
|
||||||
return md;
|
return md;
|
||||||
|
@ -2,9 +2,16 @@
|
|||||||
import type { Load } from '@sveltejs/kit';
|
import type { Load } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const load: Load = ({ error, status }) => {
|
export const load: Load = ({ error, status }) => {
|
||||||
|
let explainText = '';
|
||||||
|
|
||||||
|
if (status == 404) {
|
||||||
|
explainText = `No note was found for this link. It may be that the note that was once connected to this link has expired.`;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
title: `${status}: ${error?.message}`
|
title: `${status}: ${error?.message}`,
|
||||||
|
explainText: explainText
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -12,8 +19,10 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let title: string;
|
export let title: string;
|
||||||
|
export let explainText: string;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="prose max-w-2xl">
|
<div class="prose max-w-2xl">
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
|
<p class="prose-xl">{explainText}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,13 +41,15 @@
|
|||||||
export let note: EncryptedNote;
|
export let note: EncryptedNote;
|
||||||
let plaintext: string;
|
let plaintext: string;
|
||||||
let timeString: string;
|
let timeString: string;
|
||||||
|
let decryptFailed = false;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (browser) {
|
if (browser) {
|
||||||
// Decrypt note
|
// Decrypt note
|
||||||
console.log(note);
|
|
||||||
const key = location.hash.slice(1);
|
const key = location.hash.slice(1);
|
||||||
plaintext = decrypt({ ...note, key });
|
decrypt({ ...note, key })
|
||||||
|
.then((value) => (plaintext = value))
|
||||||
|
.catch(() => (decryptFailed = true));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -74,19 +76,28 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="max-w-2xl mx-auto">
|
{#if plaintext}
|
||||||
<p class="mb-4 text-sm flex justify-between text-neutral-500">
|
<div class="max-w-2xl mx-auto">
|
||||||
<span class="flex gap-1.5 items-center uppercase">
|
<p class="mb-4 text-sm flex justify-between text-neutral-500">
|
||||||
<span class="h-5"><IconEncrypted /></span>
|
<span class="flex gap-1.5 items-center uppercase">
|
||||||
<span>e2e encrypted | <span>Shared {timeString} ago</span></span>
|
<span class="h-5"><IconEncrypted /></span>
|
||||||
</span>
|
<span>e2e encrypted | <span>Shared {timeString} ago</span></span>
|
||||||
<button class="flex gap-1.5 uppercase items-center">
|
</span>
|
||||||
<span>Raw Markdown</span>
|
<button class="flex gap-1.5 uppercase items-center">
|
||||||
<span class="h-6"><LogoMarkdown /></span>
|
<span>Raw Markdown</span>
|
||||||
</button>
|
<span class="h-6"><LogoMarkdown /></span>
|
||||||
</p>
|
</button>
|
||||||
|
</p>
|
||||||
{#if plaintext}
|
|
||||||
<MarkdownRenderer {plaintext} />
|
<MarkdownRenderer {plaintext} />
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
|
|
||||||
|
{#if decryptFailed}
|
||||||
|
<div class="prose max-w-2xl">
|
||||||
|
<h1>Error: Cannot decrypt file</h1>
|
||||||
|
<p class="prose-xl">This note could not be decrypted with this link.</p>
|
||||||
|
<p class="prose-xl">
|
||||||
|
If you think this is an error, please double check that you copied the entire URL.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
Loading…
Reference in New Issue
Block a user