Enhance upload functionality with genre selection and validation; refactor session cookie handling
This commit is contained in:
@@ -52,9 +52,27 @@ export function unwrapOrError<T>(
|
||||
return result.data;
|
||||
}
|
||||
|
||||
export function apiErrorDetail(error: unknown): string | undefined {
|
||||
if (typeof error !== 'object' || error === null) return undefined;
|
||||
const { errors, detail, title } = error as {
|
||||
errors?: Record<string, unknown>;
|
||||
detail?: unknown;
|
||||
title?: unknown;
|
||||
};
|
||||
if (errors && typeof errors === 'object') {
|
||||
const messages = Object.values(errors)
|
||||
.flat()
|
||||
.filter((entry): entry is string => typeof entry === 'string');
|
||||
if (messages.length > 0) return messages.join(' ');
|
||||
}
|
||||
if (typeof detail === 'string' && detail !== '') return detail;
|
||||
if (typeof title === 'string' && title !== '') return title;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function unwrapOrFail(
|
||||
result: { error?: unknown },
|
||||
message: string
|
||||
): ActionFailure<{ message: string }> | undefined {
|
||||
return result.error ? fail(502, { message }) : undefined;
|
||||
): ActionFailure<{ message: string; detail?: string }> | undefined {
|
||||
return result.error ? fail(502, { message, detail: apiErrorDetail(result.error) }) : undefined;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Cookies } from '@sveltejs/kit';
|
||||
import * as client from 'openid-client';
|
||||
import { EncryptJWT, jwtDecrypt } from 'jose';
|
||||
import { dev } from '$app/environment';
|
||||
@@ -53,6 +54,44 @@ export function sessionCookieOptions(url: URL) {
|
||||
};
|
||||
}
|
||||
|
||||
const SESSION_CHUNK_SIZE = 3600;
|
||||
|
||||
function sessionChunkName(index: number): string {
|
||||
return index === 0 ? SESSION_COOKIE : `${SESSION_COOKIE}.${index}`;
|
||||
}
|
||||
|
||||
export function readSessionCookie(cookies: Cookies): string | undefined {
|
||||
const parts: string[] = [];
|
||||
for (let index = 0; ; index++) {
|
||||
const part = cookies.get(sessionChunkName(index));
|
||||
if (part === undefined) break;
|
||||
parts.push(part);
|
||||
}
|
||||
return parts.length > 0 ? parts.join('') : undefined;
|
||||
}
|
||||
|
||||
export function clearSessionCookie(cookies: Cookies, keep = 0): void {
|
||||
for (const { name } of cookies.getAll()) {
|
||||
const match =
|
||||
name === SESSION_COOKIE
|
||||
? 0
|
||||
: name.startsWith(`${SESSION_COOKIE}.`)
|
||||
? Number(name.slice(SESSION_COOKIE.length + 1))
|
||||
: -1;
|
||||
if (Number.isInteger(match) && match >= keep) cookies.delete(name, { path: '/' });
|
||||
}
|
||||
}
|
||||
|
||||
export function writeSessionCookie(cookies: Cookies, token: string, url: URL): void {
|
||||
const options = sessionCookieOptions(url);
|
||||
const count = Math.ceil(token.length / SESSION_CHUNK_SIZE);
|
||||
for (let index = 0; index < count; index++) {
|
||||
const chunk = token.slice(index * SESSION_CHUNK_SIZE, (index + 1) * SESSION_CHUNK_SIZE);
|
||||
cookies.set(sessionChunkName(index), chunk, options);
|
||||
}
|
||||
clearSessionCookie(cookies, count);
|
||||
}
|
||||
|
||||
export async function encodeSession(session: Session): Promise<string> {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
return new EncryptJWT({ ...session })
|
||||
|
||||
Reference in New Issue
Block a user