judge: key check report

This commit is contained in:
undefined committed 2021-09-21 23:21:22 +08:00
1 parent cf4ef57f68
commit 132ef0312c
14 files changed
+38 -25

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "@hydrooj/hydrojudge", "name": "@hydrooj/hydrojudge",
"bin": "bin/hydrojudge.js", "bin": "bin/hydrojudge.js",
"version": "2.11.2", "version": "2.11.3",
"main": "package.json", "main": "package.json",
"author": "undefined <i@undefined.moe>", "author": "undefined <i@undefined.moe>",
"repository": "https://github.com/hydro-dev/Hydro.git", "repository": "https://github.com/hydro-dev/Hydro.git",
+2 -1
View File
@@ -229,6 +229,7 @@ export default async function readCases(folder: string, cfg: Record<string, any>
result.subtasks = c.subtasks; result.subtasks = c.subtasks;
result.count = c.count; 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; return result;
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.37.2", "version": "2.37.3",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "src/loader", "main": "src/loader",
"module": "src/loader", "module": "src/loader",
+11 -7
View File
@@ -402,21 +402,25 @@ export class ProblemFilesHandler extends ProblemDetailHandler {
@post('filename', Types.Name, true) @post('filename', Types.Name, true)
@post('type', Types.Range(['testdata', 'additional_file']), true) @post('type', Types.Range(['testdata', 'additional_file']), true)
async postUploadFile(domainId: string, filename: string, type = 'testdata') { 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'); 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) filename = this.request.files.file.name || String.random(16);
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', null, 'Bad filename'); 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 (!this.user.own(this.pdoc, PERM.PERM_EDIT_PROBLEM_SELF)) this.checkPerm(PERM.PERM_EDIT_PROBLEM);
if (filename.endsWith('.zip')) { if (filename.endsWith('.zip')) {
const zip = new AdmZip(this.request.files.file.path); const zip = new AdmZip(this.request.files.file.path);
const entries = zip.getEntries(); const entries = zip.getEntries();
for (const entry of entries) { for (const entry of entries) {
// TODO check file size
if (!entry.name) continue; if (!entry.name) continue;
if (type === 'testdata') { if (type === 'testdata') {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
+2
View File
@@ -160,12 +160,14 @@ export interface ProblemConfigFile {
judge_extra_files?: string[]; judge_extra_files?: string[];
detail?: boolean; detail?: boolean;
outputs?: [string, number][]; outputs?: [string, number][];
redirect?: string;
cases?: TestCaseConfig[]; cases?: TestCaseConfig[];
subtasks?: SubtaskConfig[]; subtasks?: SubtaskConfig[];
langs?: string[]; langs?: string[];
} }
export interface ProblemConfig { export interface ProblemConfig {
redirect?: [string, string];
count: number; count: number;
memoryMax: number; memoryMax: number;
memoryMin: number; memoryMin: number;
@@ -36,6 +36,7 @@ export async function parseConfig(config: string | ProblemConfigFile = {}) {
result.timeMax = result.timeMin = 1000; result.timeMax = result.timeMin = 1000;
} }
if (cfg.langs) result.langs = cfg.langs; if (cfg.langs) result.langs = cfg.langs;
if (cfg.redirect) result.redirect = cfg.redirect.split('/', 2) as any;
if (cfg.filename && result.type === 'default') { if (cfg.filename && result.type === 'default') {
result.type = 'fileio'; result.type = 'fileio';
result.subType = cfg.filename; result.subType = cfg.filename;
+3 -3
View File
@@ -88,9 +88,9 @@ export interface Types {
} }
export const Types: Types = { export const Types: Types = {
Content: [(v) => v.toString(), isContent], Content: [(v) => v.toString().trim(), isContent],
Name: [(v) => v.toString(), isName], Name: [(v) => v.toString().trim(), isName],
Title: [(v) => v.toString(), isTitle], Title: [(v) => v.toString().trim(), isTitle],
String: [(v) => v.toString(), null], String: [(v) => v.toString(), null],
Int: [(v) => parseInt(v, 10), (v) => isSafeInteger(parseInt(v, 10))], Int: [(v) => parseInt(v, 10), (v) => isSafeInteger(parseInt(v, 10))],
UnsignedInt: [(v) => parseInt(v, 10), (v) => parseInt(v, 10) >= 0], UnsignedInt: [(v) => parseInt(v, 10), (v) => parseInt(v, 10) >= 0],
@@ -37,6 +37,7 @@ const problemConfigSchema = {
type: 'object', type: 'object',
def: problemConfigSchemaDef, def: problemConfigSchemaDef,
properties: { properties: {
redirect: { type: 'string', pattern: '[0-9a-z_-]+\\/[0-9]+' },
key: { type: 'string', pattern: '[0-9a-f]{32}' }, key: { type: 'string', pattern: '[0-9a-f]{32}' },
type: { enum: ['default', 'interactive', 'submit_answer', 'objective', 'remote_judge'] }, type: { enum: ['default', 'interactive', 'submit_answer', 'objective', 'remote_judge'] },
subType: { type: 'string' }, subType: { type: 'string' },
+1 -1
View File
@@ -5,7 +5,7 @@
"compilerOptions": { "compilerOptions": {
"jsx": "react", "jsx": "react",
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"target": "ES6", "target": "ES2020",
"baseUrl": ".", "baseUrl": ".",
"moduleResolution": "node", "moduleResolution": "node",
"paths": { "paths": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@hydrooj/ui-default", "name": "@hydrooj/ui-default",
"version": "4.22.2", "version": "4.22.3",
"author": "undefined <i@undefined.moe>", "author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "hydro.js", "main": "hydro.js",
@@ -39,16 +39,20 @@ const page = new NamedPage('home_messages', () => {
type: 'DIALOGUES_MESSAGE_PUSH', type: 'DIALOGUES_MESSAGE_PUSH',
payload: msg, payload: msg,
}); });
new VjNotification({ const notification = new VjNotification({
title: msg.udoc.uname, title: msg.udoc.uname,
avatar: msg.udoc.avatarUrl, avatar: msg.udoc.avatarUrl,
message: msg.mdoc.content, message: msg.mdoc.content,
duration: 15000, duration: 15000,
action: () => store.dispatch({ action: () => {
type: 'DIALOGUES_SWITCH_TO', store.dispatch({
payload: msg.udoc._id, type: 'DIALOGUES_SWITCH_TO',
}), payload: msg.udoc._id,
}).show(); });
notification.hide();
},
});
notification.show();
}; };
const userSelector = UserSelectAutoComplete.getOrConstruct($('.dialog__body--user-select [name="user"]')); const userSelector = UserSelectAutoComplete.getOrConstruct($('.dialog__body--user-select [name="user"]'));
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@hydrooj/vjudge", "name": "@hydrooj/vjudge",
"version": "1.3.7", "version": "1.3.8",
"description": "Submit problems to remote oj", "description": "Submit problems to remote oj",
"main": "package.json", "main": "package.json",
"repository": "https://github.com/hydro-dev/Hydro.git", "repository": "https://github.com/hydro-dev/Hydro.git",
+1 -1
View File
@@ -19,7 +19,7 @@ declare module 'hydrooj/src/interface' {
} }
} }
export interface IBasicProvider { export interface IBasicProvider {
ensureLogin(): Promise<boolean>; ensureLogin(): Promise<boolean | string>;
getProblem(id: string): Promise<{ getProblem(id: string): Promise<{
title: string; title: string;
data: Record<string, any>; data: Record<string, any>;
+2 -2
View File
@@ -71,11 +71,11 @@ class Service {
async login() { async login() {
const login = await this.api.ensureLogin(); const login = await this.api.ensureLogin();
if (login) { if (login === true) {
logger.info(`${this.account.type}/${this.account.handle}: logged in`); logger.info(`${this.account.type}/${this.account.handle}: logged in`);
return true; 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; return false;
} }