From 29965f323b1257ad19ceae3cebe54ec82e21197c Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 11 May 2021 23:38:34 +0800 Subject: [PATCH] core: list all domains for users with PRIV_VIEW_ALL_DOMAIN --- packages/hydrooj/package.json | 2 +- packages/hydrooj/src/handler/contest.ts | 4 +++- packages/hydrooj/src/handler/home.ts | 15 +++++++++++---- packages/hydrooj/src/handler/homework.ts | 4 ++-- packages/hydrooj/src/handler/problem.ts | 10 +++++++--- packages/hydrooj/src/handler/record.ts | 4 +++- packages/hydrooj/src/handler/remote.ts | 6 +++--- packages/hydrooj/src/model/builtin.ts | 7 +++++-- packages/hydrooj/src/model/document.ts | 9 +++++++-- packages/hydrooj/src/model/user.ts | 6 +++++- packages/hydrooj/src/service/server.ts | 2 +- packages/ui-default/package.json | 2 +- .../templates/partials/contest_sidebar.html | 2 +- .../templates/partials/homework_sidebar.html | 2 +- .../partials/problem_sidebar_normal.html | 2 +- packages/ui-default/templates/problem_files.html | 2 +- 16 files changed, 53 insertions(+), 26 deletions(-) diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 534045040..53c4918ea 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.25.9", + "version": "2.25.10", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index 99da25b13..57c795366 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -296,7 +296,9 @@ export class ContestProblemFileDownloadHandler extends ContestProblemHandler { @param('filename', Types.Name) @param('noDisposition', Types.Boolean) async get(domainId: string, type = 'additional_file', filename: string, noDisposition = false) { - if (type === 'testdata' && !this.user.own(this.pdoc)) this.checkPerm(PERM.PERM_READ_PROBLEM_DATA); + if (type === 'testdata' && !this.user.own(this.pdoc)) { + if (!this.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA)) this.checkPerm(PERM.PERM_READ_PROBLEM_DATA); + } this.response.redirect = await storage.signDownloadLink( `problem/${this.pdoc.domainId}/${this.pdoc.docId}/${type}/${filename}`, noDisposition ? undefined : filename, false, 'user', diff --git a/packages/hydrooj/src/handler/home.ts b/packages/hydrooj/src/handler/home.ts index 0ceb6aa6b..cd4ff0c85 100644 --- a/packages/hydrooj/src/handler/home.ts +++ b/packages/hydrooj/src/handler/home.ts @@ -5,7 +5,7 @@ import { NotFoundError, UserNotFoundError, PermissionError, DomainAlreadyExistsError, ValidationError, BlacklistedError, } from '../error'; -import { Mdoc, Setting } from '../interface'; +import { Mdoc, Setting, DomainDoc } from '../interface'; import * as bus from '../service/bus'; import { Route, Connection, Handler, ConnectionHandler, param, Types, @@ -281,9 +281,16 @@ class HomeDomainHandler extends Handler { ['Hydro', 'homepage'], ['home_domain', null], ]; - const dudict = await domain.getDictUserByDomainId(this.user._id); - const dids = Object.keys(dudict); - const ddocs = await domain.getMulti({ _id: { $in: dids } }).toArray(); + let ddocs: DomainDoc[]; + let dudict: Record; + if (!this.user.hasPriv(PRIV.PRIV_VIEW_ALL_DOMAIN)) { + dudict = await domain.getDictUserByDomainId(this.user._id); + const dids = Object.keys(dudict); + ddocs = await domain.getMulti({ _id: { $in: dids } }).toArray(); + } else { + ddocs = await domain.getMulti().toArray(); + for (const ddoc of ddocs) dudict[ddoc._id] = ddoc; + } const canManage = {}; for (const ddoc of ddocs) { // eslint-disable-next-line no-await-in-loop diff --git a/packages/hydrooj/src/handler/homework.ts b/packages/hydrooj/src/handler/homework.ts index bd9870d00..0a28ff656 100644 --- a/packages/hydrooj/src/handler/homework.ts +++ b/packages/hydrooj/src/handler/homework.ts @@ -13,7 +13,7 @@ import { } from '../service/server'; import * as bus from '../service/bus'; import domain from '../model/domain'; -import { PERM } from '../model/builtin'; +import { PERM, PRIV } from '../model/builtin'; import user from '../model/user'; import * as system from '../model/system'; import * as contest from '../model/contest'; @@ -391,7 +391,7 @@ class HomeworkScoreboardDownloadHandler extends Handler { class HomeworkCodeHandler extends Handler { @param('tid', Types.ObjectID) async get(domainId: string, tid: ObjectID) { - this.checkPerm(PERM.PERM_READ_RECORD_CODE); + if (!this.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE)) this.checkPerm(PERM.PERM_READ_RECORD_CODE); await this.limitRate('homework_code', 3600, 60); const [tdoc, tsdocs] = await contest.getAndListStatus( domainId, tid, document.TYPE_HOMEWORK, diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index a6b84287d..79e40aa07 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -380,7 +380,9 @@ export class ProblemFilesHandler extends ProblemDetailHandler { @param('testdata', Types.Boolean) @param('additional_file', Types.Boolean) async get(domainId: string, getTestdata = true, getAdditionalFile = true) { - const canReadData = !this.user.own(this.pdoc) || this.user.hasPerm(PERM.PERM_READ_PROBLEM_DATA); + const canReadData = this.user.own(this.pdoc) + || this.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA) + || this.user.hasPerm(PERM.PERM_READ_PROBLEM_DATA); this.response.body.testdata = (getTestdata && canReadData) ? sortFiles(this.pdoc.data || []) : []; this.response.body.additional_file = getAdditionalFile ? sortFiles(this.pdoc.additional_file || []) : []; this.response.template = 'problem_files.html'; @@ -390,7 +392,7 @@ export class ProblemFilesHandler extends ProblemDetailHandler { @post('type', Types.Range(['testdata', 'additional_file']), true) async postGetLinks(domainId: string, files: Set, type = 'testdata') { if (type === 'testdata' && !this.user.own(this.pdoc)) { - this.checkPerm(PERM.PERM_READ_PROBLEM_DATA); + if (!this.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA)) this.checkPerm(PERM.PERM_READ_PROBLEM_DATA); } const links = {}; for (const file of files) { @@ -449,7 +451,9 @@ export class ProblemFileDownloadHandler extends ProblemDetailHandler { @param('filename', Types.Name) @param('noDisposition', Types.Boolean) async get(domainId: string, type = 'additional_file', filename: string, noDisposition = false) { - if (type === 'testdata' && !this.user.own(this.pdoc)) this.checkPerm(PERM.PERM_READ_PROBLEM_DATA); + if (type === 'testdata' && !this.user.own(this.pdoc)) { + if (!this.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA)) this.checkPerm(PERM.PERM_READ_PROBLEM_DATA); + } this.response.redirect = await storage.signDownloadLink( `problem/${this.pdoc.domainId}/${this.pdoc.docId}/${type}/${filename}`, noDisposition ? undefined : filename, false, 'user', diff --git a/packages/hydrooj/src/handler/record.ts b/packages/hydrooj/src/handler/record.ts index 3c2572651..4eade0bab 100644 --- a/packages/hydrooj/src/handler/record.ts +++ b/packages/hydrooj/src/handler/record.ts @@ -92,7 +92,9 @@ class RecordDetailHandler extends Handler { const tdoc = await contest.get(domainId, rdoc.contest.tid, rdoc.contest.type); if (!contest.canShowRecord.call(this, tdoc, true)) throw new PermissionError(rid); } - if (rdoc.uid !== this.user._id && !this.user.hasPerm(PERM.PERM_READ_RECORD_CODE)) rdoc.code = null; + if (rdoc.uid !== this.user._id && !this.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE)) { + if (!this.user.hasPerm(PERM.PERM_READ_RECORD_CODE)) rdoc.code = null; + } // eslint-disable-next-line prefer-const let [pdoc, udoc] = await Promise.all([ problem.get(domainId, rdoc.pid), diff --git a/packages/hydrooj/src/handler/remote.ts b/packages/hydrooj/src/handler/remote.ts index ca7adb29c..46da897fc 100644 --- a/packages/hydrooj/src/handler/remote.ts +++ b/packages/hydrooj/src/handler/remote.ts @@ -6,7 +6,7 @@ import { PermissionError, InvalidTokenError, RemoteOnlineJudgeError } from '../e import { Logger } from '../logger'; import { logAndReturn } from '../utils'; import { ProblemAdd } from '../lib/ui'; -import { PERM } from '../model/builtin'; +import { PERM, PRIV } from '../model/builtin'; import token from '../model/token'; import problem from '../model/problem'; import * as system from '../model/system'; @@ -30,7 +30,7 @@ export class ProblemSendHandler extends Handler { const target = _target.split('@'); if (target[1].endsWith('/')) target[1] = target[1].substr(0, target[1].length - 1); const getHidden = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN); - const getData = this.user.hasPerm(PERM.PERM_READ_PROBLEM_DATA); + const getData = this.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA) || this.user.hasPerm(PERM.PERM_READ_PROBLEM_DATA); const pdocs = await problem.getList(domainId, _pids, true, true, ['docId', 'owner', 'hidden']); const pids = new Set(); for (const key in pdocs) { @@ -38,7 +38,7 @@ export class ProblemSendHandler extends Handler { if (pdocs[key].hidden && !getHidden && !this.user.own(pdocs[key])) { throw new PermissionError(PERM.PERM_VIEW_PROBLEM_HIDDEN); } - if (!getData && !this.user.own(pdocs[key])) { + if (!getData && !this.user.own(pdocs[key]) && !this.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA)) { throw new PermissionError(PERM.PERM_READ_PROBLEM_DATA); } } diff --git a/packages/hydrooj/src/model/builtin.ts b/packages/hydrooj/src/model/builtin.ts index 1c188f867..47f1924dd 100644 --- a/packages/hydrooj/src/model/builtin.ts +++ b/packages/hydrooj/src/model/builtin.ts @@ -227,8 +227,6 @@ export const PRIV = { PRIV_USER_PROFILE: 1 << 2, PRIV_REGISTER_USER: 1 << 3, PRIV_READ_PROBLEM_DATA: 1 << 4, - PRIV_READ_PRETEST_DATA: 1 << 5, // deprecated - PRIV_READ_PRETEST_DATA_SELF: 1 << 6, // deprecated PRIV_READ_RECORD_CODE: 1 << 7, PRIV_VIEW_HIDDEN_RECORD: 1 << 8, PRIV_JUDGE: 1 << 9, // (renamed) @@ -239,11 +237,16 @@ export const PRIV = { PRIV_VIEW_USER_SECRET: 1 << 14, PRIV_VIEW_JUDGE_STATISTICS: 1 << 15, PRIV_UNLIMITED_ACCESS: 1 << 22, + PRIV_VIEW_SYSTEM_NOTIFICATION: 1 << 23, PRIV_ALL: -1, PRIV_DEFAULT: 0, PRIV_NEVER: 1 << 20, + /** @deprecated */ + PRIV_READ_PRETEST_DATA: 1 << 5, + /** @deprecated */ + PRIV_READ_PRETEST_DATA_SELF: 1 << 6, /** @deprecated */ PRIV_CREATE_FILE: 1 << 16, /** @deprecated */ diff --git a/packages/hydrooj/src/model/document.ts b/packages/hydrooj/src/model/document.ts index 130e26b4b..5f5c3870a 100644 --- a/packages/hydrooj/src/model/document.ts +++ b/packages/hydrooj/src/model/document.ts @@ -4,13 +4,13 @@ import { ObjectID, Cursor, FilterQuery, UpdateQuery, OnlyFieldsOfType, } from 'mongodb'; import { - Pdoc, Ddoc, Drdoc, Tdoc, TrainingDoc, ProblemStatusDoc, + Pdoc, Ddoc, Drdoc, Tdoc, TrainingDoc, + ProblemStatusDoc, User, Content, } from '../interface'; import { buildProjection } from '../utils'; import { NumberKeys, ArrayKeys, Projection, MaybeArray } from '../typeutils'; import db from '../service/db'; import * as bus from '../service/bus'; -import { Content } from '../loader'; type DocID = ObjectID | string | number; @@ -44,6 +44,11 @@ export interface DocStatusType { [key: number]: any } +export async function canView(doc: DocType[T], user: User): Promise { + if (doc.owner === user._id || doc.maintainers.includes(user._id) || doc.participants.includes(user._id)) return true; + if () +} + export async function add( domainId: string, content: Content, owner: number, docType: T, docId: K, diff --git a/packages/hydrooj/src/model/user.ts b/packages/hydrooj/src/model/user.ts index c909367aa..7bd9bd247 100644 --- a/packages/hydrooj/src/model/user.ts +++ b/packages/hydrooj/src/model/user.ts @@ -303,7 +303,11 @@ class UserModel { @ArgMethod static async setJudge(uid: number) { - return await UserModel.setPriv(uid, PRIV.PRIV_USER_PROFILE | PRIV.PRIV_JUDGE); + return await UserModel.setPriv( + uid, + PRIV.PRIV_USER_PROFILE | PRIV.PRIV_JUDGE | PRIV.PRIV_VIEW_ALL_DOMAIN + | PRIV.PRIV_READ_PROBLEM_DATA, + ); } @ArgMethod diff --git a/packages/hydrooj/src/service/server.ts b/packages/hydrooj/src/service/server.ts index c24efc2ba..552a1bfb1 100644 --- a/packages/hydrooj/src/service/server.ts +++ b/packages/hydrooj/src/service/server.ts @@ -519,7 +519,7 @@ export class Handler extends HandlerCommon { icon: global.Hydro.lib[key].icon, text: global.Hydro.lib[key].text, })); - if (!this.noCheckPermView) this.checkPerm(PERM.PERM_VIEW); + if (!this.noCheckPermView && !this.user.hasPriv(PRIV.PRIV_VIEW_ALL_DOMAIN)) this.checkPerm(PERM.PERM_VIEW); if (this.request.method === 'post' && this.request.headers.referer) { const host = new URL(this.request.headers.referer).host; if (host !== this.request.host) throw new CsrfTokenError(host); diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 259cb1d7c..36f511468 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.8.6", + "version": "4.8.7", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/templates/partials/contest_sidebar.html b/packages/ui-default/templates/partials/contest_sidebar.html index df9a96580..1e7702087 100644 --- a/packages/ui-default/templates/partials/contest_sidebar.html +++ b/packages/ui-default/templates/partials/contest_sidebar.html @@ -57,7 +57,7 @@ {{ _('Edit Contest') }} {% endif %} - {% if handler.user.hasPerm(perm.PERM_READ_RECORD_CODE) %} + {% if handler.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE) or handler.user.hasPerm(perm.PERM_READ_RECORD_CODE) %} diff --git a/packages/ui-default/templates/partials/homework_sidebar.html b/packages/ui-default/templates/partials/homework_sidebar.html index 029c3386e..1447d1bf4 100644 --- a/packages/ui-default/templates/partials/homework_sidebar.html +++ b/packages/ui-default/templates/partials/homework_sidebar.html @@ -57,7 +57,7 @@ {{ _('Edit Homework') }} {% endif %} - {% if handler.user.hasPerm(perm.PERM_READ_RECORD_CODE) %} + {% if handler.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE) or handler.user.hasPerm(perm.PERM_READ_RECORD_CODE) %} diff --git a/packages/ui-default/templates/partials/problem_sidebar_normal.html b/packages/ui-default/templates/partials/problem_sidebar_normal.html index 7e0fd6753..742170714 100644 --- a/packages/ui-default/templates/partials/problem_sidebar_normal.html +++ b/packages/ui-default/templates/partials/problem_sidebar_normal.html @@ -84,7 +84,7 @@ {{ _('Edit') }} {% endif %} - {% if page_name == 'problem_detail' and (handler.user.own(pdoc) or handler.user.hasPerm(perm.PERM_READ_PROBLEM_DATA)) %} + {% if page_name == 'problem_detail' and (handler.user.own(pdoc) or handler.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA) or handler.user.hasPerm(perm.PERM_READ_PROBLEM_DATA)) %}