core: list all domains for users with PRIV_VIEW_ALL_DOMAIN

This commit is contained in:
undefined committed 2021-05-11 23:38:34 +08:00
1 parent ced60e6567
commit 29965f323b
16 files changed
+53 -26

No files matched your search

+1 -1
View File
@@ -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",
+3 -1
View File
@@ -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',
+11 -4
View File
@@ -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<string, DomainDoc>;
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
+2 -2
View File
@@ -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,
+7 -3
View File
@@ -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<string>, 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',
+3 -1
View File
@@ -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),
+3 -3
View File
@@ -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<number>();
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);
}
}
+5 -2
View File
@@ -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 */
+7 -2
View File
@@ -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<T extends keyof DocType>(doc: DocType[T], user: User): Promise<boolean> {
if (doc.owner === user._id || doc.maintainers.includes(user._id) || doc.participants.includes(user._id)) return true;
if ()
}
export async function add<T extends keyof DocType, K extends DocType[T]['docId']>(
domainId: string, content: Content, owner: number,
docType: T, docId: K,
+5 -1
View File
@@ -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
+1 -1
View File
@@ -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);