core: database structure update

This commit is contained in:
undefined committed 2021-09-23 18:15:17 +08:00
1 parent dca8e28361
commit 4daf8bac80
24 files changed
+182 -263

No files matched your search

+6 -19
View File
@@ -15,7 +15,6 @@ import {
import paginate from '../lib/paginate';
import { PERM, PRIV } from '../model/builtin';
import * as contest from '../model/contest';
import * as document from '../model/document';
import domain from '../model/domain';
import message from '../model/message';
import problem from '../model/problem';
@@ -32,19 +31,15 @@ export class ContestListHandler extends Handler {
@param('rule', Types.Range(contest.RULES), true)
@param('page', Types.PositiveInt, true)
async get(domainId: string, rule = '', page = 1) {
const cursor = contest.getMulti(domainId, rule ? { rule } : undefined);
const cursor = contest.getMulti(domainId, rule ? { rule } : { rule: { $ne: 'homework' } });
const qs = rule ? `rule=${rule}` : '';
const [tdocs, tpcount] = await paginate(cursor, page, system.get('pagination.contest'));
const tids = [];
for (const tdoc of tdocs) tids.push(tdoc.docId);
const tsdict = await contest.getListStatus(domainId, this.user._id, tids);
const path = [
['Hydro', 'homepage'],
['contest_main', null],
];
this.response.template = 'contest_main.html';
this.response.body = {
page, tpcount, qs, rule, tdocs, tsdict, path,
page, tpcount, qs, rule, tdocs, tsdict,
};
}
}
@@ -68,17 +63,12 @@ export class ContestDetailHandler extends Handler {
if (contest.canShowSelfRecord.call(this, tdoc)) {
const q = [];
for (const i in psdict) q.push(psdict[i].rid);
rdict = await record.getList(domainId, q, true);
rdict = await record.getList(domainId, q);
} else {
for (const i in psdict) rdict[psdict[i].rid] = { _id: psdict[i].rid };
}
} else attended = false;
const udict = await user.getList(domainId, [tdoc.owner]);
const path = [
['Hydro', 'homepage'],
['contest_main', 'contest_main'],
[tdoc.title, null, null, true],
];
const index = tdoc.pids.map((i) => i.toString());
for (const key in pdict) {
pdict[key].tag.length = 0;
@@ -86,7 +76,7 @@ export class ContestDetailHandler extends Handler {
if (i !== '9') pdict[key].pid = i;
}
this.response.body = {
path, tdoc, tsdoc, attended, udict, pdict, psdict, rdict, page,
tdoc, tsdoc, attended, udict, pdict, psdict, rdict, page,
};
}
@@ -258,7 +248,7 @@ export class ContestEditHandler extends Handler {
}
export class ContestProblemHandler extends Handler {
tdoc: Tdoc<30 | 60>;
tdoc: Tdoc<30>;
pdoc: ProblemDoc;
tsdoc: any;
udoc: User;
@@ -391,10 +381,7 @@ export class ContestDetailProblemSubmitHandler extends ContestProblemHandler {
throw new BadRequestError('Language not allowed.');
}
await this.limitRate('add_record', 60, system.get('limit.submission'));
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : {
type: document.TYPE_CONTEST,
tid,
});
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : tid);
const rdoc = await record.get(domainId, rid);
if (!rdoc) throw new RecordNotFoundError(domainId, rid);
if (!pretest) {
+1 -1
View File
@@ -19,7 +19,7 @@ export const typeMapper = {
contest: document.TYPE_CONTEST,
node: document.TYPE_DISCUSSION_NODE,
training: document.TYPE_TRAINING,
homework: document.TYPE_HOMEWORK,
homework: document.TYPE_CONTEST,
};
class DiscussionHandler extends Handler {
+1 -3
View File
@@ -8,9 +8,7 @@ import {
import type { DomainDoc } from '../interface';
import avatar from '../lib/avatar';
import paginate from '../lib/paginate';
import {
PERM, PERMS_BY_FAMILY, PRIV,
} from '../model/builtin';
import { PERM, PERMS_BY_FAMILY, PRIV } from '../model/builtin';
import * as discussion from '../model/discussion';
import domain from '../model/domain';
import { DOMAIN_SETTINGS, DOMAIN_SETTINGS_BY_KEY } from '../model/setting';
+3 -5
View File
@@ -14,7 +14,6 @@ import BlackListModel from '../model/blacklist';
import { PERM, PRIV } from '../model/builtin';
import * as contest from '../model/contest';
import * as discussion from '../model/discussion';
import * as document from '../model/document';
import domain from '../model/domain';
import message from '../model/message';
import ProblemModel from '../model/problem';
@@ -39,11 +38,10 @@ class HomeHandler extends Handler {
async getHomework(domainId: string, limit = 5) {
if (this.user.hasPerm(PERM.PERM_VIEW_HOMEWORK)) {
const tdocs = await contest.getMulti(domainId, {}, document.TYPE_HOMEWORK)
const tdocs = await contest.getMulti(domainId, { rule: 'homework' })
.limit(limit).toArray();
const tsdict = await contest.getListStatus(
domainId, this.user._id,
tdocs.map((tdoc) => tdoc.docId), document.TYPE_HOMEWORK,
domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId),
);
return ['homework', tdocs, tsdict];
}
@@ -52,7 +50,7 @@ class HomeHandler extends Handler {
async getContest(domainId: string, limit = 10) {
if (this.user.hasPerm(PERM.PERM_VIEW_CONTEST)) {
const tdocs = await contest.getMulti(domainId)
const tdocs = await contest.getMulti(domainId, { rule: { $ne: 'homework' } })
.limit(limit).toArray();
const tsdict = await contest.getListStatus(
domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId),
+38 -72
View File
@@ -6,17 +6,16 @@ import moment from 'moment-timezone';
import { ObjectID } from 'mongodb';
import { Time } from '@hydrooj/utils/lib/utils';
import {
BadRequestError, HomeworkNotAttendedError, HomeworkNotLiveError,
ProblemNotFoundError, ValidationError,
BadRequestError, ContestNotFoundError, HomeworkNotAttendedError,
HomeworkNotLiveError, ProblemNotFoundError, ValidationError,
} from '../error';
import {
DomainDoc, PenaltyRules, ProblemDoc, Tdoc, User,
DomainDoc, PenaltyRules, ProblemDoc, ProblemId, Tdoc, User,
} from '../interface';
import paginate from '../lib/paginate';
import { PERM, PRIV, STATUS } from '../model/builtin';
import * as contest from '../model/contest';
import * as discussion from '../model/discussion';
import * as document from '../model/document';
import domain from '../model/domain';
import problem from '../model/problem';
import record from '../model/record';
@@ -33,7 +32,7 @@ const convertPenaltyRules = validatePenaltyRules;
class HomeworkMainHandler extends Handler {
async get({ domainId }) {
const tdocs = await contest.getMulti(domainId, {}, document.TYPE_HOMEWORK).toArray();
const tdocs = await contest.getMulti(domainId, { rule: 'homework' }).toArray();
const calendar = [];
for (const tdoc of tdocs) {
const cal = { ...tdoc, url: this.url('homework_detail', { tid: tdoc.docId }) };
@@ -43,11 +42,7 @@ class HomeworkMainHandler extends Handler {
} else cal.endAt = tdoc.penaltySince;
calendar.push(cal);
}
const path = [
['Hydro', 'homepage'],
['homework_main', null],
];
this.response.body = { tdocs, calendar, path };
this.response.body = { tdocs, calendar };
this.response.template = 'homework_main.html';
}
}
@@ -56,9 +51,10 @@ class HomeworkDetailHandler extends Handler {
@param('tid', Types.ObjectID)
@param('page', Types.PositiveInt, true)
async get(domainId: string, tid: ObjectID, page = 1) {
const tdoc = await contest.get(domainId, tid, document.TYPE_HOMEWORK);
const tdoc = await contest.get(domainId, tid);
if (tdoc.rule !== 'homework') throw new ContestNotFoundError(domainId, tid);
const [tsdoc, pdict] = await Promise.all([
contest.getStatus(domainId, tdoc.docId, this.user._id, document.TYPE_HOMEWORK),
contest.getStatus(domainId, tdoc.docId, this.user._id),
problem.getList(domainId, tdoc.pids, true),
]);
const psdict = {};
@@ -74,7 +70,6 @@ class HomeworkDetailHandler extends Handler {
rdict = await record.getList(
domainId,
tsdoc.journal.map((pdetail) => pdetail.rid),
true,
);
}
}
@@ -87,11 +82,6 @@ class HomeworkDetailHandler extends Handler {
const uids = ddocs.map((ddoc) => ddoc.owner);
uids.push(tdoc.owner);
const udict = await user.getList(domainId, uids);
const path = [
['Hydro', 'homepage'],
['homework_main', 'homework_main'],
[tdoc.title, null, null, true],
];
const index = tdoc.pids.map((i) => i.toString());
for (const key in pdict) {
const i = (index.indexOf(key) + 10).toString(36).toUpperCase();
@@ -99,31 +89,32 @@ class HomeworkDetailHandler extends Handler {
}
this.response.template = 'homework_detail.html';
this.response.body = {
tdoc, tsdoc, attended, udict, pdict, psdict, rdict, ddocs, page, dpcount, dcount, path,
tdoc, tsdoc, attended, udict, pdict, psdict, rdict, ddocs, page, dpcount, dcount,
};
}
@param('tid', Types.ObjectID)
async postAttend(domainId: string, tid: ObjectID) {
this.checkPerm(PERM.PERM_ATTEND_HOMEWORK);
const tdoc = await contest.get(domainId, tid, document.TYPE_HOMEWORK);
const tdoc = await contest.get(domainId, tid);
if (contest.isDone(tdoc)) throw new HomeworkNotLiveError(tdoc.docId);
await contest.attend(domainId, tdoc.docId, this.user._id, document.TYPE_HOMEWORK);
await contest.attend(domainId, tdoc.docId, this.user._id);
this.back();
}
@param('tid', Types.ObjectID)
async postDelete(domainId: string, tid: ObjectID) {
const tdoc = await contest.get(domainId, tid, document.TYPE_HOMEWORK);
const tdoc = await contest.get(domainId, tid);
if (!this.user.own(tdoc)) this.checkPerm(PERM.PERM_EDIT_HOMEWORK);
await contest.del(domainId, tid, document.TYPE_HOMEWORK);
await contest.del(domainId, tid);
this.response.redirect = this.url('homework_main');
}
}
class HomeworkDetailProblemHandler extends Handler {
tdoc: Tdoc<60>;
tdoc: Tdoc<30>;
pdoc: ProblemDoc;
pid: ProblemId;
tsdoc: any;
udoc: User;
attended: boolean;
@@ -131,19 +122,20 @@ class HomeworkDetailProblemHandler extends Handler {
@param('tid', Types.ObjectID)
@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);
this.tdoc = await contest.get(domainId, tid);
if (this.tdoc.rule !== 'homework') throw new ContestNotFoundError(domainId, tid);
this.pid = this.tdoc.pids[parseInt(_pid, 36) - 10];
if (!this.pid) throw new ProblemNotFoundError(domainId, tid, _pid);
[this.udoc, this.pdoc, this.tsdoc] = await Promise.all([
user.getById(domainId, this.tdoc.owner),
problem.get(domainId, pid),
contest.getStatus(domainId, tid, this.user._id, document.TYPE_HOMEWORK),
problem.get(domainId, this.pid),
contest.getStatus(domainId, tid, this.user._id),
]);
if (!this.pdoc) throw new ProblemNotFoundError(domainId, pid);
if (!this.pdoc) throw new ProblemNotFoundError(domainId, this.pid);
// @ts-ignore
if (this.pdoc.domainId !== domainId) this.pdoc.docId = `${this.pdoc.domainId}:${this.pdoc.docId}`;
this.pdoc.pid = _pid;
this.attended = this.tsdoc && this.tsdoc.attend === 1;
this.attended = this.tsdoc?.attend === 1;
this.response.body = {
tdoc: this.tdoc,
pdoc: this.pdoc,
@@ -212,13 +204,11 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler {
pdomain: DomainDoc;
@param('tid', Types.ObjectID)
@param('pid', Types.Name)
async prepare(domainId: string, tid: ObjectID, _pid: string) {
const pid = this.tdoc.pids[parseInt(_pid, 36) - 10];
async prepare(domainId: string, tid: ObjectID) {
if (!this.attended) throw new HomeworkNotAttendedError(tid);
if (!contest.isOngoing(this.tdoc)) throw new HomeworkNotLiveError(tid);
this.pdomainId = typeof pid === 'string' ? pid.split(':')[0] : domainId;
this.ppid = typeof pid === 'number' ? pid : +pid.split(':')[1];
this.pdomainId = typeof this.pid === 'string' ? this.pid.split(':')[0] : domainId;
this.ppid = typeof this.pid === 'number' ? this.pid : +this.pid.split(':')[1];
this.pdomain = await domain.get(this.pdomainId);
if (this.pdomain.langs) {
this.response.body.pdoc.config.langs = intersection(
@@ -243,29 +233,23 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler {
}
@param('tid', Types.ObjectID)
@param('pid', Types.String)
@param('code', Types.Content)
@param('lang', Types.Name)
@param('pretest', Types.Boolean)
@param('input', Types.String, true)
async post(domainId: string, tid: ObjectID, _pid: string, code: string, lang: string, pretest = false, input = '') {
const pid = this.tdoc.pids[parseInt(_pid, 36) - 10];
async post(domainId: string, tid: ObjectID, code: string, lang: string, pretest = false, input = '') {
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, system.get('limit.submission'));
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : {
type: document.TYPE_HOMEWORK,
tid,
});
const rid = await record.add(domainId, this.pid, this.user._id, lang, code, true, pretest ? input : tid);
const rdoc = await record.get(domainId, rid);
if (!pretest) {
await Promise.all([
(this.tsdoc.journal || []).filter((i) => i.pid === pid).length
(this.tsdoc.journal || []).filter((i) => i.pid === this.pid).length
&& problem.inc(this.pdomainId, this.ppid, 'nSubmit', 1),
domain.incUserInDomain(domainId, this.user._id, 'nSubmit'),
contest.updateStatus(domainId, tid, this.user._id,
rid, pid, STATUS.STATUS_WAITING, 0, document.TYPE_HOMEWORK),
contest.updateStatus(domainId, tid, this.user._id, rid, this.pid, STATUS.STATUS_WAITING),
]);
}
bus.broadcast('record/change', rdoc);
@@ -279,9 +263,7 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler {
class HomeworkEditHandler extends Handler {
@param('tid', Types.ObjectID, true)
async get(domainId: string, tid: ObjectID) {
const tdoc = tid
? await contest.get(domainId, tid, document.TYPE_HOMEWORK)
: null;
const tdoc = tid ? await contest.get(domainId, tid) : null;
if (!tid) this.checkPerm(PERM.PERM_CREATE_HOMEWORK);
else if (!this.user.own(tdoc)) this.checkPerm(PERM.PERM_EDIT_HOMEWORK);
else this.checkPerm(PERM.PERM_EDIT_HOMEWORK_SELF);
@@ -290,16 +272,6 @@ class HomeworkEditHandler extends Handler {
(tdoc.endAt.getTime() - tdoc.penaltySince.getTime()) / (Time.day / 100),
) / 100
: 1;
const path = [
['Hydro', 'homepage'],
['homework_main', 'homework_main'],
...tid
? [
[tdoc.title, 'homework_detail', { tid }, true],
['homework_edit', null],
]
: [['homework_create', null]],
];
const beginAt = tid
? moment(tdoc.beginAt).tz(this.user.timeZone)
: moment().add(1, 'day').tz(this.user.timeZone).hour(0).minute(0).millisecond(0);
@@ -316,7 +288,6 @@ class HomeworkEditHandler extends Handler {
extensionDays,
penaltyRules: tid ? yaml.dump(tdoc.penaltyRules) : null,
pids: tid ? tdoc.pids.join(',') : '',
path,
page_name: tid ? 'homework_edit' : 'homework_create',
};
}
@@ -344,9 +315,7 @@ class HomeworkEditHandler extends Handler {
if (!i.includes(':')) throw new ValidationError('pids');
return i;
}).filter((i) => i);
const tdoc = tid
? await contest.get(domainId, tid, document.TYPE_HOMEWORK)
: null;
const tdoc = tid ? await contest.get(domainId, tid) : null;
if (!tid) this.checkPerm(PERM.PERM_CREATE_HOMEWORK);
else if (!this.user.own(tdoc)) this.checkPerm(PERM.PERM_EDIT_HOMEWORK);
else this.checkPerm(PERM.PERM_EDIT_HOMEWORK_SELF);
@@ -361,16 +330,16 @@ class HomeworkEditHandler extends Handler {
if (!tid) {
tid = await contest.add(domainId, title, content, this.user._id,
'homework', beginAt.toDate(), endAt.toDate(), pids, rated,
{ penaltySince: penaltySince.toDate(), penaltyRules }, document.TYPE_HOMEWORK);
{ penaltySince: penaltySince.toDate(), penaltyRules });
} else {
await contest.edit(domainId, tid, {
title, content, beginAt: beginAt.toDate(), endAt: endAt.toDate(), pids, penaltySince: penaltySince.toDate(), penaltyRules, rated,
}, document.TYPE_HOMEWORK);
});
if (tdoc.beginAt !== beginAt.toDate()
|| tdoc.endAt !== endAt.toDate()
|| tdoc.penaltySince !== penaltySince.toDate()
|| tdoc.pids.sort().join(' ') !== pids.sort().join(' ')) {
await contest.recalcStatus(domainId, tdoc.docId, document.TYPE_HOMEWORK);
await contest.recalcStatus(domainId, tdoc.docId);
}
}
this.response.body = { tid };
@@ -383,8 +352,7 @@ class HomeworkScoreboardHandler extends Handler {
@param('page', Types.PositiveInt, true)
async get(domainId: string, tid: ObjectID, page = 1) {
const [tdoc, rows, udict, , nPages] = await contest.getScoreboard.call(
this, domainId, tid, false,
page, document.TYPE_HOMEWORK,
this, domainId, tid, false, page,
);
const path = [
['Hydro', 'homepage'],
@@ -409,7 +377,7 @@ class HomeworkScoreboardDownloadHandler extends Handler {
html: (rows) => this.renderHTML('contest_scoreboard_download_html.html', { rows }),
};
if (!getContent[ext]) throw new ValidationError('ext');
const [tdoc, rows] = await contest.getScoreboard.call(this, domainId, tid, true, 0, document.TYPE_HOMEWORK);
const [tdoc, rows] = await contest.getScoreboard.call(this, domainId, tid, true, 0);
this.binary(await getContent[ext](rows), `${tdoc.title}.${ext}`);
}
}
@@ -418,9 +386,7 @@ class HomeworkCodeHandler extends Handler {
@param('tid', Types.ObjectID)
async get(domainId: string, tid: ObjectID) {
await this.limitRate('contest_code', 3600, 60);
const [tdoc, tsdocs] = await contest.getAndListStatus(
domainId, tid, document.TYPE_HOMEWORK,
);
const [tdoc, tsdocs] = await contest.getAndListStatus(domainId, tid);
if (!this.user.own(tdoc) && !this.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE)) {
this.checkPerm(PERM.PERM_READ_RECORD_CODE);
}
+2 -2
View File
@@ -32,9 +32,9 @@ export async function postJudge(rdoc: RecordDoc) {
const updated = await problem.updateStatus(rdoc.pdomain, rdoc.pid, rdoc.uid, rdoc._id, rdoc.status, rdoc.score);
if (rdoc.contest) {
await contest.updateStatus(
rdoc.domainId, rdoc.contest.tid, rdoc.uid, rdoc._id,
rdoc.domainId, rdoc.contest, rdoc.uid, rdoc._id,
rdoc.domainId === rdoc.pdomain ? rdoc.pid : `${rdoc.pdomain}:${rdoc.pid}`,
rdoc.status, rdoc.score, rdoc.contest.type,
rdoc.status, rdoc.score,
);
} else if (accept && updated) await domain.incUserInDomain(rdoc.domainId, rdoc.uid, 'nAccept', 1);
const pdoc = (accept && updated)
+2 -7
View File
@@ -16,7 +16,6 @@ import paginate from '../lib/paginate';
import { isPid, parsePid as convertPid } from '../lib/validator';
import { PERM, PRIV } from '../model/builtin';
import * as contest from '../model/contest';
import * as document from '../model/document';
import domain from '../model/domain';
import problem from '../model/problem';
import record from '../model/record';
@@ -258,12 +257,8 @@ export class ProblemDetailHandler extends ProblemHandler {
async postDelete() {
if (!this.user.own(this.pdoc, PERM.PERM_EDIT_PROBLEM_SELF)) this.checkPerm(PERM.PERM_EDIT_PROBLEM);
const [ctdocs, htdocs] = await Promise.all([
contest.getRelated(this.domainId, this.pdoc.docId, document.TYPE_CONTEST),
contest.getRelated(this.domainId, this.pdoc.docId, document.TYPE_HOMEWORK),
]);
if (ctdocs.length) throw new BadRequestError('Problem already used by contest {0}', ctdocs[0]._id);
if (htdocs.length) throw new BadRequestError('Problem already used by homwrork {0}', htdocs[0]._id);
const tdocs = await contest.getRelated(this.domainId, this.pdoc.docId);
if (tdocs.length) throw new BadRequestError('Problem already used by contest {0}', tdocs[0]._id);
await problem.del(this.pdoc.domainId, this.pdoc.docId);
this.response.redirect = this.url('problem_main');
}
+18 -15
View File
@@ -4,7 +4,7 @@ import {
ContestNotAttendedError, ContestNotFoundError, PermissionError,
ProblemNotFoundError, RecordNotFoundError, UserNotFoundError,
} from '../error';
import { RecordDoc } from '../interface';
import { RecordDoc, Tdoc } from '../interface';
import { PERM, PRIV, STATUS } from '../model/builtin';
import * as contest from '../model/contest';
import problem from '../model/problem';
@@ -34,13 +34,13 @@ class RecordListHandler extends Handler {
let tdoc = null;
let invalid = false;
this.response.template = 'record_main.html';
const q: FilterQuery<RecordDoc> = { 'contest.tid': tid, hidden: false };
const q: FilterQuery<RecordDoc> = { contest: tid };
if (full) uidOrName = this.user._id.toString();
if (tid) {
tdoc = await contest.get(domainId, tid, -1);
tdoc = await contest.get(domainId, tid);
if (!tdoc) throw new ContestNotFoundError(domainId, pid);
if (!contest.canShowScoreboard.call(this, tdoc, true)) throw new PermissionError(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
if (!this.user.own(tdoc) && !(await contest.getStatus(domainId, tid, this.user._id, -1))?.attend) {
if (!this.user.own(tdoc) && !(await contest.getStatus(domainId, tid, this.user._id))?.attend) {
throw new ContestNotAttendedError(domainId, tid);
}
}
@@ -108,7 +108,7 @@ class RecordDetailHandler extends Handler {
const rdoc = await record.get(domainId, rid);
if (!rdoc) throw new RecordNotFoundError(rid);
if (rdoc.contest) {
const tdoc = await contest.get(domainId, rdoc.contest.tid, rdoc.contest.type);
const tdoc = await contest.get(domainId, rdoc.contest);
let canView = this.user.own(tdoc);
canView ||= contest.canShowRecord.call(this, tdoc);
canView ||= contest.canShowSelfRecord.call(this, tdoc, true) && rdoc.uid === this.user._id;
@@ -135,7 +135,7 @@ class RecordDetailHandler extends Handler {
}
this.response.body = { udoc, rdoc, pdoc };
if (rdoc.contest) {
this.response.body.tdoc = await contest.get(domainId, rdoc.contest.tid, rdoc.contest.type);
this.response.body.tdoc = await contest.get(domainId, rdoc.contest);
}
}
@@ -182,6 +182,7 @@ class RecordMainConnectionHandler extends ConnectionHandler {
pid: number;
status: number;
pretest = false;
tdoc: Tdoc<30>;
@param('tid', Types.ObjectID, true)
@param('pid', Types.Name, true)
@@ -194,9 +195,9 @@ class RecordMainConnectionHandler extends ConnectionHandler {
status?: number, pretest = false, all = false,
) {
if (tid) {
const tdoc = await contest.get(domainId, tid, -1);
if (!tdoc) throw new ContestNotFoundError(domainId, tid);
if (pretest || contest.canShowScoreboard.call(this, tdoc, true)) this.tid = tid.toHexString();
this.tdoc = await contest.get(domainId, tid);
if (!this.tdoc) throw new ContestNotFoundError(domainId, tid);
if (pretest || contest.canShowScoreboard.call(this, this.tdoc, true)) this.tid = tid.toHexString();
else throw new PermissionError(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
}
if (pretest) {
@@ -236,10 +237,12 @@ class RecordMainConnectionHandler extends ConnectionHandler {
}
async onRecordChange(rdoc: RecordDoc) {
if (!this.all && !this.pretest && rdoc.input) return;
if (!this.all && rdoc.domainId !== this.domainId) return;
if (!this.all && rdoc.contest && rdoc.contest.tid.toString() !== this.tid) return;
if (!this.all && this.pid && rdoc.pid !== this.pid) return;
if (!this.all) {
if (!this.pretest && rdoc.input) return;
if (rdoc.domainId !== this.domainId) return;
if (rdoc.contest && ![this.tid, '000000000000000000000000'].includes(rdoc.contest.toString())) return;
}
if (this.pid && rdoc.pid !== this.pid) return;
if (this.uid && rdoc.uid !== this.uid) return;
// eslint-disable-next-line prefer-const
@@ -247,7 +250,7 @@ class RecordMainConnectionHandler extends ConnectionHandler {
user.getById(this.domainId, rdoc.uid),
problem.get(rdoc.pdomain, rdoc.pid),
]);
const tdoc = this.tid ? await contest.get(rdoc.domainId, new ObjectID(this.tid), -1) : null;
const tdoc = this.tid ? this.tdoc || await contest.get(rdoc.domainId, new ObjectID(this.tid)) : null;
if (pdoc && !rdoc.contest) {
if (pdoc.hidden && !this.user.own(pdoc) && !this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) pdoc = null;
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)) pdoc = null;
@@ -272,7 +275,7 @@ class RecordDetailConnectionHandler extends ConnectionHandler {
const rdoc = await record.get(domainId, rid);
if (!rdoc) return;
if (rdoc.contest && rdoc.input === undefined) {
const tdoc = await contest.get(domainId, rdoc.contest.tid, -1);
const tdoc = await contest.get(domainId, rdoc.contest);
let canView = this.user.own(tdoc);
canView ||= contest.canShowRecord.call(this, tdoc);
canView ||= this.user._id === rdoc.uid && contest.canShowSelfRecord.call(this, tdoc);