diff --git a/packages/hydrojudge/package.json b/packages/hydrojudge/package.json index 78359b6ce..62a874efa 100644 --- a/packages/hydrojudge/package.json +++ b/packages/hydrojudge/package.json @@ -1,7 +1,7 @@ { "name": "@hydrooj/hydrojudge", "bin": "bin/hydrojudge.js", - "version": "2.11.2", + "version": "2.11.3", "main": "package.json", "author": "undefined ", "repository": "https://github.com/hydro-dev/Hydro.git", diff --git a/packages/hydrojudge/src/cases.ts b/packages/hydrojudge/src/cases.ts index f015089fc..36c7ee824 100644 --- a/packages/hydrojudge/src/cases.ts +++ b/packages/hydrojudge/src/cases.ts @@ -229,6 +229,7 @@ export default async function readCases(folder: string, cfg: Record result.subtasks = c.subtasks; result.count = c.count; } - if ((!args.key) || args.key !== result.key) isValidConfig(result); + if (args.key && args.key !== result.key) throw new FormatError('Incorrect secret key'); + if (!args.key) isValidConfig(result); return result; } diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index d527f6fcb..0224cb0e0 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.37.2", + "version": "2.37.3", "bin": "bin/hydrooj.js", "main": "src/loader", "module": "src/loader", diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index fd847aa90..1511da2b6 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -402,21 +402,25 @@ export class ProblemFilesHandler extends ProblemDetailHandler { @post('filename', Types.Name, true) @post('type', Types.Range(['testdata', 'additional_file']), true) async postUploadFile(domainId: string, filename: string, type = 'testdata') { - if ((this.pdoc.data?.length || 0) + (this.pdoc.additional_file?.length || 0) >= system.get('limit.problem_files_max')) { - throw new ForbiddenError('File limit exceeded.'); - } if (!this.request.files.file) throw new ValidationError('file'); - const size = Math.sum((this.pdoc.data || []).map((i) => i.size), (this.pdoc.additional_file || []).map((i) => i.size)); - if (size >= system.get('limit.problem_files_max_size')) { - throw new ForbiddenError('File size limit exceeded.'); - } if (!filename) filename = this.request.files.file.name || String.random(16); if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename'); + if (!this.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM)) { + if ((this.pdoc.data?.length || 0) + (this.pdoc.additional_file?.length || 0) + >= system.get('limit.problem_files_max')) { + throw new ForbiddenError('File limit exceeded.'); + } + const size = Math.sum((this.pdoc.data || []).map((i) => i.size), (this.pdoc.additional_file || []).map((i) => i.size)); + if (size >= system.get('limit.problem_files_max_size')) { + throw new ForbiddenError('File size limit exceeded.'); + } + } if (!this.user.own(this.pdoc, PERM.PERM_EDIT_PROBLEM_SELF)) this.checkPerm(PERM.PERM_EDIT_PROBLEM); if (filename.endsWith('.zip')) { const zip = new AdmZip(this.request.files.file.path); const entries = zip.getEntries(); for (const entry of entries) { + // TODO check file size if (!entry.name) continue; if (type === 'testdata') { // eslint-disable-next-line no-await-in-loop diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 3ce1c7263..be95b4f52 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -160,12 +160,14 @@ export interface ProblemConfigFile { judge_extra_files?: string[]; detail?: boolean; outputs?: [string, number][]; + redirect?: string; cases?: TestCaseConfig[]; subtasks?: SubtaskConfig[]; langs?: string[]; } export interface ProblemConfig { + redirect?: [string, string]; count: number; memoryMax: number; memoryMin: number; diff --git a/packages/hydrooj/src/lib/testdataConfig.ts b/packages/hydrooj/src/lib/testdataConfig.ts index 4c6baf40e..3607b5d06 100644 --- a/packages/hydrooj/src/lib/testdataConfig.ts +++ b/packages/hydrooj/src/lib/testdataConfig.ts @@ -36,6 +36,7 @@ export async function parseConfig(config: string | ProblemConfigFile = {}) { result.timeMax = result.timeMin = 1000; } if (cfg.langs) result.langs = cfg.langs; + if (cfg.redirect) result.redirect = cfg.redirect.split('/', 2) as any; if (cfg.filename && result.type === 'default') { result.type = 'fileio'; result.subType = cfg.filename; diff --git a/packages/hydrooj/src/service/server.ts b/packages/hydrooj/src/service/server.ts index ac19b7119..1c945be6e 100644 --- a/packages/hydrooj/src/service/server.ts +++ b/packages/hydrooj/src/service/server.ts @@ -88,9 +88,9 @@ export interface Types { } export const Types: Types = { - Content: [(v) => v.toString(), isContent], - Name: [(v) => v.toString(), isName], - Title: [(v) => v.toString(), isTitle], + Content: [(v) => v.toString().trim(), isContent], + Name: [(v) => v.toString().trim(), isName], + Title: [(v) => v.toString().trim(), isTitle], String: [(v) => v.toString(), null], Int: [(v) => parseInt(v, 10), (v) => isSafeInteger(parseInt(v, 10))], UnsignedInt: [(v) => parseInt(v, 10), (v) => parseInt(v, 10) >= 0], diff --git a/packages/ui-default/components/monaco/languages/yaml.ts b/packages/ui-default/components/monaco/languages/yaml.ts index 65d2ec6bc..28bc3605a 100644 --- a/packages/ui-default/components/monaco/languages/yaml.ts +++ b/packages/ui-default/components/monaco/languages/yaml.ts @@ -37,6 +37,7 @@ const problemConfigSchema = { type: 'object', def: problemConfigSchemaDef, properties: { + redirect: { type: 'string', pattern: '[0-9a-z_-]+\\/[0-9]+' }, key: { type: 'string', pattern: '[0-9a-f]{32}' }, type: { enum: ['default', 'interactive', 'submit_answer', 'objective', 'remote_judge'] }, subType: { type: 'string' }, diff --git a/packages/ui-default/jsconfig.json b/packages/ui-default/jsconfig.json index b9472621d..7c306e165 100644 --- a/packages/ui-default/jsconfig.json +++ b/packages/ui-default/jsconfig.json @@ -5,7 +5,7 @@ "compilerOptions": { "jsx": "react", "allowSyntheticDefaultImports": true, - "target": "ES6", + "target": "ES2020", "baseUrl": ".", "moduleResolution": "node", "paths": { diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 15ce90a27..b2238fdfa 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.22.2", + "version": "4.22.3", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/pages/home_messages.page.jsx b/packages/ui-default/pages/home_messages.page.jsx index 8f776276d..f5a4f565b 100644 --- a/packages/ui-default/pages/home_messages.page.jsx +++ b/packages/ui-default/pages/home_messages.page.jsx @@ -39,16 +39,20 @@ const page = new NamedPage('home_messages', () => { type: 'DIALOGUES_MESSAGE_PUSH', payload: msg, }); - new VjNotification({ + const notification = new VjNotification({ title: msg.udoc.uname, avatar: msg.udoc.avatarUrl, message: msg.mdoc.content, duration: 15000, - action: () => store.dispatch({ - type: 'DIALOGUES_SWITCH_TO', - payload: msg.udoc._id, - }), - }).show(); + action: () => { + store.dispatch({ + type: 'DIALOGUES_SWITCH_TO', + payload: msg.udoc._id, + }); + notification.hide(); + }, + }); + notification.show(); }; const userSelector = UserSelectAutoComplete.getOrConstruct($('.dialog__body--user-select [name="user"]')); diff --git a/packages/vjudge/package.json b/packages/vjudge/package.json index af3fc31bf..84fdb03a5 100644 --- a/packages/vjudge/package.json +++ b/packages/vjudge/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/vjudge", - "version": "1.3.7", + "version": "1.3.8", "description": "Submit problems to remote oj", "main": "package.json", "repository": "https://github.com/hydro-dev/Hydro.git", diff --git a/packages/vjudge/src/interface.ts b/packages/vjudge/src/interface.ts index 75e4fca1a..0573f62f1 100644 --- a/packages/vjudge/src/interface.ts +++ b/packages/vjudge/src/interface.ts @@ -19,7 +19,7 @@ declare module 'hydrooj/src/interface' { } } export interface IBasicProvider { - ensureLogin(): Promise; + ensureLogin(): Promise; getProblem(id: string): Promise<{ title: string; data: Record; diff --git a/packages/vjudge/src/model.ts b/packages/vjudge/src/model.ts index 29365390e..2a7bc967f 100644 --- a/packages/vjudge/src/model.ts +++ b/packages/vjudge/src/model.ts @@ -71,11 +71,11 @@ class Service { async login() { const login = await this.api.ensureLogin(); - if (login) { + if (login === true) { logger.info(`${this.account.type}/${this.account.handle}: logged in`); return true; } - logger.warn(`${this.account.type}/${this.account.handle}: login fail`); + logger.warn(`${this.account.type}/${this.account.handle}: login fail`, login || ''); return false; }