core: fix contest permission check

pull/546/head
undefined 2 years ago
parent 78b6c6b913
commit dde46c6e7f
No known key found for this signature in database

@ -331,10 +331,8 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler {
async exportScoreboard(domainId: string, tid: ObjectId, ext: string) { async exportScoreboard(domainId: string, tid: ObjectId, ext: string) {
await this.limitRate('scoreboard_download', 60, 3); await this.limitRate('scoreboard_download', 60, 3);
if (ext === 'ghost') { if (ext === 'ghost') {
if ((contest.isDone(this.tdoc) || contest.isLocked(this.tdoc)) && !this.tdoc.unlocked) { if (contest.isLocked(this.tdoc) && !this.user.own(this.tdoc)) {
if (!this.user.own(this.tdoc)) { this.checkPerm(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
this.checkPerm(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
}
} }
await this.exportGhost(domainId, tid); await this.exportGhost(domainId, tid);
return; return;

@ -51,13 +51,14 @@ class RecordListHandler extends ContestDetailBaseHandler {
this.tdoc = tdoc; this.tdoc = tdoc;
if (!tdoc) throw new ContestNotFoundError(domainId, pid); if (!tdoc) throw new ContestNotFoundError(domainId, pid);
if (!contest.canShowScoreboard.call(this, tdoc, true)) throw new PermissionError(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD); if (!contest.canShowScoreboard.call(this, tdoc, true)) throw new PermissionError(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
if (!contest.canShowRecord.call(this, tdoc, true)) {
throw new PermissionError(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
}
if (!(await contest.getStatus(domainId, tid, this.user._id))?.attend) { if (!(await contest.getStatus(domainId, tid, this.user._id))?.attend) {
if (contest.canShowRecord.call(this, tdoc, true)) { const name = tdoc.rule === 'homework'
const name = tdoc.rule === 'homework' ? "You haven't claimed this homework yet."
? "You haven't claimed this homework yet." : "You haven't attended this contest yet.";
: "You haven't attended this contest yet."; notification.push({ name, args: { type: 'note' }, checker: () => true });
notification.push({ name, args: { type: 'note' }, checker: () => true });
} else throw new ContestNotAttendedError(domainId, tid);
} }
} }
if (uidOrName) { if (uidOrName) {
@ -250,7 +251,7 @@ class RecordMainConnectionHandler extends ConnectionHandler {
if (tid) { if (tid) {
this.tdoc = await contest.get(domainId, tid); this.tdoc = await contest.get(domainId, tid);
if (!this.tdoc) throw new ContestNotFoundError(domainId, tid); if (!this.tdoc) throw new ContestNotFoundError(domainId, tid);
if (pretest || contest.canShowScoreboard.call(this, this.tdoc, true)) this.tid = tid.toHexString(); if (pretest || contest.canShowScoreboard.call(this, this.tdoc, true, true)) this.tid = tid.toHexString();
else throw new PermissionError(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD); else throw new PermissionError(PERM.PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
} }
if (pretest) { if (pretest) {

@ -53,7 +53,8 @@ const acm = buildContestRule({
submitAfterAccept: false, submitAfterAccept: false,
showScoreboard: (tdoc, now) => now > tdoc.beginAt, showScoreboard: (tdoc, now) => now > tdoc.beginAt,
showSelfRecord: () => true, showSelfRecord: () => true,
showRecord: (tdoc, now) => now > tdoc.endAt, // eslint-disable-next-line @typescript-eslint/no-use-before-define
showRecord: (tdoc, now) => now > tdoc.endAt && !isLocked(tdoc),
stat(tdoc, journal: AcmJournal[]) { stat(tdoc, journal: AcmJournal[]) {
const naccept = Counter<number>(); const naccept = Counter<number>();
const npending = Counter<number>(); const npending = Counter<number>();
@ -245,7 +246,8 @@ const oi = buildContestRule({
}, },
showScoreboard: (tdoc, now) => now > tdoc.endAt, showScoreboard: (tdoc, now) => now > tdoc.endAt,
showSelfRecord: (tdoc, now) => now > tdoc.endAt, showSelfRecord: (tdoc, now) => now > tdoc.endAt,
showRecord: (tdoc, now) => now > tdoc.endAt, // eslint-disable-next-line @typescript-eslint/no-use-before-define
showRecord: (tdoc, now) => now > tdoc.endAt && !isLocked(tdoc),
async scoreboardHeader(config, _, tdoc, pdict) { async scoreboardHeader(config, _, tdoc, pdict) {
const columns: ScoreboardNode[] = [ const columns: ScoreboardNode[] = [
{ type: 'rank', value: '#' }, { type: 'rank', value: '#' },
@ -781,7 +783,7 @@ export function isDone(tdoc: Tdoc, tsdoc?: any) {
export function isLocked(tdoc: Tdoc) { export function isLocked(tdoc: Tdoc) {
if (!tdoc.lockAt) return false; if (!tdoc.lockAt) return false;
const now = new Date(); const now = new Date();
return (tdoc.lockAt < now && now < tdoc.endAt); return tdoc.lockAt < now && !tdoc.unlocked;
} }
export function isExtended(tdoc: Tdoc) { export function isExtended(tdoc: Tdoc) {

@ -10,13 +10,11 @@
{% if model.contest.isLocked(tdoc) %} {% if model.contest.isLocked(tdoc) %}
<div class="section__body no-padding"> <div class="section__body no-padding">
<blockquote class="note"> <blockquote class="note">
{{ _('The scoreboard was frozen with {0} minutes remaining at {1} - submissions in the last {0} minutes of the contest are still shown as pending.').format((tdoc.endAt - tdoc.lockAt) / 1000 / 60, datetimeSpan(tdoc.lockAt))|safe }} {% if model.contest.isDone(tdoc) %}
</blockquote> {{ _('Please wait until contest host unfreeze the scoreboard.') }}
</div> {% else %}
{% elif model.contest.isDone(tdoc) and tdoc.lockAt and not tdoc.unlocked %} {{ _('The scoreboard was frozen with {0} minutes remaining at {1} - submissions in the last {0} minutes of the contest are still shown as pending.').format((tdoc.endAt - tdoc.lockAt) / 1000 / 60, datetimeSpan(tdoc.lockAt))|safe }}
<div class="section__body no-padding"> {% endif %}
<blockquote class="note">
{{ _('Please wait until contest host unfreeze the scoreboard.') }}
</blockquote> </blockquote>
</div> </div>
{% endif %} {% endif %}

Loading…
Cancel
Save