diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index c64731170..f5875d58e 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.28.4", + "version": "2.28.5", "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 7b511b8a3..dd89a62ce 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -6,9 +6,7 @@ import { ContestNotLiveError, ValidationError, ProblemNotFoundError, ContestNotAttendedError, PermissionError, BadRequestError, } from '../error'; -import { - ProblemId, ProblemDoc, Tdoc, User, -} from '../interface'; +import { ProblemDoc, Tdoc, User } from '../interface'; import paginate from '../lib/paginate'; import { PERM, PRIV } from '../model/builtin'; import * as contest from '../model/contest'; @@ -79,6 +77,7 @@ export class ContestDetailHandler extends Handler { for (const key in pdict) { // @ts-ignore if (pdict[key].domainId !== domainId) pdict[key].docId = `${pdict[key].domainId}:${pdict[key].docId}`; + pdict[key].pid = (tdoc.pids.indexOf(pdict[key].docId) + 10).toString(36).toUpperCase(); } this.response.body = { path, tdoc, tsdoc, attended, udict, pdict, psdict, rdict, page, @@ -102,7 +101,7 @@ export class ContestDetailHandler extends Handler { } } -class ContestBoardcastHandler extends Handler { +export class ContestBoardcastHandler extends Handler { @param('tid', Types.ObjectID) async get(domainId: string, tid: ObjectID) { const tdoc = await contest.get(domainId, tid); @@ -131,7 +130,7 @@ class ContestBoardcastHandler extends Handler { } } -class ContestScoreboardHandler extends Handler { +export class ContestScoreboardHandler extends Handler { @param('tid', Types.ObjectID) @param('page', Types.PositiveInt, true) async get(domainId: string, tid: ObjectID, page = 1) { @@ -149,7 +148,7 @@ class ContestScoreboardHandler extends Handler { } } -class ContestScoreboardDownloadHandler extends Handler { +export class ContestScoreboardDownloadHandler extends Handler { @param('tid', Types.ObjectID) @param('ext', Types.Range(['csv', 'html'])) async get(domainId: string, tid: ObjectID, ext: string) { @@ -253,15 +252,17 @@ export class ContestProblemHandler extends Handler { @param('tid', Types.ObjectID) @param('pid', Types.Name) - async _prepare(domainId: string, tid: ObjectID, pid: ProblemId) { + async _prepare(domainId: string, tid: ObjectID, _pid: string) { this.tdoc = await contest.get(domainId, tid); - if (!this.tdoc.pids.includes(pid)) throw new ProblemNotFoundError(domainId, pid); + const pid = this.tdoc.pids[parseInt(_pid, 36) - 10]; + if (!pid) throw new ProblemNotFoundError(domainId, tid, _pid); [this.pdoc, this.tsdoc, this.udoc] = await Promise.all([ problem.get(domainId, pid), contest.getStatus(domainId, tid, this.user._id), user.getById(domainId, this.tdoc.owner), ]); if (!this.pdoc) throw new ProblemNotFoundError(domainId, pid); + this.pdoc.pid = _pid; // @ts-ignore if (this.pdoc.domainId !== domainId) this.pdoc.docId = `${this.pdoc.domainId}:${this.pdoc.docId}`; this.attended = this.tsdoc && this.tsdoc.attend === 1; @@ -316,7 +317,8 @@ export class ContestDetailProblemSubmitHandler extends ContestProblemHandler { @param('tid', Types.ObjectID) @param('pid', Types.Name) - async get(domainId: string, tid: ObjectID, pid: ProblemId) { + async get(domainId: string, tid: ObjectID, _pid: string) { + const pid = this.tdoc.pids[parseInt(_pid, 36) - 10]; this.response.body.rdocs = []; if (contest.canShowRecord.call(this, this.tdoc)) { this.response.body.rdocs = await record.getUserInProblemMulti( @@ -339,7 +341,8 @@ export class ContestDetailProblemSubmitHandler extends ContestProblemHandler { @param('lang', Types.Name) @param('code', Types.Content) @param('pid', Types.Name) - async post(domainId: string, tid: ObjectID, lang: string, code: string, pid: ProblemId) { + async post(domainId: string, tid: ObjectID, lang: string, code: string, _pid: string) { + const pid = this.tdoc.pids[parseInt(_pid, 36) - 10]; if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) { throw new BadRequestError('Language not allowed.'); } diff --git a/packages/hydrooj/src/handler/homework.ts b/packages/hydrooj/src/handler/homework.ts index 5b81d8b7d..743a679ce 100644 --- a/packages/hydrooj/src/handler/homework.ts +++ b/packages/hydrooj/src/handler/homework.ts @@ -8,7 +8,7 @@ import { HomeworkNotAttendedError, BadRequestError, } from '../error'; import { - PenaltyRules, Tdoc, ProblemDoc, User, ProblemId, + PenaltyRules, Tdoc, ProblemDoc, User, } from '../interface'; import { Route, Handler, Types, param, query, @@ -25,7 +25,6 @@ import record from '../model/record'; import storage from '../model/storage'; import * as document from '../model/document'; import paginate from '../lib/paginate'; -import { isExternalPid } from '../lib/validator'; const validatePenaltyRules = (input: string) => yaml.load(input); const convertPenaltyRules = validatePenaltyRules; @@ -94,6 +93,7 @@ class HomeworkDetailHandler extends Handler { for (const key in pdict) { // @ts-ignore if (pdict[key].domainId !== domainId) pdict[key].docId = `${pdict[key].domainId}:${pdict[key].docId}`; + pdict[key].pid = (tdoc.pids.indexOf(pdict[key].docId) + 10).toString(36).toUpperCase(); } this.response.template = 'homework_detail.html'; this.response.body = { @@ -127,17 +127,19 @@ class HomeworkDetailProblemHandler extends Handler { attended: boolean; @param('tid', Types.ObjectID) - @param('pid', Types.String, isExternalPid) - async _prepare(domainId: string, tid: ObjectID, pid: ProblemId) { - if (!this.tdoc.pids.includes(pid)) throw new ProblemNotFoundError(domainId, pid, tid); + @param('pid', Types.String) + async _prepare(domainId: string, tid: ObjectID, _pid: string) { + this.tdoc = await contest.get(domainId, tid, document.TYPE_HOMEWORK); + const pid = this.tdoc.pids[parseInt(_pid, 36) - 10]; + if (!pid) throw new ProblemNotFoundError(domainId, tid, _pid); const pdomainId = typeof pid === 'string' ? pid.split(':')[0] : domainId; const ppid = typeof pid === 'number' ? pid : +pid.split(':')[1]; - [this.tdoc, this.pdoc, this.tsdoc] = await Promise.all([ - contest.get(domainId, tid, document.TYPE_HOMEWORK), + [this.udoc, this.pdoc, this.tsdoc] = await Promise.all([ + user.getById(domainId, this.tdoc.owner), problem.get(pdomainId, ppid), contest.getStatus(domainId, tid, this.user._id, document.TYPE_HOMEWORK), ]); - this.udoc = await user.getById(domainId, this.tdoc.owner); + this.pdoc.pid = _pid; this.attended = this.tsdoc && this.tsdoc.attend === 1; this.response.body = { tdoc: this.tdoc, @@ -150,8 +152,7 @@ class HomeworkDetailProblemHandler extends Handler { @param('tid', Types.ObjectID) @param('pid', Types.Name) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - async get(domainId: string, tid: ObjectID, pid: ProblemId) { + async get(domainId: string, tid: ObjectID, pid: string) { if (!contest.isDone(this.tdoc)) { if (!this.attended) throw new HomeworkNotAttendedError(tid); if (contest.isNotStarted(this.tdoc)) throw new HomeworkNotLiveError(tid); @@ -195,8 +196,9 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler { } @param('tid', Types.ObjectID) - @param('pid', Types.String, isExternalPid) - async get(domainId: string, tid: ObjectID, pid: ProblemId) { + @param('pid', Types.String) + async get(domainId: string, tid: ObjectID, _pid: string) { + const pid = this.tdoc.pids[parseInt(_pid, 36) - 10]; this.response.body.rdocs = contest.canShowRecord.call(this, this.tdoc) ? await record.getUserInProblemMulti(domainId, this.user._id, pid, { type: document.TYPE_HOMEWORK, tid }) .sort('_id', -1).limit(10).toArray() @@ -212,10 +214,11 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler { } @param('tid', Types.ObjectID) - @param('pid', Types.String, isExternalPid) + @param('pid', Types.String) @param('code', Types.Content) @param('lang', Types.Name) - async post(domainId: string, tid: ObjectID, pid: ProblemId, code: string, lang: string) { + async post(domainId: string, tid: ObjectID, _pid: string, code: string, lang: string) { + const pid = this.tdoc.pids[parseInt(_pid, 36) - 10]; if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) { throw new BadRequestError('Language not allowed.'); } diff --git a/packages/hydrooj/src/loader.ts b/packages/hydrooj/src/loader.ts index 477dd8d87..d0f7cd7ec 100644 --- a/packages/hydrooj/src/loader.ts +++ b/packages/hydrooj/src/loader.ts @@ -120,6 +120,7 @@ async function reload(count = 1) { const shell = new Logger('shell'); async function executeCommand(input: string) { + input = input.trim(); // Clear the stack setImmediate(async () => { if (input === 'restart') return reload(); @@ -128,7 +129,7 @@ async function executeCommand(input: string) { } try { // eslint-disable-next-line no-eval - shell.info(await eval(input.trim())); + shell.info(await eval(input)); } catch (e) { shell.warn(e); } diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 84d93857a..a9ea3ef64 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -247,8 +247,8 @@ export class ProblemModel { const l = {}; const ddocs = await Promise.all(Object.keys(parsed).map((i) => domain.get(i))); const f = ddocs.filter((i) => !( - i.share === '*' - || (`,${(i.share || '').replace(/,/g, ',').split(',').map((q) => q.trim()).join(',')},`).includes(`,${domainId},`) + i?.share === '*' + || (`,${(i?.share || '').replace(/,/g, ',').split(',').map((q) => q.trim()).join(',')},`).includes(`,${domainId},`) )); if (f.length) { if (doThrow) throw new ProblemNotFoundError(f[0]._id, parsed[f[0]._id][0].pid); diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index f3971cd64..d6953c19b 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.11.0", + "version": "4.11.1", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/templates/components/problem.html b/packages/ui-default/templates/components/problem.html index cd2543a0d..49b1c09fc 100644 --- a/packages/ui-default/templates/components/problem.html +++ b/packages/ui-default/templates/components/problem.html @@ -2,15 +2,15 @@ {%- if not invalid %} {%- endif %} -{{ pdoc.pid if pdoc.pid else 'P'+pdoc.docId }} {{ pdoc.title }} +{{ pdoc.pid if pdoc.pid else 'P'+pdoc.docId }}. {{ pdoc.title }} {%- if not invalid %} {%- endif %} diff --git a/packages/ui-default/templates/contest_detail.html b/packages/ui-default/templates/contest_detail.html index aa28d4f3b..3146c8ff1 100644 --- a/packages/ui-default/templates/contest_detail.html +++ b/packages/ui-default/templates/contest_detail.html @@ -57,7 +57,6 @@ {% endif %} {% endif %}