From 87adfd288cad3ac01958644174a36a8218d96e07 Mon Sep 17 00:00:00 2001 From: panda Date: Tue, 30 Apr 2024 00:31:39 +0800 Subject: [PATCH] core: fix scoreboard_export PERM_VIEW_DISPLAYNAME (#793) --- packages/hydrooj/src/handler/contest.ts | 13 ++++++++----- packages/hydrooj/src/handler/training.ts | 2 +- packages/hydrooj/src/interface.ts | 1 + packages/hydrooj/src/model/contest.ts | 6 +++--- packages/hydrooj/src/model/user.ts | 6 +++--- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index cd691f87c..49fef3459 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -314,7 +314,7 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler { await this.exportScoreboard(domainId, tid, ext); return; } - const config: ScoreboardConfig = { isExport: false }; + const config: ScoreboardConfig = { isExport: false, showDisplayName: this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME) }; if (!realtime && this.tdoc.lockAt && !this.tdoc.unlocked) { config.lockAt = this.tdoc.lockAt; } @@ -388,7 +388,9 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler { csv: async (rows) => `\uFEFF${rows.map((c) => (c.map((i) => i.value?.toString().replace(/\n/g, ' ')).join(','))).join('\n')}`, html: (rows, tdoc) => this.renderHTML('contest_scoreboard_download_html.html', { rows, tdoc }), }; - const [, rows] = await contest.getScoreboard.call(this, domainId, tid, { isExport: true, lockAt: this.tdoc.lockAt }); + const [, rows] = await contest.getScoreboard.call(this, domainId, tid, { + isExport: true, lockAt: this.tdoc.lockAt, showDisplayName: this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME), + }); this.binary(await getContent[ext](rows, this.tdoc), `${this.tdoc.title}.${ext}`); } @@ -588,7 +590,7 @@ export class ContestManagementHandler extends ContestManagementBaseHandler { owner_udoc: await user.getById(domainId, this.tdoc.owner), pdict: await problem.getList(domainId, this.tdoc.pids, true, true, [...problem.PROJECTION_CONTEST_LIST, 'tag']), files: sortFiles(this.tdoc.files || []), - udict: await user.getListForRender(domainId, tcdocs.map((i) => i.owner)), + udict: await user.getListForRender(domainId, tcdocs.map((i) => i.owner), this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME)), tcdocs, urlForFile: (filename: string) => this.url('contest_file_download', { tid, filename }), }; @@ -693,7 +695,8 @@ export class ContestUserHandler extends ContestManagementBaseHandler { for (const tsdoc of tsdocs) { tsdoc.endAt = (this.tdoc.duration && tsdoc.startAt) ? moment(tsdoc.startAt).add(this.tdoc.duration, 'hours').toDate() : null; } - const udict = await user.getListForRender(domainId, [this.tdoc.owner, ...tsdocs.map((i) => i.uid)]); + const udict = await user.getListForRender(domainId, + [this.tdoc.owner, ...tsdocs.map((i) => i.uid)], this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME)); this.response.body = { tdoc: this.tdoc, tsdocs, udict }; this.response.pjax = 'partials/contest_user.html'; this.response.template = 'contest_user.html'; @@ -733,7 +736,7 @@ export class ContestBalloonHandler extends ContestManagementBaseHandler { owner_udoc: await user.getById(domainId, this.tdoc.owner), pdict: await problem.getList(domainId, this.tdoc.pids, true, true, problem.PROJECTION_CONTEST_LIST), bdocs, - udict: await user.getListForRender(domainId, uids), + udict: await user.getListForRender(domainId, uids, this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME)), }; this.response.pjax = 'partials/contest_balloon.html'; this.response.template = 'contest_balloon.html'; diff --git a/packages/hydrooj/src/handler/training.ts b/packages/hydrooj/src/handler/training.ts index 8c074c16e..6de397a44 100644 --- a/packages/hydrooj/src/handler/training.ts +++ b/packages/hydrooj/src/handler/training.ts @@ -112,7 +112,7 @@ class TrainingDetailHandler extends Handler { const canViewHidden = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id; const [udoc, udict, pdict, psdict, selfPsdict] = await Promise.all([ user.getById(domainId, tdoc.owner), - user.getListForRender(domainId, enrollUsers), + user.getListForRender(domainId, enrollUsers, this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME)), problem.getList(domainId, pids, canViewHidden, true), problem.getListStatus(domainId, uid, pids), shouldCompare ? problem.getListStatus(domainId, this.user._id, pids) : {}, diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 9d05486be..7f57a3637 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -530,6 +530,7 @@ export interface ContestStat extends Record { export interface ScoreboardConfig { isExport: boolean; + showDisplayName: boolean; lockAt?: Date; } diff --git a/packages/hydrooj/src/model/contest.ts b/packages/hydrooj/src/model/contest.ts index 8769a5cdc..dfaad2bcc 100644 --- a/packages/hydrooj/src/model/contest.ts +++ b/packages/hydrooj/src/model/contest.ts @@ -222,7 +222,7 @@ const acm = buildContestRule({ async scoreboard(config, _, tdoc, pdict, cursor) { const rankedTsdocs = await ranked(cursor, (a, b) => a.score === b.score && a.time === b.time); const uids = rankedTsdocs.map(([, tsdoc]) => tsdoc.uid); - const udict = await user.getListForRender(tdoc.domainId, uids); + const udict = await user.getListForRender(tdoc.domainId, uids, config.showDisplayName); // Find first accept const first = {}; const data = await document.collStatus.aggregate([ @@ -388,7 +388,7 @@ const oi = buildContestRule({ async scoreboard(config, _, tdoc, pdict, cursor) { const rankedTsdocs = await ranked(cursor, (a, b) => a.score === b.score); const uids = rankedTsdocs.map(([, tsdoc]) => tsdoc.uid); - const udict = await user.getListForRender(tdoc.domainId, uids); + const udict = await user.getListForRender(tdoc.domainId, uids, config.showDisplayName); const psdict = {}; const first = {}; await Promise.all(tdoc.pids.map(async (pid) => { @@ -726,7 +726,7 @@ const homework = buildContestRule({ async scoreboard(config, _, tdoc, pdict, cursor) { const rankedTsdocs = await ranked(cursor, (a, b) => a.score === b.score); const uids = rankedTsdocs.map(([, tsdoc]) => tsdoc.uid); - const udict = await user.getListForRender(tdoc.domainId, uids); + const udict = await user.getListForRender(tdoc.domainId, uids, config.showDisplayName); const columns = await this.scoreboardHeader(config, _, tdoc, pdict); const rows: ScoreboardRow[] = [ columns, diff --git a/packages/hydrooj/src/model/user.ts b/packages/hydrooj/src/model/user.ts index 501e8b264..0e60c4358 100644 --- a/packages/hydrooj/src/model/user.ts +++ b/packages/hydrooj/src/model/user.ts @@ -384,16 +384,16 @@ class UserModel { return projection ? coll.find(params).project(buildProjection(projection)) : coll.find(params); } - static async getListForRender(domainId: string, uids: number[]) { + static async getListForRender(domainId: string, uids: number[], showDisplayName = true) { const [udocs, vudocs, dudocs] = await Promise.all([ UserModel.getMulti({ _id: { $in: uids } }, ['_id', 'uname', 'mail', 'avatar', 'school', 'studentId']).toArray(), collV.find({ _id: { $in: uids } }).toArray(), - domain.getDomainUserMulti(domainId, uids).project({ uid: true, displayName: true }).toArray(), + domain.getDomainUserMulti(domainId, uids).project({ uid: true, displayName: showDisplayName }).toArray(), ]); const udict = {}; for (const udoc of udocs) udict[udoc._id] = udoc; for (const udoc of vudocs) udict[udoc._id] = udoc; - for (const dudoc of dudocs) udict[dudoc.uid].displayName = dudoc.displayName; + if (showDisplayName) for (const dudoc of dudocs) udict[dudoc.uid].displayName = dudoc.displayName; for (const uid of uids) udict[uid] ||= { ...UserModel.defaultUser }; for (const key in udict) { udict[key].school ||= '';