diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index 34e5436f9..8f40ea16c 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -273,6 +273,11 @@ export class ContestPrintHandler extends ContestDetailBaseHandler { } export class ContestProblemListHandler extends ContestDetailBaseHandler { + @param('tid', Types.ObjectId) + async prepare(domainId: string, tid: ObjectId) { + if (contest.RULES[this.tdoc.rule].hidden) throw new ContestNotFoundError(domainId, tid); + } + @param('tid', Types.ObjectId) async get(domainId: string, tid: ObjectId) { if (contest.isNotStarted(this.tdoc)) throw new ContestNotLiveError(domainId, tid); @@ -663,6 +668,9 @@ export class ContestFileDownloadHandler extends ContestDetailBaseHandler { @param('noDisposition', Types.Boolean) @param('type', Types.Range(['public', 'private']), true) async get(domainId: string, tid: ObjectId, filename: string, noDisposition = false, type = 'private') { + if (contest.RULES[this.tdoc.rule].hidden && !contest.RULES[this.tdoc.rule].features?.includes('download')) { + throw new ContestNotFoundError(domainId, tid); + } if (type === 'private' && !this.user.own(this.tdoc) && !this.user.hasPerm(PERM.PERM_EDIT_CONTEST)) { if (!this.tsdoc?.attend) throw new ContestNotAttendedError(domainId, tid); if (!contest.isOngoing(this.tdoc) && !contest.isDone(this.tdoc)) throw new ContestNotLiveError(domainId, tid); @@ -785,6 +793,9 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler { @param('tid', Types.ObjectId) @param('view', Types.String, true) async get(domainId: string, tid: ObjectId, viewId = 'default') { + if (contest.RULES[this.tdoc.rule].hidden && !contest.RULES[this.tdoc.rule].features?.includes('scoreboard')) { + throw new ContestNotFoundError(domainId, tid); + } if (!this.user.own(this.tdoc)) { if (!contest.canShowScoreboard.call(this, this.tdoc, true)) throw new ContestScoreboardHiddenError(tid); if (contest.isNotStarted(this.tdoc)) throw new ContestNotLiveError(domainId, tid); diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 206412b18..f54a787f3 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -422,10 +422,13 @@ export interface ScoreboardConfig { lockAt?: Date; } +export type Feature = 'scoreboard' | 'download'; + export interface ContestRule { _originalRule?: Partial>; TEXT: string; hidden?: boolean; + features?: Feature[]; check: (args: any) => any; statusSort: Record; submitAfterAccept: boolean; diff --git a/packages/hydrooj/src/model/contest.ts b/packages/hydrooj/src/model/contest.ts index bd9f9aa0e..2a6964180 100644 --- a/packages/hydrooj/src/model/contest.ts +++ b/packages/hydrooj/src/model/contest.ts @@ -636,6 +636,7 @@ const ledo = buildContestRule({ const homework = buildContestRule({ TEXT: 'Assignment', hidden: true, + features: ['scoreboard', 'download'], check: () => { }, submitAfterAccept: false, statusSort: { penaltyScore: -1, time: 1 },