From 97ef5756440ce60b1e9d7eb54fc64570e979ada8 Mon Sep 17 00:00:00 2001 From: undefined Date: Sun, 9 Mar 2025 17:47:11 +0800 Subject: [PATCH] core: fix builtin storage service --- packages/hydrooj/src/handler/misc.ts | 9 +++--- packages/hydrooj/src/service/storage.ts | 16 ++++++++++ packages/hydrooj/src/settings.ts | 42 +++++++++++-------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/packages/hydrooj/src/handler/misc.ts b/packages/hydrooj/src/handler/misc.ts index 48ce4df6f..7781f3f2a 100644 --- a/packages/hydrooj/src/handler/misc.ts +++ b/packages/hydrooj/src/handler/misc.ts @@ -15,7 +15,7 @@ import { Handler, param, post, requireSudo, Types, } from '../service/server'; import { encodeRFC5987ValueChars } from '../service/storage'; -import { md5, sortFiles } from '../utils'; +import { sortFiles } from '../utils'; class SwitchLanguageHandler extends Handler { noCheckPermView = true; @@ -108,10 +108,9 @@ export class StorageHandler extends Handler { @param('filename', Types.Filename, true) @param('expire', Types.UnsignedInt) @param('secret', Types.String) - async get(domainId: string, target: string, filename = '', expire: number, secret: string) { - const expected = md5(`${target}/${expire}/${this.ctx.config.get('file.secret')}`); + async get({ }, target: string, filename = '', expire: number, secret: string) { if (expire < Date.now()) throw new AccessDeniedError(); - if (secret !== expected) throw new AccessDeniedError(); + if (!(await this.ctx.get('storage')?.isLinkValid?.(`${target}/${expire}/${secret}`))) throw new AccessDeniedError(); this.response.body = await storage.get(target); this.response.type = (target.endsWith('.out') || target.endsWith('.ans')) ? 'text/plain' @@ -123,7 +122,7 @@ export class StorageHandler extends Handler { export class SwitchAccountHandler extends Handler { @requireSudo @param('uid', Types.Int) - async get(domainId: string, uid: number) { + async get({ }, uid: number) { this.session.sudoUid = this.user._id; this.session.uid = uid; this.back(); diff --git a/packages/hydrooj/src/service/storage.ts b/packages/hydrooj/src/service/storage.ts index 9ddd2a785..10eaf70e2 100644 --- a/packages/hydrooj/src/service/storage.ts +++ b/packages/hydrooj/src/service/storage.ts @@ -262,6 +262,10 @@ class RemoteStorageService { return url; } + async isLinkValid(_: string) { + return false; + } + async signUpload(target: string, size: number) { const client = this.alternatives.user || this.client; const { url, fields } = await createPresignedPost(client, { @@ -365,6 +369,12 @@ class LocalStorageService { return `/${url.toString().split('localhost/')[1]}`; } + async isLinkValid(link: string) { + const [target, expire, secret] = link.split('/'); + const expected = md5(`${target}/${expire}/${this.config.secret}`); + return expected === secret; + } + async signUpload() { throw new Error('Not implemented'); } @@ -416,6 +426,12 @@ export async function apply(ctx: Context, config: ReturnType ctx.set('storage', service); } +declare module '../context' { + interface Context { + storage: RemoteStorageService | LocalStorageService; + } +} + /** @deprecated use ctx.storage instead */ const serviceProxy = new Proxy({}, { get(self, key) { diff --git a/packages/hydrooj/src/settings.ts b/packages/hydrooj/src/settings.ts index 4a9aae124..2f7194178 100644 --- a/packages/hydrooj/src/settings.ts +++ b/packages/hydrooj/src/settings.ts @@ -15,7 +15,7 @@ export class ConfigService extends Service { static inject = ['db']; settings: Schema[] = []; - systemConfig: any = {}; + private systemConfig: any = {}; configSource: string = ''; constructor(ctx: Context) { @@ -74,30 +74,26 @@ export class ConfigService extends Service { await this.saveConfig(newConfig); } - get(path: string) { - let root = this.systemConfig; - for (const p of path.split('.')) { - root = root[p]; + requestConfig(s: Schema, dynamic = true): ReturnType> { + if (dynamic) { + this.ctx.effect(() => { + this.settings.push(s); + return () => { + this.settings = this.settings.filter((v) => v !== s); + }; + }); } - return root; - } - - requestConfig(s: Schema): ReturnType> { - this.ctx.effect(() => { - this.settings.push(s); - return () => { - this.settings = this.settings.filter((v) => v !== s); - }; - }); let curValue = s(this.systemConfig); - this.ctx.on('system/setting', () => { - try { - curValue = s(this.systemConfig); - } catch (e) { - logger.warn('Cannot read config: ', e.message); - curValue = null; - } - }); + if (dynamic) { + this.ctx.on('system/setting', () => { + try { + curValue = s(this.systemConfig); + } catch (e) { + logger.warn('Cannot read config: ', e.message); + curValue = null; + } + }); + } const that = this; const getAccess = (path: (string | symbol)[]) => { let currentValue = curValue;