2026-07-12 19:29:46 +02:00
|
|
|
export type Credential = { kind: 'password' | 'hash' | 'invite'; value: string }
|
2026-07-09 19:48:56 +02:00
|
|
|
|
|
|
|
|
function credentialHeaders(cred: Credential): Record<string, string> {
|
2026-07-12 19:29:46 +02:00
|
|
|
if (cred.kind === 'password') return { 'X-Upload-Password': cred.value }
|
|
|
|
|
if (cred.kind === 'hash') return { 'X-Upload-Password-Hash': cred.value }
|
|
|
|
|
return { 'X-Upload-Invite': cred.value }
|
2026-07-09 19:48:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function checkCredential(cred: Credential): Promise<boolean> {
|
2026-07-09 19:14:54 +02:00
|
|
|
const res = await fetch('/api/auth/check', {
|
|
|
|
|
method: 'POST',
|
2026-07-09 19:48:56 +02:00
|
|
|
headers: credentialHeaders(cred),
|
2026-07-09 19:14:54 +02:00
|
|
|
})
|
|
|
|
|
const body = (await res.json()) as { ok: boolean }
|
|
|
|
|
return body.ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function uploadDrop(
|
|
|
|
|
ciphertext: Uint8Array,
|
2026-07-09 19:48:56 +02:00
|
|
|
cred: Credential,
|
2026-07-09 19:14:54 +02:00
|
|
|
): Promise<{ id: string; ttl: number }> {
|
|
|
|
|
const res = await fetch('/api/drops', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/octet-stream',
|
2026-07-09 19:48:56 +02:00
|
|
|
...credentialHeaders(cred),
|
2026-07-09 19:14:54 +02:00
|
|
|
},
|
|
|
|
|
body: ciphertext.slice().buffer,
|
|
|
|
|
})
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
const body = (await res.json().catch(() => ({}))) as { error?: string }
|
|
|
|
|
throw new Error(body.error ?? `upload failed: ${res.status}`)
|
|
|
|
|
}
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function downloadDrop(
|
|
|
|
|
id: string,
|
|
|
|
|
): Promise<{ ciphertext: Uint8Array; confirmToken: string }> {
|
|
|
|
|
const res = await fetch(`/api/drops/${id}`)
|
|
|
|
|
if (!res.ok) throw new Error(`download failed: ${res.status}`)
|
|
|
|
|
const confirmToken = res.headers.get('X-Confirm-Token') ?? ''
|
|
|
|
|
const ciphertext = new Uint8Array(await res.arrayBuffer())
|
|
|
|
|
return { ciphertext, confirmToken }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function confirmDrop(id: string, confirmToken: string): Promise<void> {
|
|
|
|
|
await fetch(`/api/drops/${id}/confirm`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { Authorization: `Bearer ${confirmToken}` },
|
|
|
|
|
})
|
|
|
|
|
}
|