diff --git a/config.ts b/config.ts index 4536d49..976af5e 100644 --- a/config.ts +++ b/config.ts @@ -23,6 +23,7 @@ export type ConfigType = { thumbnail_dir: string; remove_previous_gallery: boolean; img_verify_secret?: string; + img_verify_bypass_auth: boolean; }; export enum ThumbnailMethod { @@ -136,6 +137,9 @@ export class Config { get img_verify_secret() { return this._return_string("img_verify_secret"); } + get img_verify_bypass_auth() { + return this._return_bool("img_verify_bypass_auth") || false; + } to_json(): ConfigType { return { cookies: typeof this.cookies === "string", @@ -159,6 +163,7 @@ export class Config { thumbnail_dir: this.thumbnail_dir, remove_previous_gallery: this.remove_previous_gallery, img_verify_secret: this.img_verify_secret, + img_verify_bypass_auth: this.img_verify_bypass_auth, }; } } diff --git a/routes/api/_middleware.ts b/routes/api/_middleware.ts index f39ea97..c2cc142 100644 --- a/routes/api/_middleware.ts +++ b/routes/api/_middleware.ts @@ -3,8 +3,10 @@ import { get_task_manager } from "../../server.ts"; import { parse_cookies } from "../../server/cookies.ts"; import { return_error } from "../../server/utils.ts"; import type { Token } from "../../db.ts"; +import pbkdf2Hmac from "pbkdf2-hmac"; +import { encode } from "std/encoding/base64.ts"; -function handle_auth(req: Request, ctx: MiddlewareHandlerContext) { +async function handle_auth(req: Request, ctx: MiddlewareHandlerContext) { if (req.method === "OPTIONS") return true; const m = get_task_manager(); if (m.db.get_user_count() === 0) return true; @@ -16,19 +18,43 @@ function handle_auth(req: Request, ctx: MiddlewareHandlerContext) { token = cookies.get("token"); is_from_cookie = true; } - const check = () => { + const check = async () => { if (u.pathname === "/api/token" && req.method === "PUT") return true; if (u.pathname === "/api/status" && req.method === "GET") return true; + if (m.cfg.img_verify_bypass_auth) { + if ( + u.pathname.startsWith("/api/file") || + u.pathname.startsWith("/api/thumbnail") + ) { + if (ctx.params.id) { + const verify = u.searchParams.get("verify"); + if (verify) { + const tverify = encode( + new Uint8Array( + await pbkdf2Hmac( + `${ctx.params.id}`, + m.cfg.img_verify_secret, + 1000, + 64, + "SHA-512", + ), + ), + ); + if (verify === tverify) return true; + } + } + } + } return false; }; - if (!token) return check(); + if (!token) return await check(); const t = m.db.get_token(token); const now = (new Date()).getTime(); - if (!t || t.expired.getTime() < now) return check(); + if (!t || t.expired.getTime() < now) return await check(); const user = m.db.get_user(t.uid); if (!user) { m.db.delete_token(token); - return check(); + return await check(); } ctx.state.user = user; ctx.state.is_from_cookie = is_from_cookie; @@ -37,7 +63,7 @@ function handle_auth(req: Request, ctx: MiddlewareHandlerContext) { } export async function handler(req: Request, ctx: MiddlewareHandlerContext) { - if (!handle_auth(req, ctx)) { + if (!(await handle_auth(req, ctx))) { return return_error(401, "Unauthorized"); } const res = await ctx.next(); diff --git a/routes/api/file/[id].ts b/routes/api/file/[id].ts index 2baa94f..ce65a02 100644 --- a/routes/api/file/[id].ts +++ b/routes/api/file/[id].ts @@ -34,7 +34,7 @@ export const handler: Handlers = { const tverify = encode( new Uint8Array( await pbkdf2Hmac( - `id`, + `${id}`, m.cfg.img_verify_secret, 1000, 64, diff --git a/routes/api/thumbnail/[id].ts b/routes/api/thumbnail/[id].ts index b30174e..5b76fc9 100644 --- a/routes/api/thumbnail/[id].ts +++ b/routes/api/thumbnail/[id].ts @@ -92,7 +92,7 @@ export const handler: Handlers = { const tverify = encode( new Uint8Array( await pbkdf2Hmac( - `id`, + `${id}`, m.cfg.img_verify_secret, 1000, 64,