mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: list all domains for users with PRIV_VIEW_ALL_DOMAIN
This commit is contained in:
1 parent
ced60e6567
commit
29965f323b
16 files changed
+53
-26
No files matched your search
@@ -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",
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hydrooj/ui-default",
|
||||
"version": "4.8.6",
|
||||
"version": "4.8.7",
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "hydro.js",
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<span class="icon icon-edit"></span> {{ _('Edit Contest') }}
|
||||
</a></li>
|
||||
{% 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) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('contest_code', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export All Code') }}
|
||||
</a></li>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<span class="icon icon-edit"></span> {{ _('Edit Homework') }}
|
||||
</a></li>
|
||||
{% 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) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('homework_code', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export All Code') }}
|
||||
</a></li>
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
{% 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)) %}
|
||||
<div style="display: none" class="dialog__body--send-to">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
{% if handler.user.own(pdoc) or handler.user.hasPerm(perm.PERM_READ_PROBLEM_DATA) %}
|
||||
{% if handler.user.own(pdoc) or handler.user.hasPriv(PRIV.PRIV_READ_PROBLEM_DATA) or handler.user.hasPerm(perm.PERM_READ_PROBLEM_DATA) %}
|
||||
{{ nothing.render('No testdata at current.') }}
|
||||
{% else %}
|
||||
{{ nothing.render("You don't have permission to read testdata.")}}
|
||||
|
||||
Reference in new issue
Block a user