mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
讨论置顶功能,修复setup
This commit is contained in:
1 parent
32a6d2de13
commit
d184ca9ea1
20 files changed
+136
-173
No files matched your search
@@ -8,14 +8,13 @@ import {
|
||||
} from '../error';
|
||||
import { isContent, isTitle } from '../lib/validator';
|
||||
import paginate from '../lib/paginate';
|
||||
import { PERM, PRIV } from '../model/builtin';
|
||||
import { PERM, PRIV, CONSTANT } from '../model/builtin';
|
||||
import * as contest from '../model/contest';
|
||||
import * as document from '../model/document';
|
||||
import * as problem from '../model/problem';
|
||||
import * as record from '../model/record';
|
||||
import * as user from '../model/user';
|
||||
import * as message from '../model/message';
|
||||
import * as system from '../model/system';
|
||||
import {
|
||||
Route, Handler, Types, param,
|
||||
} from '../service/server';
|
||||
@@ -40,7 +39,7 @@ class ContestListHandler extends ContestHandler {
|
||||
qs = `rule=${rule}`;
|
||||
}
|
||||
// eslint-disable-next-line prefer-const
|
||||
[tdocs, tpcount] = await paginate(tdocs, page, await system.get('CONTEST_PER_PAGE'));
|
||||
[tdocs, tpcount] = await paginate(tdocs, page, CONSTANT.CONTEST_PER_PAGE);
|
||||
const tids = [];
|
||||
for (const tdoc of tdocs) tids.push(tdoc.docId);
|
||||
const tsdict = await contest.getListStatus(domainId, this.user._id, tids);
|
||||
|
||||
+39
-32
@@ -1,14 +1,15 @@
|
||||
import { ObjectID } from 'mongodb';
|
||||
import { isSafeInteger } from 'lodash';
|
||||
import { DiscussionNotFoundError, DocumentNotFoundError } from '../error';
|
||||
import { Drdoc, Mdoc } from '../interface';
|
||||
import {
|
||||
Mdoc, Drdoc, Ddoc, Drrdoc,
|
||||
} from '../interface';
|
||||
import paginate from '../lib/paginate';
|
||||
import * as system from '../model/system';
|
||||
import * as user from '../model/user';
|
||||
import * as message from '../model/message';
|
||||
import * as discussion from '../model/discussion';
|
||||
import * as document from '../model/document';
|
||||
import { PERM, PRIV } from '../model/builtin';
|
||||
import { PERM, PRIV, CONSTANT } from '../model/builtin';
|
||||
import {
|
||||
Route, Handler, Types, param,
|
||||
} from '../service/server';
|
||||
@@ -23,46 +24,45 @@ export const typeMapper = {
|
||||
};
|
||||
|
||||
class DiscussionHandler extends Handler {
|
||||
ddoc?: any;
|
||||
ddoc?: Ddoc;
|
||||
|
||||
drdoc?: any;
|
||||
drdoc?: Drdoc;
|
||||
|
||||
drrdoc?: any;
|
||||
drrdoc?: Drrdoc;
|
||||
|
||||
vnode?: any;
|
||||
|
||||
async _prepare({
|
||||
domainId, type, name, did, drid, drrid,
|
||||
}) {
|
||||
@param('type', Types.String, true)
|
||||
@param('name', Types.String, true)
|
||||
@param('did', Types.ObjectID, true)
|
||||
@param('drid', Types.ObjectID, true)
|
||||
@param('drrid', Types.ObjectID, true)
|
||||
async _prepare(
|
||||
domainId: string, type: string, name: string,
|
||||
did: ObjectID, drid: ObjectID, drrid: ObjectID,
|
||||
) {
|
||||
this.checkPerm(PERM.PERM_VIEW_DISCUSSION);
|
||||
if (did) {
|
||||
did = new ObjectID(did);
|
||||
this.ddoc = await discussion.get(domainId, did);
|
||||
if (!this.ddoc) throw new DiscussionNotFoundError(did);
|
||||
type = discussion.typeDisplay[this.ddoc.parentType];
|
||||
name = this.ddoc.parentId;
|
||||
if (drid) {
|
||||
drid = new ObjectID(drid);
|
||||
name = this.ddoc.parentId.toString();
|
||||
if (drrid) {
|
||||
[this.drdoc, this.drrdoc] = await discussion.getTailReply(domainId, drid, drrid);
|
||||
if (!this.drrdoc) throw new DiscussionNotFoundError(drrid);
|
||||
} else if (drid) {
|
||||
this.drdoc = await discussion.getReply(domainId, drid);
|
||||
if (!this.drdoc) throw new DiscussionNotFoundError(drid);
|
||||
if (!this.drdoc.parentId.equals(this.ddoc._id)) {
|
||||
throw new DocumentNotFoundError(drid);
|
||||
}
|
||||
if (drrid) {
|
||||
drrid = new ObjectID(drrid);
|
||||
[, this.drrdoc] = await discussion.getTailReply(domainId, drid, drrid);
|
||||
if (!this.drrdoc) throw new DiscussionNotFoundError(drrid);
|
||||
if (!this.drrdoc.parentId.equals(this.drdoc._id)) {
|
||||
throw new DocumentNotFoundError(drid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO(twd2): do more visibility check eg. contest
|
||||
// TODO(twd2): exclude problem/contest discussions?
|
||||
// TODO(iceboy): continuation based pagination.
|
||||
if (ObjectID.isValid(name.toString())) name = new ObjectID(name);
|
||||
this.vnode = await discussion.getVnode(domainId, typeMapper[type], name, this);
|
||||
this.vnode = await discussion.getVnode(domainId, typeMapper[type], name);
|
||||
if (this.vnode.hidden) this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
|
||||
if (this.ddoc) {
|
||||
this.ddoc.parentType = this.ddoc.parentType || this.vnode.type;
|
||||
this.ddoc.parentId = this.ddoc.parentId || this.vnode.id;
|
||||
@@ -76,7 +76,7 @@ class DiscussionMainHandler extends Handler {
|
||||
const [ddocs, dpcount] = await paginate(
|
||||
discussion.getMulti(domainId),
|
||||
page,
|
||||
await system.get('DISCUSSION_PER_PAGE'),
|
||||
CONSTANT.DISCUSSION_PER_PAGE,
|
||||
);
|
||||
const udict = await user.getList(domainId, ddocs.map((ddoc) => ddoc.owner));
|
||||
const path = [
|
||||
@@ -84,7 +84,9 @@ class DiscussionMainHandler extends Handler {
|
||||
['discussion_main', null],
|
||||
];
|
||||
const [vndict, vnodes] = await Promise.all([
|
||||
discussion.getListVnodes(domainId, ddocs, this),
|
||||
discussion.getListVnodes(
|
||||
domainId, ddocs, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN),
|
||||
),
|
||||
discussion.getNodes(domainId),
|
||||
]);
|
||||
this.response.template = 'discussion_main_or_node.html';
|
||||
@@ -106,7 +108,7 @@ class DiscussionNodeHandler extends DiscussionHandler {
|
||||
const [ddocs, dpcount] = await paginate(
|
||||
discussion.getMulti(domainId, { parentType: typeMapper[type], parentId: name }),
|
||||
page,
|
||||
await system.get('DISCUSSION_PER_PAGE'),
|
||||
CONSTANT.DISCUSSION_PER_PAGE,
|
||||
);
|
||||
const uids = ddocs.map((ddoc) => ddoc.owner);
|
||||
uids.push(this.vnode.owner);
|
||||
@@ -152,9 +154,10 @@ class DiscussionCreateHandler extends DiscussionHandler {
|
||||
@param('title', Types.String, isTitle)
|
||||
@param('content', Types.String, isContent)
|
||||
@param('highlight', Types.Boolean)
|
||||
@param('pin', Types.Boolean)
|
||||
async post(
|
||||
domainId: string, type: string, _name: string,
|
||||
title: string, content: string, highlight = false,
|
||||
title: string, content: string, highlight = false, pin = false,
|
||||
) {
|
||||
this.limitRate('add_discussion', 3600, 30);
|
||||
let name: ObjectID | string | number;
|
||||
@@ -162,9 +165,10 @@ class DiscussionCreateHandler extends DiscussionHandler {
|
||||
else if (isSafeInteger(parseInt(_name, 10))) name = parseInt(_name, 10);
|
||||
else name = _name;
|
||||
if (highlight) this.checkPerm(PERM.PERM_HIGHLIGHT_DISCUSSION);
|
||||
if (pin) this.checkPerm(PERM.PERM_PIN_DISCUSSION);
|
||||
const did = await discussion.add(
|
||||
domainId, typeMapper[type], name, this.user._id,
|
||||
title, content, this.request.ip, highlight,
|
||||
title, content, this.request.ip, highlight, pin,
|
||||
);
|
||||
this.response.body = { did };
|
||||
this.response.redirect = this.url('discussion_detail', { did });
|
||||
@@ -181,7 +185,7 @@ class DiscussionDetailHandler extends DiscussionHandler {
|
||||
const [drdocs, pcount, drcount] = await paginate(
|
||||
discussion.getMultiReply(domainId, did),
|
||||
page,
|
||||
await system.get('REPLY_PER_PAGE'),
|
||||
CONSTANT.REPLY_PER_PAGE,
|
||||
);
|
||||
const uids = drdocs.map((drdoc) => drdoc.owner);
|
||||
uids.push(this.ddoc.owner);
|
||||
@@ -327,13 +331,16 @@ class DiscussionEditHandler extends DiscussionHandler {
|
||||
@param('title', Types.String, isTitle)
|
||||
@param('content', Types.String, isContent)
|
||||
@param('highlight', Types.Boolean)
|
||||
@param('pin', Types.Boolean)
|
||||
async postUpdate(
|
||||
domainId: string, did: ObjectID, title: string, content: string, highlight = false,
|
||||
domainId: string, did: ObjectID, title: string, content: string,
|
||||
highlight = false, pin = false,
|
||||
) {
|
||||
if (this.ddoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_DISCUSSION);
|
||||
else this.checkPerm(PERM.PERM_EDIT_DISCUSSION_SELF);
|
||||
if (highlight && !this.ddoc.highlight) this.checkPerm(PERM.PERM_HIGHLIGHT_DISCUSSION);
|
||||
await discussion.edit(domainId, did, title, content, highlight);
|
||||
if (highlight !== this.ddoc.highlight) this.checkPerm(PERM.PERM_HIGHLIGHT_DISCUSSION);
|
||||
if (pin !== this.ddoc.pin) this.checkPerm(PERM.PERM_PIN_DISCUSSION);
|
||||
await discussion.edit(domainId, did, title, content, highlight, pin);
|
||||
this.response.body = { did };
|
||||
this.response.redirect = this.url('discussion_detail', { did });
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import * as domain from '../model/domain';
|
||||
import * as discussion from '../model/discussion';
|
||||
import * as token from '../model/token';
|
||||
import * as training from '../model/training';
|
||||
import { PERM, PRIV } from '../model/builtin';
|
||||
import { PERM, PRIV, CONSTANT } from '../model/builtin';
|
||||
import {
|
||||
isContent, isPassword, isEmail, isTitle,
|
||||
} from '../lib/validator';
|
||||
@@ -33,7 +33,7 @@ class HomeHandler extends Handler {
|
||||
if (this.user.hasPerm(PERM.PERM_VIEW_HOMEWORK)) {
|
||||
const tdocs = await contest.getMulti(domainId, {}, document.TYPE_HOMEWORK)
|
||||
.sort('beginAt', -1)
|
||||
.limit(await system.get('HOMEWORK_ON_MAIN'))
|
||||
.limit(CONSTANT.HOMEWORK_ON_MAIN)
|
||||
.toArray();
|
||||
const tsdict = await contest.getListStatus(
|
||||
domainId, this.user._id,
|
||||
@@ -48,7 +48,7 @@ class HomeHandler extends Handler {
|
||||
if (this.user.hasPerm(PERM.PERM_VIEW_CONTEST)) {
|
||||
const tdocs = await contest.getMulti(domainId)
|
||||
.sort('beginAt', -1)
|
||||
.limit(await system.get('CONTEST_ON_MAIN'))
|
||||
.limit(CONSTANT.CONTEST_ON_MAIN)
|
||||
.toArray();
|
||||
const tsdict = await contest.getListStatus(
|
||||
domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId),
|
||||
@@ -62,7 +62,7 @@ class HomeHandler extends Handler {
|
||||
if (this.user.hasPerm(PERM.PERM_VIEW_TRAINING)) {
|
||||
const tdocs = await training.getMulti(domainId)
|
||||
.sort('_id', 1)
|
||||
.limit(await system.get('TRAINING_ON_MAIN'))
|
||||
.limit(CONSTANT.TRAINING_ON_MAIN)
|
||||
.toArray();
|
||||
const tsdict = await training.getListStatus(
|
||||
domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId),
|
||||
@@ -75,9 +75,11 @@ class HomeHandler extends Handler {
|
||||
async discussion(domainId: string): Promise<[any[], any]> {
|
||||
if (this.user.hasPerm(PERM.PERM_VIEW_DISCUSSION)) {
|
||||
const ddocs = await discussion.getMulti(domainId)
|
||||
.limit(await system.get('DISCUSSION_ON_MAIN'))
|
||||
.limit(CONSTANT.DISCUSSION_ON_MAIN)
|
||||
.toArray();
|
||||
const vndict = await discussion.getListVnodes(domainId, ddocs, this);
|
||||
const vndict = await discussion.getListVnodes(
|
||||
domainId, ddocs, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN),
|
||||
);
|
||||
return [ddocs, vndict];
|
||||
}
|
||||
return [[], {}];
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
Route, Handler, Types, param,
|
||||
} from '../service/server';
|
||||
import * as bus from '../service/bus';
|
||||
import { PERM } from '../model/builtin';
|
||||
import * as system from '../model/system';
|
||||
import { PERM, CONSTANT } from '../model/builtin';
|
||||
import * as user from '../model/user';
|
||||
import * as contest from '../model/contest';
|
||||
import * as discussion from '../model/discussion';
|
||||
@@ -84,7 +83,7 @@ class HomeworkDetailHandler extends HomeworkHandler {
|
||||
const [ddocs, dpcount, dcount] = await paginate(
|
||||
discussion.getMulti(domainId, { parentType: tdoc.docType, parentId: tdoc.docId }),
|
||||
page,
|
||||
await system.get('DISCUSSION_PER_PAGE'),
|
||||
CONSTANT.DISCUSSION_PER_PAGE,
|
||||
);
|
||||
const uids = ddocs.map((ddoc) => ddoc.owner);
|
||||
uids.push(tdoc.owner);
|
||||
|
||||
@@ -102,34 +102,6 @@ class SwitchLanguageHandler extends Handler {
|
||||
}
|
||||
}
|
||||
|
||||
class UiSettingsHandler extends Handler {
|
||||
async get() {
|
||||
const [
|
||||
header_logo, header_logo_2x,
|
||||
nav_logo_dark, nav_logo_light,
|
||||
nav_logo_dark_2x, nav_logo_light_2x,
|
||||
header_background, header_background_2x,
|
||||
] = await system.getMany([
|
||||
'ui.header_logo', 'ui.header_logo_2x',
|
||||
'ui.nav_logo_dark', 'ui.nav_logo_light',
|
||||
'ui.nav_logo_dark_2x', 'ui.nav_logo_light_2x',
|
||||
'ui.header_background', 'ui.header_background2x',
|
||||
]);
|
||||
this.response.body = await this.renderHTML('extra.css', {
|
||||
header_logo,
|
||||
header_logo_2x,
|
||||
nav_logo_dark,
|
||||
nav_logo_light,
|
||||
nav_logo_dark_2x,
|
||||
nav_logo_light_2x,
|
||||
header_background,
|
||||
header_background_2x,
|
||||
});
|
||||
this.response.type = 'text/css';
|
||||
this.ctx.set('nolog', '1');
|
||||
}
|
||||
}
|
||||
|
||||
export async function apply() {
|
||||
Route('file_download', '/fs/:fileId/:secret', FileDownloadHandler);
|
||||
Route('file_download_with_name', '/fs/:fileId/:name/:secret', FileDownloadHandler);
|
||||
@@ -137,7 +109,6 @@ export async function apply() {
|
||||
Route('status', '/status', StatusHandler);
|
||||
Route('status_update', '/status/update', StatusUpdateHandler);
|
||||
Route('switch_language', '/language/:lang', SwitchLanguageHandler);
|
||||
Route('ui', '/extra.css', UiSettingsHandler);
|
||||
}
|
||||
|
||||
global.Hydro.handler.misc = apply;
|
||||
@@ -19,8 +19,7 @@ import * as record from '../model/record';
|
||||
import * as domain from '../model/domain';
|
||||
import * as user from '../model/user';
|
||||
import * as solution from '../model/solution';
|
||||
import * as system from '../model/system';
|
||||
import { PERM, PRIV } from '../model/builtin';
|
||||
import { PERM, PRIV, CONSTANT } from '../model/builtin';
|
||||
import * as bus from '../service/bus';
|
||||
import {
|
||||
Route, Connection, Handler, ConnectionHandler, Types, param, multipart,
|
||||
@@ -78,7 +77,7 @@ class ProblemMainHandler extends ProblemHandler {
|
||||
const [pdocs, ppcount, pcount] = await paginate(
|
||||
problem.getMulti(domainId, query).sort({ pid: 1 }),
|
||||
page,
|
||||
await system.get('PROBLEM_PER_PAGE'),
|
||||
CONSTANT.PROBLEM_PER_PAGE,
|
||||
);
|
||||
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
|
||||
psdict = await problem.getListStatus(
|
||||
@@ -122,7 +121,7 @@ class ProblemCategoryHandler extends ProblemHandler {
|
||||
const [pdocs, ppcount, pcount] = await paginate(
|
||||
problem.getMulti(domainId, q).sort({ pid: 1 }),
|
||||
page,
|
||||
await system.get('PROBLEM_PER_PAGE'),
|
||||
CONSTANT.PROBLEM_PER_PAGE,
|
||||
);
|
||||
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
|
||||
psdict = await problem.getListStatus(
|
||||
@@ -466,7 +465,7 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
|
||||
const [psdocs, pcount, pscount] = await paginate(
|
||||
solution.getMulti(domainId, this.pdoc.docId),
|
||||
page,
|
||||
await system.get('SOLUTION_PER_PAGE'),
|
||||
CONSTANT.SOLUTION_PER_PAGE,
|
||||
);
|
||||
const uids = [this.pdoc.owner];
|
||||
const docids = [];
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { ObjectID } from 'mongodb';
|
||||
import { PermissionError, RecordNotFoundError } from '../error';
|
||||
import { PERM } from '../model/builtin';
|
||||
import { PERM, CONSTANT } from '../model/builtin';
|
||||
import * as problem from '../model/problem';
|
||||
import * as record from '../model/record';
|
||||
import * as contest from '../model/contest';
|
||||
import * as system from '../model/system';
|
||||
import * as user from '../model/user';
|
||||
import paginate from '../lib/paginate';
|
||||
import * as bus from '../service/bus';
|
||||
@@ -34,7 +33,7 @@ class RecordListHandler extends RecordHandler {
|
||||
const [rdocs] = await paginate(
|
||||
record.getMulti(domainId, q).sort('_id', -1),
|
||||
page,
|
||||
await system.get('RECORD_PER_PAGE'),
|
||||
CONSTANT.RECORD_PER_PAGE,
|
||||
);
|
||||
const canViewProblemHidden = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
|
||||
const [udict, pdict] = await Promise.all([
|
||||
|
||||
@@ -3,12 +3,11 @@ import { ObjectID } from 'mongodb';
|
||||
import { ValidationError, ProblemNotFoundError } from '../error';
|
||||
import { isTitle, isContent, isDescription } from '../lib/validator';
|
||||
import paginate from '../lib/paginate';
|
||||
import { PERM, PRIV } from '../model/builtin';
|
||||
import { PERM, PRIV, CONSTANT } from '../model/builtin';
|
||||
import * as problem from '../model/problem';
|
||||
import * as builtin from '../model/builtin';
|
||||
import * as training from '../model/training';
|
||||
import * as user from '../model/user';
|
||||
import * as system from '../model/system';
|
||||
import {
|
||||
Route, Handler, Types, param,
|
||||
} from '../service/server';
|
||||
@@ -58,9 +57,9 @@ class TrainingMainHandler extends Handler {
|
||||
@param('page', Types.UnsignedInt, true)
|
||||
async get(domainId: string, page = 1) {
|
||||
const [tdocs, tpcount] = await paginate(
|
||||
training.getMulti(domainId).sort('_id', 1),
|
||||
training.getMulti(domainId),
|
||||
page,
|
||||
await system.get('TRAINING_PER_PAGE'),
|
||||
CONSTANT.TRAINING_PER_PAGE,
|
||||
);
|
||||
const tids: Set<ObjectID> = new Set();
|
||||
for (const tdoc of tdocs) tids.add(tdoc.docId);
|
||||
|
||||
Reference in new issue
Block a user