core: fix builtin storage service

This commit is contained in:
undefined committed 2025-03-09 17:47:11 +08:00
1 parent 1a7b08e56e
commit 97ef575644
3 files changed
+39 -28

No files matched your search

+4 -5
View File
@@ -15,7 +15,7 @@ import {
Handler, param, post, requireSudo, Types, Handler, param, post, requireSudo, Types,
} from '../service/server'; } from '../service/server';
import { encodeRFC5987ValueChars } from '../service/storage'; import { encodeRFC5987ValueChars } from '../service/storage';
import { md5, sortFiles } from '../utils'; import { sortFiles } from '../utils';
class SwitchLanguageHandler extends Handler { class SwitchLanguageHandler extends Handler {
noCheckPermView = true; noCheckPermView = true;
@@ -108,10 +108,9 @@ export class StorageHandler extends Handler {
@param('filename', Types.Filename, true) @param('filename', Types.Filename, true)
@param('expire', Types.UnsignedInt) @param('expire', Types.UnsignedInt)
@param('secret', Types.String) @param('secret', Types.String)
async get(domainId: string, target: string, filename = '', expire: number, secret: string) { async get({ }, target: string, filename = '', expire: number, secret: string) {
const expected = md5(`${target}/${expire}/${this.ctx.config.get('file.secret')}`);
if (expire < Date.now()) throw new AccessDeniedError(); 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.body = await storage.get(target);
this.response.type = (target.endsWith('.out') || target.endsWith('.ans')) this.response.type = (target.endsWith('.out') || target.endsWith('.ans'))
? 'text/plain' ? 'text/plain'
@@ -123,7 +122,7 @@ export class StorageHandler extends Handler {
export class SwitchAccountHandler extends Handler { export class SwitchAccountHandler extends Handler {
@requireSudo @requireSudo
@param('uid', Types.Int) @param('uid', Types.Int)
async get(domainId: string, uid: number) { async get({ }, uid: number) {
this.session.sudoUid = this.user._id; this.session.sudoUid = this.user._id;
this.session.uid = uid; this.session.uid = uid;
this.back(); this.back();
+16
View File
@@ -262,6 +262,10 @@ class RemoteStorageService {
return url; return url;
} }
async isLinkValid(_: string) {
return false;
}
async signUpload(target: string, size: number) { async signUpload(target: string, size: number) {
const client = this.alternatives.user || this.client; const client = this.alternatives.user || this.client;
const { url, fields } = await createPresignedPost(client, { const { url, fields } = await createPresignedPost(client, {
@@ -365,6 +369,12 @@ class LocalStorageService {
return `/${url.toString().split('localhost/')[1]}`; 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() { async signUpload() {
throw new Error('Not implemented'); throw new Error('Not implemented');
} }
@@ -416,6 +426,12 @@ export async function apply(ctx: Context, config: ReturnType<typeof FileSetting>
ctx.set('storage', service); ctx.set('storage', service);
} }
declare module '../context' {
interface Context {
storage: RemoteStorageService | LocalStorageService;
}
}
/** @deprecated use ctx.storage instead */ /** @deprecated use ctx.storage instead */
const serviceProxy = new Proxy({}, { const serviceProxy = new Proxy({}, {
get(self, key) { get(self, key) {
+19 -23
View File
@@ -15,7 +15,7 @@ export class ConfigService extends Service {
static inject = ['db']; static inject = ['db'];
settings: Schema[] = []; settings: Schema[] = [];
systemConfig: any = {}; private systemConfig: any = {};
configSource: string = ''; configSource: string = '';
constructor(ctx: Context) { constructor(ctx: Context) {
@@ -74,30 +74,26 @@ export class ConfigService extends Service {
await this.saveConfig(newConfig); await this.saveConfig(newConfig);
} }
get(path: string) { requestConfig<T, S>(s: Schema<T, S>, dynamic = true): ReturnType<Schema<T, S>> {
let root = this.systemConfig; if (dynamic) {
for (const p of path.split('.')) { this.ctx.effect(() => {
root = root[p]; this.settings.push(s);
return () => {
this.settings = this.settings.filter((v) => v !== s);
};
});
} }
return root;
}
requestConfig<T, S>(s: Schema<T, S>): ReturnType<Schema<T, S>> {
this.ctx.effect(() => {
this.settings.push(s);
return () => {
this.settings = this.settings.filter((v) => v !== s);
};
});
let curValue = s(this.systemConfig); let curValue = s(this.systemConfig);
this.ctx.on('system/setting', () => { if (dynamic) {
try { this.ctx.on('system/setting', () => {
curValue = s(this.systemConfig); try {
} catch (e) { curValue = s(this.systemConfig);
logger.warn('Cannot read config: ', e.message); } catch (e) {
curValue = null; logger.warn('Cannot read config: ', e.message);
} curValue = null;
}); }
});
}
const that = this; const that = this;
const getAccess = (path: (string | symbol)[]) => { const getAccess = (path: (string | symbol)[]) => {
let currentValue = curValue; let currentValue = curValue;