mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 09:46:28 +08:00
core: database structure update
This commit is contained in:
1 parent
dca8e28361
commit
4daf8bac80
24 files changed
+182
-263
No files matched your search
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user