diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index e5ae9917c..e0256fa2a 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.26.12", + "version": "2.26.13", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index dea587291..d4a7103de 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -4,7 +4,7 @@ import AdmZip from 'adm-zip'; import { isSafeInteger } from 'lodash'; import { ContestNotLiveError, ValidationError, ProblemNotFoundError, - ContestNotAttendedError, PermissionError, + ContestNotAttendedError, PermissionError, BadRequestError, } from '../error'; import { ProblemDoc, Tdoc, User } from '../interface'; import paginate from '../lib/paginate'; @@ -344,6 +344,9 @@ class ContestDetailProblemSubmitHandler extends ContestProblemHandler { @param('lang', Types.Name) @param('code', Types.Content) async post(domainId: string, tid: ObjectID, lang: string, code: string) { + if (this.response.body.pdoc.config.langs && !this.response.body.pdoc.config.langs.includes('lang')) { + throw new BadRequestError('Language not allowed.'); + } await this.limitRate('add_record', 60, 10); const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, { type: document.TYPE_CONTEST, diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index 2b7b35b53..7c60e8a75 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -264,6 +264,9 @@ export class ProblemSubmitHandler extends ProblemDetailHandler { @param('lang', Types.Name) @param('code', Types.Content) async post(domainId: string, lang: string, code: string) { + if (this.response.body.pdoc.config.langs && !this.response.body.pdoc.config.langs.includes('lang')) { + throw new BadRequestError('Language not allowed.'); + } await this.limitRate('add_record', 60, 5); const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true); const [rdoc] = await Promise.all([ diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index fe7942761..fc963df5f 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -143,19 +143,20 @@ export interface SubtaskConfig { } export interface ProblemConfig { - type?: ProblemType, - score?: number, - time?: string, - memory?: string, - filename?: string, - checker_type?: string, - checker?: string, - interactor?: string, - user_extra_files?: string[], - judge_extra_files?: string[], - outputs?: [string, number][], - cases?: TestCaseConfig[], - subtasks?: SubtaskConfig[], + type?: ProblemType; + score?: number; + time?: string; + memory?: string; + filename?: string; + checker_type?: string; + checker?: string; + interactor?: string; + user_extra_files?: string[]; + judge_extra_files?: string[]; + outputs?: [string, number][]; + cases?: TestCaseConfig[]; + subtasks?: SubtaskConfig[]; + langs?: string[]; } export interface PlainContentNode { diff --git a/packages/hydrooj/src/lib/testdataConfig.ts b/packages/hydrooj/src/lib/testdataConfig.ts index efc9345c9..c6f02b7a3 100644 --- a/packages/hydrooj/src/lib/testdataConfig.ts +++ b/packages/hydrooj/src/lib/testdataConfig.ts @@ -3,11 +3,12 @@ import { load } from 'js-yaml'; import type { ProblemConfig } from '../interface'; interface ParseResult { - count: number, - memoryMax: number, - memoryMin: number, - timeMax: number, - timeMin: number, + count: number; + memoryMax: number; + memoryMin: number; + timeMax: number; + timeMin: number; + langs?: string[]; } export async function parseConfig(config: string | ProblemConfig = {}) { @@ -40,6 +41,7 @@ export async function parseConfig(config: string | ProblemConfig = {}) { if (result.timeMax < result.timeMin) { result.timeMax = result.timeMin = 1000; } + if (cfg.langs) result.langs = cfg.langs; return result; } diff --git a/packages/hydrooj/src/model/discussion.ts b/packages/hydrooj/src/model/discussion.ts index feda948dd..563a35485 100644 --- a/packages/hydrooj/src/model/discussion.ts +++ b/packages/hydrooj/src/model/discussion.ts @@ -284,7 +284,8 @@ const t = Math.exp(-0.15); async function updateSort() { const cursor = document.coll.find({ docType: document.TYPE_DISCUSSION }); - while (cursor.hasNext()) { + // eslint-disable-next-line no-await-in-loop + while (await cursor.hasNext()) { // eslint-disable-next-line no-await-in-loop const data = await cursor.next(); // eslint-disable-next-line no-await-in-loop diff --git a/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx b/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx index b7fef7b7f..4c8ee15e1 100644 --- a/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx +++ b/packages/ui-default/components/scratchpad/ScratchpadToolbarContainer.jsx @@ -78,6 +78,11 @@ export default connect(mapStateToProps, mapDispatchToProps)(class ScratchpadTool } render() { + const LANGS = {}; + for (const key in window.LANGS) { + if (UiContext.pdoc.config.langs && !UiContext.pdoc.config.langs.includes(key)) continue; + LANGS[key] = window.LANGS[key]; + } return ( this.props.setEditorLanguage(ev.target.value)} > - {_.map(window.LANGS, (val, key) => ( + {_.map(LANGS, (val, key) => ( ))} diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index aadda825e..56f04f5d3 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.8.25", + "version": "4.8.26", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/pages/problem_submit.page.js b/packages/ui-default/pages/problem_submit.page.js index 8c907d8f3..fdcb516da 100644 --- a/packages/ui-default/pages/problem_submit.page.js +++ b/packages/ui-default/pages/problem_submit.page.js @@ -15,12 +15,13 @@ const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit'], $('#codelang-main-select').on('change', function () { const options = {}; for (const key in window.LANGS) { + if (UiContext.pdocConfig.langs && !UiContext.pdocConfig.langs.includes(key)) continue; if (key.startsWith(`${this.value}.`) && key !== this.value) options[key] = window.LANGS[key].display; } if (Object.keys(options).length > 1) { setOptions($('#codelang-sub-select'), options); $('#codelang-sub-container').show(); - $('[name="codeLang"]').val($('#codelang-sub-container').val()); + $('[name="codeLang"]').val($('#codelang-sub-select').val()); } else { $('#codelang-sub-container').hide(); $('[name="codeLang"]').val(this.value); @@ -31,6 +32,7 @@ const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit'], }); const main = {}; for (const key in window.LANGS) { + if (UiContext.pdocConfig.langs && !UiContext.pdocConfig.langs.includes(key)) continue; if (!key.includes('.')) main[key] = window.LANGS[key].display; } setOptions($('#codelang-main-select'), main); @@ -38,7 +40,8 @@ const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit'], if (current.includes('.')) { const [m, s] = current.split('.'); $('#codelang-main-select').val(m); - $('#codelang-sub-select').val(s).show(); + $('#codelang-sub-select').val(s); + $('#codelang-sub-container').show(); } else $('#codelang-main-select').val(current); }); diff --git a/packages/ui-default/templates/problem_submit.html b/packages/ui-default/templates/problem_submit.html index bb58c2fcf..4a3a04171 100644 --- a/packages/ui-default/templates/problem_submit.html +++ b/packages/ui-default/templates/problem_submit.html @@ -1,5 +1,6 @@ {% extends "layout/basic.html" %} {% block content %} +{{ set(UiContext, 'pdocConfig', pdoc.config) }}
{% if not tdoc or rdocs.length %}