Skip to content

Commit bdcbe36

Browse files
authored
Merge pull request #940 from WardPearce/update/3.1.7
Update/3.1.7
2 parents 357469c + 25f365a commit bdcbe36

File tree

12 files changed

+297
-153
lines changed

12 files changed

+297
-153
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ paaster.io {
9393
reverse_proxy localhost:3016
9494
}
9595

96+
# Only required for Minio
9697
s3.paaster.io {
9798
header Access-Control-Allow-Origin "https://paaster.io" {
9899
defer
@@ -116,6 +117,7 @@ server {
116117
}
117118
}
118119
120+
# Only required for minio
119121
server {
120122
listen 80;
121123
server_name s3.paaster.io;
@@ -132,6 +134,26 @@ server {
132134
}
133135
```
134136

137+
## Minio
138+
### Install minio mc cli tool
139+
[Follow guide here](https://min.io/docs/minio/linux/reference/minio-mc.html#install-mc)
140+
141+
### Add instance
142+
```
143+
mc alias set minio_instance https://s3.paaster.io my_minio_username my_minio_password
144+
```
145+
146+
### Create bucket
147+
148+
```
149+
mc mb minio_instance/paaster;mc anonymous set none minio_instance/paaster
150+
```
151+
152+
### Get credentials
153+
```
154+
mc admin accesskey create minio_instance/my_minio_username
155+
```
156+
135157
### Object storage providers
136158
- [iDrive e2](https://www.idrive.com/e2/) (no free tier anymore)
137159
- [Wasabi Hot Cloud Storage](https://wasabi.com/hot-cloud-storage/)

paaster/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "paaster",
33
"private": true,
4-
"version": "3.1.6",
4+
"version": "3.1.7",
55
"type": "module",
66
"scripts": {
77
"dev": "vite dev",

paaster/src/hooks.server.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { Handle } from '@sveltejs/kit';
2-
32
import { env } from '$env/dynamic/private';
43
import { S3Client } from '@aws-sdk/client-s3';
54
import { unsign } from 'cookie-signature';

paaster/src/lib/client/paste.ts

Lines changed: 87 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,102 @@
11
import sodium from 'libsodium-wrappers-sumo';
2-
import { get } from "svelte/store";
3-
import { localDb } from "./dexie";
4-
import { authStore } from "./stores";
2+
import { localDb } from './dexie';
3+
import { authStore } from './stores';
4+
import { get } from 'svelte/store';
5+
import { _ } from '$lib/i18n';
56

67
export async function deletePaste(pasteId: string, accessKey?: string) {
7-
if (accessKey) {
8-
await fetch(`/api/paste/${pasteId}`, {
9-
method: 'DELETE',
10-
headers: {
11-
Authorization: `Bearer ${accessKey}`
12-
}
13-
});
14-
}
15-
await localDb.pastes.delete(pasteId);
8+
if (accessKey) {
9+
await fetch(`/api/paste/${pasteId}`, {
10+
method: 'DELETE',
11+
headers: {
12+
Authorization: `Bearer ${accessKey}`
13+
}
14+
});
15+
}
16+
await localDb.pastes.delete(pasteId);
1617
}
1718

1819
export async function savePaste(
19-
pasteId: string,
20-
accessKey: string,
21-
masterKey: string,
22-
created?: Date,
23-
name?: string
20+
pasteId: string,
21+
accessKey: string,
22+
masterKey: string,
23+
created?: Date,
24+
name?: string
2425
) {
26+
const auth = get(authStore);
2527

26-
const auth = get(authStore);
28+
if (!auth) {
29+
await localDb.pastes.add({
30+
id: pasteId,
31+
accessKey: accessKey,
32+
masterKey: masterKey,
33+
created: created ?? new Date(),
34+
name: name ?? 'Unknown'
35+
});
36+
} else {
37+
await sodium.ready;
2738

28-
if (!auth) {
29-
await localDb.pastes.add({
30-
id: pasteId,
31-
accessKey: accessKey,
32-
masterKey: masterKey,
33-
created: created ?? new Date(),
34-
name: name ?? 'Unknown'
35-
});
36-
} else {
37-
await sodium.ready;
39+
const rawEncryptionKey = sodium.from_base64(auth.encryptionKey);
3840

39-
const rawEncryptionKey = sodium.from_base64(auth.encryptionKey);
41+
const encryptedPasteNonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
42+
const encryptedPaste = sodium.crypto_secretbox_easy(
43+
sodium.from_base64(masterKey),
44+
encryptedPasteNonce,
45+
rawEncryptionKey
46+
);
4047

41-
const encryptedPasteNonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
42-
const encryptedPaste = sodium.crypto_secretbox_easy(
43-
sodium.from_base64(masterKey),
44-
encryptedPasteNonce,
45-
rawEncryptionKey
46-
);
48+
const encryptedAccessNonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
49+
const encryptedAccessKey = sodium.crypto_secretbox_easy(
50+
sodium.from_base64(accessKey),
51+
encryptedAccessNonce,
52+
rawEncryptionKey
53+
);
4754

48-
const encryptedAccessNonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
49-
const encryptedAccessKey = sodium.crypto_secretbox_easy(
50-
sodium.from_base64(accessKey),
51-
encryptedAccessNonce,
52-
rawEncryptionKey
53-
);
55+
const savePastePayload = new FormData();
56+
savePastePayload.append('encryptedPasteNonce', sodium.to_base64(encryptedPasteNonce));
57+
savePastePayload.append('encryptedPasteKey', sodium.to_base64(encryptedPaste));
5458

55-
const savePastePayload = new FormData();
56-
savePastePayload.append('encryptedPasteNonce', sodium.to_base64(encryptedPasteNonce));
57-
savePastePayload.append('encryptedPasteKey', sodium.to_base64(encryptedPaste));
59+
savePastePayload.append('encryptedAccessNonce', sodium.to_base64(encryptedAccessNonce));
60+
savePastePayload.append('encryptedAccessKey', sodium.to_base64(encryptedAccessKey));
5861

59-
savePastePayload.append('encryptedAccessNonce', sodium.to_base64(encryptedAccessNonce));
60-
savePastePayload.append('encryptedAccessKey', sodium.to_base64(encryptedAccessKey));
62+
await fetch(`/api/account/paste/${pasteId}`, { method: 'POST', body: savePastePayload });
63+
}
64+
}
6165

62-
await fetch(
63-
`/api/account/paste/${pasteId}`,
64-
{ method: 'POST', body: savePastePayload }
65-
);
66-
}
67-
}
66+
export function pasteDeletionTimes() {
67+
// Must be used in func due to how states work
68+
return [
69+
{ value: -2, label: get(_)('paste_actions.expire.periods.never') },
70+
{ value: -1, label: get(_)('paste_actions.expire.periods.being_viewed') },
71+
{
72+
value: 0.08333,
73+
label: `5 ${get(_)('paste_actions.expire.periods.minutes')}`
74+
},
75+
{ value: 0.25, label: `15 ${get(_)('paste_actions.expire.periods.minutes')}` },
76+
{ value: 0.5, label: `30 ${get(_)('paste_actions.expire.periods.minutes')}` },
77+
{ value: 1, label: `1 ${get(_)('paste_actions.expire.periods.hour')}` },
78+
{ value: 2, label: `2 ${get(_)('paste_actions.expire.periods.hours')}` },
79+
{ value: 3, label: `3 ${get(_)('paste_actions.expire.periods.hours')}` },
80+
{ value: 4, label: `4 ${get(_)('paste_actions.expire.periods.hours')}` },
81+
{ value: 5, label: `5 ${get(_)('paste_actions.expire.periods.hours')}` },
82+
{ value: 6, label: `6 ${get(_)('paste_actions.expire.periods.hours')}` },
83+
{ value: 7, label: `7 ${get(_)('paste_actions.expire.periods.hours')}` },
84+
{ value: 8, label: `8 ${get(_)('paste_actions.expire.periods.hours')}` },
85+
{ value: 9, label: `9 ${get(_)('paste_actions.expire.periods.hours')}` },
86+
{ value: 10, label: `10 ${get(_)('paste_actions.expire.periods.hours')}` },
87+
{ value: 11, label: `11 ${get(_)('paste_actions.expire.periods.hours')}` },
88+
{ value: 12, label: `12 ${get(_)('paste_actions.expire.periods.hours')}` },
89+
{ value: 24, label: `1 ${get(_)('paste_actions.expire.periods.day')}` },
90+
{ value: 48, label: `2 ${get(_)('paste_actions.expire.periods.days')}` },
91+
{ value: 72, label: `3 ${get(_)('paste_actions.expire.periods.days')}` },
92+
{ value: 96, label: `4 ${get(_)('paste_actions.expire.periods.days')}` },
93+
{ value: 120, label: `5 ${get(_)('paste_actions.expire.periods.days')}` },
94+
{ value: 144, label: `6 ${get(_)('paste_actions.expire.periods.days')}` },
95+
{ value: 168, label: `1 ${get(_)('paste_actions.expire.periods.week')}` },
96+
{ value: 336, label: `2 ${get(_)('paste_actions.expire.periods.weeks')}` },
97+
{ value: 504, label: `3 ${get(_)('paste_actions.expire.periods.weeks')}` },
98+
{ value: 730, label: `1 ${get(_)('paste_actions.expire.periods.month')}` },
99+
{ value: 1461, label: `2 ${get(_)('paste_actions.expire.periods.months')}` },
100+
{ value: 2192, label: `3 ${get(_)('paste_actions.expire.periods.months')}` }
101+
];
102+
}

paaster/src/lib/consts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const CHUNK_SIZE = 1 * 1024 * 1024; // 1MB chunk size
2-
export const MAX_UPLOAD_SIZE = 10 * 1024 * 1024; // 10MB chunk size
1+
export const CHUNK_SIZE = 1 * 1024 * 1024; // 1MB chunk size
2+
export const MAX_UPLOAD_SIZE = 10 * 1024 * 1024; // 10MB chunk size
33

44
export const THEMES = ['dark', 'light', 'black', 'ghibli', 'corporate', 'luxury', 'mintlify'];

paaster/src/lib/i18n/locales/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"empty_paste": "Paste contains no characters",
44
"paste_size_too_large": "Paste size surpasses max size",
55
"themes": "Themes",
6+
"defaultPasteExpiry": "Default paste expiry",
67
"account": {
78
"login": "Login",
89
"logout": "Logout",
@@ -17,7 +18,8 @@
1718
"newPassword": "New Password",
1819
"changePassword": "Change password",
1920
"deleteAccount": "Delete account",
20-
"deleteConfirm": "Type \"Confirm account deletion\" to delete account"
21+
"deleteConfirm": "Type \"{{content}}\" to delete account",
22+
"deleteConfirmContent": "Confirm account deletion"
2123
},
2224
"shortcuts": "Shortcuts",
2325
"paste_owner": "Owner Panel",
@@ -111,4 +113,4 @@
111113
"content": "Paaster utilizes end-to-end encryption for storing and sharing pastes, meaning even the server can't view what you save here.",
112114
"source_code": "Our source code is completely open source and can be reviewed on {github}"
113115
}
114-
}
116+
}

paaster/src/routes/[pasteId]/+page.svelte

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
// @ts-expect-error qrcode types missing
2828
import QrCode from 'svelte-qrcode';
2929
import { get } from 'svelte/store';
30-
import { oklchToHex } from '$lib/client/colors.js';
30+
import { oklchToHex } from '$lib/client/colors';
31+
import { pasteDeletionTimes } from '$lib/client/paste.js';
32+
import { HSOverlay } from 'flyonui/flyonui.js';
3133
3234
let { data } = $props();
3335
@@ -48,40 +50,8 @@
4850
} = $state({});
4951
let langImport: LanguageType<string> | null = $state(null);
5052
51-
const timePeriods = [
52-
{ value: -2, label: $_('paste_actions.expire.periods.never') },
53-
{ value: -1, label: $_('paste_actions.expire.periods.being_viewed') },
54-
{
55-
value: 0.08333,
56-
label: `5 ${$_('paste_actions.expire.periods.minutes')}`
57-
},
58-
{ value: 0.25, label: `15 ${$_('paste_actions.expire.periods.minutes')}` },
59-
{ value: 0.5, label: `30 ${$_('paste_actions.expire.periods.minutes')}` },
60-
{ value: 1, label: `1 ${$_('paste_actions.expire.periods.hour')}` },
61-
{ value: 2, label: `2 ${$_('paste_actions.expire.periods.hours')}` },
62-
{ value: 3, label: `3 ${$_('paste_actions.expire.periods.hours')}` },
63-
{ value: 4, label: `4 ${$_('paste_actions.expire.periods.hours')}` },
64-
{ value: 5, label: `5 ${$_('paste_actions.expire.periods.hours')}` },
65-
{ value: 6, label: `6 ${$_('paste_actions.expire.periods.hours')}` },
66-
{ value: 7, label: `7 ${$_('paste_actions.expire.periods.hours')}` },
67-
{ value: 8, label: `8 ${$_('paste_actions.expire.periods.hours')}` },
68-
{ value: 9, label: `9 ${$_('paste_actions.expire.periods.hours')}` },
69-
{ value: 10, label: `10 ${$_('paste_actions.expire.periods.hours')}` },
70-
{ value: 11, label: `11 ${$_('paste_actions.expire.periods.hours')}` },
71-
{ value: 12, label: `12 ${$_('paste_actions.expire.periods.hours')}` },
72-
{ value: 24, label: `1 ${$_('paste_actions.expire.periods.day')}` },
73-
{ value: 48, label: `2 ${$_('paste_actions.expire.periods.days')}` },
74-
{ value: 72, label: `3 ${$_('paste_actions.expire.periods.days')}` },
75-
{ value: 96, label: `4 ${$_('paste_actions.expire.periods.days')}` },
76-
{ value: 120, label: `5 ${$_('paste_actions.expire.periods.days')}` },
77-
{ value: 144, label: `6 ${$_('paste_actions.expire.periods.days')}` },
78-
{ value: 168, label: `1 ${$_('paste_actions.expire.periods.week')}` },
79-
{ value: 336, label: `2 ${$_('paste_actions.expire.periods.weeks')}` },
80-
{ value: 504, label: `3 ${$_('paste_actions.expire.periods.weeks')}` },
81-
{ value: 730, label: `1 ${$_('paste_actions.expire.periods.month')}` },
82-
{ value: 1461, label: `2 ${$_('paste_actions.expire.periods.months')}` },
83-
{ value: 2192, label: `3 ${$_('paste_actions.expire.periods.months')}` }
84-
];
53+
let qrCodeOverlay: HSOverlay;
54+
let shortcutsOverlay: HSOverlay;
8555
8656
async function loadSupportedLangs() {
8757
const rawSupportedLangs: { [key: string]: any } = await import('svelte-highlight/languages');
@@ -386,7 +356,7 @@
386356
387357
if (data.expireAfter !== null) {
388358
// Allows us to change the period label in the future.
389-
timePeriods.forEach((time) => {
359+
pasteDeletionTimes().forEach((time) => {
390360
if (time.value === data.expireAfter) {
391361
expireTime = time;
392362
return true;
@@ -410,6 +380,12 @@
410380
downloadPaste();
411381
return false;
412382
});
383+
384+
qrCodeOverlay = new HSOverlay(document.querySelector('#qr-code') as HTMLElement);
385+
shortcutsOverlay = new HSOverlay(document.querySelector('#shortcuts') as HTMLElement);
386+
387+
qrCodeOverlay.isCloseWhenClickInside = true;
388+
shortcutsOverlay.isCloseWhenClickInside = true;
413389
});
414390
</script>
415391

@@ -514,7 +490,7 @@
514490
>{$_('paste_actions.expire.button')}</label
515491
>
516492
<Select
517-
items={timePeriods}
493+
items={pasteDeletionTimes()}
518494
clearable={false}
519495
bind:value={expireTime}
520496
on:change={setExpire}
@@ -546,8 +522,7 @@
546522
<button
547523
class="btn btn-primary"
548524
onclick={() => {
549-
// @ts-ignore
550-
new HSOverlay(document.querySelector('#qr-code')).open();
525+
qrCodeOverlay.open();
551526
}}
552527
>
553528
<QrCodeIcon />
@@ -562,8 +537,7 @@
562537
<button
563538
class="btn btn-primary"
564539
onclick={() => {
565-
// @ts-ignore
566-
new HSOverlay(document.querySelector('#shortcuts')).open();
540+
shortcutsOverlay.open();
567541
}}
568542
>
569543
<CommandIcon /> {$_('shortcuts')}</button

0 commit comments

Comments
 (0)