Use encrypted uploads
This commit is contained in:
parent
c4a1ad2e33
commit
55efb3fdfd
4 changed files with 52 additions and 18 deletions
BIN
pnpm-lock.yaml
BIN
pnpm-lock.yaml
Binary file not shown.
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
export const focus = () => editor.then(ed => ed.chain().focus().run())
|
export const focus = () => editor.then(ed => ed.chain().focus().run())
|
||||||
|
|
||||||
|
const uploadFiles = () => editor.then(ed => ed.chain().selectFiles().run())
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
if ($uploading) return
|
if ($uploading) return
|
||||||
|
|
||||||
|
|
@ -40,11 +42,21 @@
|
||||||
submit,
|
submit,
|
||||||
uploading,
|
uploading,
|
||||||
aggressive: true,
|
aggressive: true,
|
||||||
disableFileUpload: true,
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form class="relative z-feature flex gap-2 p-2" onsubmit={preventDefault(submit)}>
|
<form class="relative z-feature flex gap-2 p-2" onsubmit={preventDefault(submit)}>
|
||||||
|
<Button
|
||||||
|
data-tip="Add an image"
|
||||||
|
class="center tooltip tooltip-right h-10 w-10 min-w-10 rounded-box bg-base-300 transition-colors hover:bg-base-200"
|
||||||
|
disabled={$uploading}
|
||||||
|
onclick={uploadFiles}>
|
||||||
|
{#if $uploading}
|
||||||
|
<span class="loading loading-spinner loading-xs"></span>
|
||||||
|
{:else}
|
||||||
|
<Icon icon="gallery-send" />
|
||||||
|
{/if}
|
||||||
|
</Button>
|
||||||
<div class="chat-editor flex-grow overflow-hidden">
|
<div class="chat-editor flex-grow overflow-hidden">
|
||||||
<EditorContent {editor} />
|
<EditorContent {editor} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,39 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import {onMount, onDestroy} from "svelte"
|
||||||
import {getTags, getTagValue, tagsFromIMeta} from "@welshman/util"
|
import {getTags, getTagValue, tagsFromIMeta} from "@welshman/util"
|
||||||
|
import {decryptFile} from "@welshman/editor"
|
||||||
import {imgproxy} from "@app/state"
|
import {imgproxy} from "@app/state"
|
||||||
|
|
||||||
const {value, event, ...props} = $props()
|
const {value, event, ...props} = $props()
|
||||||
|
|
||||||
const url = value.url.toString()
|
const url = value.url.toString()
|
||||||
const meta = getTags("imeta", event.tags)
|
const meta =
|
||||||
.map(tagsFromIMeta)
|
getTags("imeta", event.tags)
|
||||||
.find(meta => getTagValue("url", meta) === url)
|
.map(tagsFromIMeta)
|
||||||
const src = imgproxy(url)
|
.find(meta => getTagValue("url", meta) === url) || []
|
||||||
|
|
||||||
|
const key = getTagValue("decryption-key", meta)
|
||||||
|
const nonce = getTagValue("decryption-nonce", meta)
|
||||||
|
const encryptionAlgorithm = getTagValue("encryption-algorithm", meta)
|
||||||
|
|
||||||
|
let src = $state(imgproxy(url))
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
if (encryptionAlgorithm === "aes-gcm" && key && nonce) {
|
||||||
|
const response = await fetch(url)
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const ciphertext = new Uint8Array(await response.arrayBuffer())
|
||||||
|
const decryptedData = decryptFile({ciphertext, key, nonce, encryptionAlgorithm})
|
||||||
|
|
||||||
|
src = URL.createObjectURL(new Blob([new Uint8Array(decryptedData)]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
URL.revokeObjectURL(src)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<img alt="" {src} {...props} />
|
<img alt="" {src} {...props} />
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ export const makeEditor = async ({
|
||||||
submit,
|
submit,
|
||||||
uploading,
|
uploading,
|
||||||
wordCount,
|
wordCount,
|
||||||
disableFileUpload,
|
|
||||||
}: {
|
}: {
|
||||||
aggressive?: boolean
|
aggressive?: boolean
|
||||||
autofocus?: boolean
|
autofocus?: boolean
|
||||||
|
|
@ -46,7 +45,6 @@ export const makeEditor = async ({
|
||||||
submit: () => void
|
submit: () => void
|
||||||
uploading?: Writable<boolean>
|
uploading?: Writable<boolean>
|
||||||
wordCount?: Writable<number>
|
wordCount?: Writable<number>
|
||||||
disableFileUpload?: boolean
|
|
||||||
}) => {
|
}) => {
|
||||||
return new Editor({
|
return new Editor({
|
||||||
content,
|
content,
|
||||||
|
|
@ -69,18 +67,17 @@ export const makeEditor = async ({
|
||||||
aggressive,
|
aggressive,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fileUpload: disableFileUpload
|
fileUpload: {
|
||||||
? false
|
config: {
|
||||||
: {
|
encryptionAlgorithm: "aes-gcm",
|
||||||
config: {
|
onDrop() {
|
||||||
onDrop() {
|
uploading?.set(true)
|
||||||
uploading?.set(true)
|
|
||||||
},
|
|
||||||
onComplete() {
|
|
||||||
uploading?.set(false)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
onComplete() {
|
||||||
|
uploading?.set(false)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
nprofile: {
|
nprofile: {
|
||||||
extend: {
|
extend: {
|
||||||
addNodeView: () => makeMentionNodeView(url),
|
addNodeView: () => makeMentionNodeView(url),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue