restructuring (#56)

* restructuring

* pin svelte kit version & parallel execution

* update svelte kit

* correct test result assets

* add timeout

* correct locale path

* simplify crypto

* fix for #58

* add verbosity flag

* disable flaky test
This commit is contained in:
2022-10-07 21:28:25 +02:00
committed by GitHub
parent 2d573edcac
commit cacb808117
84 changed files with 1757 additions and 1746 deletions

View File

@@ -0,0 +1,40 @@
<script lang="ts">
import { SvelteToast } from '@zerodevx/svelte-toast'
import { onMount } from 'svelte'
import { waitLocale } from 'svelte-intl-precompile'
import '../app.css'
import { init as initStores } from '$lib/stores/status'
import Footer from '$lib/views/Footer.svelte'
import Header from '$lib/views/Header.svelte'
onMount(() => {
initStores()
})
</script>
<svelte:head>
<title>cryptgeon</title>
</svelte:head>
{#await waitLocale() then _}
<main>
<Header />
<slot />
</main>
<SvelteToast />
<Footer />
{/await}
<style>
main {
padding: 1rem;
padding-bottom: 4rem;
width: 100%;
max-width: 35rem;
margin: 0 auto;
}
</style>

View File

@@ -0,0 +1,5 @@
import { getLocaleFromNavigator, init } from 'svelte-intl-precompile'
// @ts-ignore
import { registerAll } from '$locales'
registerAll()
init({ initialLocale: getLocaleFromNavigator() ?? undefined, fallbackLocale: 'en' })

View File

@@ -0,0 +1,5 @@
<script lang="ts">
import Create from '$lib/views/Create.svelte'
</script>
<Create />

View File

@@ -0,0 +1,83 @@
<script lang="ts">
import { status } from '$lib/stores/status'
import AboutParagraph from '$lib/ui/AboutParagraph.svelte'
</script>
<svelte:head>
<title>About</title>
</svelte:head>
<section class="content">
<h1>About</h1>
<p>
<i>cryptgeon</i> is a secure, open source sharing note / file service inspired by
<a href="https://privnote.com"><i>PrivNote</i></a>.
</p>
<AboutParagraph title="how does it work?">
<span>
each note has a generated <code>id (256bit)</code> and <code>key 256(bit)</code>. The
<code>id</code>
is used to save & retrieve the note. the note is then encrypted with aes in gcm mode on the client
side with the <code>key</code> and then sent to the server. data is stored in memory and never
persisted to disk. the server never sees the encryption key and cannot decrypt the contents of
the notes even if it tried to.
</span>
</AboutParagraph>
<AboutParagraph title="features">
<ul>
<li>server cannot decrypt contents due to client side encryption</li>
<li>view and time constraints</li>
<li>in memory, no persistence</li>
</ul>
</AboutParagraph>
<AboutParagraph title="tech stack">
<span>
the backend is written in rust and the frontend is svelte and typescript.
<br />
you are welcomed to check & audit the
<a href="https://github.com/cupcakearmy/cryptgeon" target="_blank" rel="noopener">
source code
</a>.
</span>
</AboutParagraph>
<AboutParagraph title="translations">
<span
>translations are managed on <a href="https://lokalise.com/" target="_blank">Lokalise</a>,
which granted an open source license to use the paid version. If you are interested in helping
translating don't hesitate to contact me!
</span>
</AboutParagraph>
<AboutParagraph title="attribution">
<span>
icons made by <a href="https://www.freepik.com" title="Freepik">freepik</a> from
<a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a>
</span>
</AboutParagraph>
<AboutParagraph title="version">
<span>
{#if $status}
<code>v{$status.version}</code>
{/if}
</span>
</AboutParagraph>
</section>
<style>
section {
width: 100%;
}
ul {
margin: 0;
padding: 0;
padding-left: 1rem;
list-style: square;
}
</style>

View File

@@ -0,0 +1,101 @@
<script lang="ts">
import { onMount } from 'svelte'
import { t } from 'svelte-intl-precompile'
import { Adapters } from '$lib/adapters'
import { get, info } from '$lib/api'
import { Keys } from '$lib/crypto'
import Button from '$lib/ui/Button.svelte'
import Loader from '$lib/ui/Loader.svelte'
import ShowNote, { type DecryptedNote } from '$lib/ui/ShowNote.svelte'
import type { PageData } from './$types'
export let data: PageData
let id = data.id
let password: string
let note: DecryptedNote | null = null
let exists = false
let loading: string | null = null
let error: string | null = null
onMount(async () => {
// Check if note exists
try {
loading = $t('common.loading')
password = window.location.hash.slice(1)
await info(id)
exists = true
} catch {
exists = false
} finally {
loading = null
}
})
/**
* Get the actual contents of the note and decrypt it.
*/
async function show() {
try {
error = null
loading = $t('common.downloading')
const data = await get(id)
loading = $t('common.decrypting')
const key = await Keys.import(password)
switch (data.meta.type) {
case 'text':
note = {
meta: { type: 'text' },
contents: await Adapters.Text.decrypt(data.contents, key),
}
break
case 'file':
note = {
meta: { type: 'file' },
contents: await Adapters.Files.decrypt(data.contents, key),
}
break
default:
error = $t('show.errors.unsupported_type')
return
}
} catch {
error = $t('show.errors.decryption_failed')
} finally {
loading = null
}
}
</script>
{#if !loading}
{#if !exists}
<p class="error-text">{$t('show.errors.not_found')}</p>
{:else if note && !error}
<ShowNote {note} />
{:else}
<form on:submit|preventDefault={show}>
<fieldset>
<p>{$t('show.explanation')}</p>
<Button data-testid="show-note-button" type="submit">{$t('show.show_note')}</Button>
{#if error}
<br />
<p class="error-text">
{error}
<br />
</p>
{/if}
</fieldset>
</form>
{/if}
{/if}
{#if loading}
<p class="loader">{loading} <Loader /></p>
{/if}
<style>
.loader {
text-align: center;
}
</style>

View File

@@ -0,0 +1,5 @@
import type { PageLoad } from './$types'
export const load: PageLoad = async ({ params }) => {
return params
}