Hello Typescript!

This commit is contained in:
undefined committed 2020-07-07 19:58:21 +08:00
1 parent c9b6412527
commit ba03d7a7bf
98 files changed
+3186 -2616

No files matched your search

@@ -1,27 +1,19 @@
const moment = require('moment-timezone');
const { ObjectID } = require('mongodb');
const AdmZip = require('adm-zip');
const {
import moment from 'moment-timezone';
import { ObjectID } from 'mongodb';
import AdmZip from 'adm-zip';
import {
ContestNotLiveError, ValidationError, ProblemNotFoundError,
ContestNotAttendedError,
} = require('../error');
const paginate = require('../lib/paginate');
const {
PERM: {
PERM_CREATE_CONTEST, PERM_EDIT_CONTEST, PERM_READ_RECORD_CODE,
PERM_VIEW_CONTEST, PERM_EDIT_CONTEST_SELF,
},
PRIV: {
PRIV_READ_RECORD_CODE,
},
} = require('../model/builtin');
const contest = require('../model/contest');
const document = require('../model/document');
const problem = require('../model/problem');
const record = require('../model/record');
const user = require('../model/user');
const system = require('../model/system');
const { Route, Handler } = require('../service/server');
} from '../error';
import paginate from '../lib/paginate';
import { PERM, PRIV } 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 system from '../model/system';
import { Route, Handler } from '../service/server';
const ContestHandler = contest.ContestHandlerMixin(Handler);
@@ -35,7 +27,7 @@ class ContestListHandler extends ContestHandler {
tdocs = contest.getMulti(domainId).sort({ beginAt: -1 });
qs = '';
} else {
if (!contest.CONTEST_RULES.includes(rule)) throw new ValidationError('rule');
if (!contest.RULES[rule]) throw new ValidationError('rule');
tdocs = contest.getMulti(domainId, { rule }).sort({ beginAt: -1 });
qs = 'rule={0}'.format(rule);
}
@@ -127,8 +119,8 @@ class ContestScoreboardDownloadHandler extends ContestDetailHandler {
class ContestEditHandler extends ContestDetailHandler {
async prepare() {
if (this.tdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_CONTEST);
else this.checkPerm(PERM_EDIT_CONTEST_SELF);
if (this.tdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_CONTEST);
else this.checkPerm(PERM.PERM_EDIT_CONTEST_SELF);
}
async get() {
@@ -160,20 +152,20 @@ class ContestEditHandler extends ContestDetailHandler {
async post({
domainId, beginAtDate, beginAtTime, duration, title, content, rule, pids, rated = false,
}) {
let beginAt = moment.tz(`${beginAtDate} ${beginAtTime}`, this.user.timeZone);
if (!beginAt.isValid()) {
const beginAtMoment = moment.tz(`${beginAtDate} ${beginAtTime}`, this.user.timeZone);
if (!beginAtMoment.isValid()) {
throw new ValidationError('beginAtDate', 'beginAtTime');
}
const endAt = beginAt.clone().add(duration, 'hours').toDate();
if (beginAt.isSameOrAfter(endAt)) throw new ValidationError('duration');
beginAt = beginAt.toDate();
const endAt = beginAtMoment.clone().add(duration, 'hours').toDate();
if (beginAtMoment.isSameOrAfter(endAt)) throw new ValidationError('duration');
const beginAt = beginAtMoment.toDate();
pids = await this.verifyProblems(domainId, pids);
await contest.edit(domainId, this.tdoc.docId, {
title, content, rule, beginAt, endAt, pids, rated,
});
if (this.tdoc.beginAt !== beginAt || this.tdoc.endAt !== endAt
|| Array.isDiff(this.tdoc.pids, pids) || this.tdoc.rule !== rule) {
await contest.recalcStatus(this.tdoc.docId);
await contest.recalcStatus(domainId, this.tdoc.docId);
}
this.response.body = { tid: this.tdoc.docId };
this.response.redirect = this.url('contest_detail', { tid: this.tdoc.docId });
@@ -201,6 +193,7 @@ class ContestProblemHandler extends ContestDetailHandler {
}
}
// @ts-ignore
async get({ tid }) {
const path = [
['Hydro', 'homepage'],
@@ -272,7 +265,9 @@ class ContestProblemSubmitHandler extends ContestProblemHandler {
class ContestCodeHandler extends ContestDetailHandler {
async get({ domainId, tid }) {
if (!this.user.hasPriv(PRIV_READ_RECORD_CODE)) this.checkPerm(PERM_READ_RECORD_CODE);
if (!this.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE)) {
this.checkPerm(PERM.PERM_READ_RECORD_CODE);
}
this.limitRate('homework_code', 3600, 60);
const [tdoc, tsdocs] = await contest.getAndListStatus(domainId, tid);
const rnames = {};
@@ -329,23 +324,23 @@ class ContestCreateHandler extends ContestHandler {
pids = await this.verifyProblems(domainId, pids);
const tid = await contest.add(
domainId, title, content,
this.user._id, rule, beginAt, endAt, pids, rated,
this.user._id, rule, beginAt.toDate(), endAt.toDate(), pids, rated,
);
this.response.body = { tid };
this.response.redirect = this.url('contest_detail', { tid });
}
}
async function apply() {
Route('contest_main', '/contest', ContestListHandler, PERM_VIEW_CONTEST);
Route('contest_detail', '/contest/:tid', ContestDetailHandler, PERM_VIEW_CONTEST);
Route('contest_edit', '/contest/:tid/edit', ContestEditHandler, PERM_VIEW_CONTEST);
Route('contest_scoreboard', '/contest/:tid/scoreboard', ContestScoreboardHandler, PERM_VIEW_CONTEST);
Route('contest_scoreboard_download', '/contest/:tid/export/:ext', ContestScoreboardDownloadHandler, PERM_VIEW_CONTEST);
Route('contest_detail_problem', '/contest/:tid/p/:pid', ContestProblemHandler, PERM_VIEW_CONTEST);
Route('contest_detail_problem_submit', '/contest/:tid/p/:pid/submit', ContestProblemSubmitHandler, PERM_VIEW_CONTEST);
Route('contest_code', '/contest/:tid/code', ContestCodeHandler, PERM_VIEW_CONTEST);
Route('contest_create', '/contest/create', ContestCreateHandler, PERM_CREATE_CONTEST);
export async function apply() {
Route('contest_main', '/contest', ContestListHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_detail', '/contest/:tid', ContestDetailHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_edit', '/contest/:tid/edit', ContestEditHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_scoreboard', '/contest/:tid/scoreboard', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_scoreboard_download', '/contest/:tid/export/:ext', ContestScoreboardDownloadHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_detail_problem', '/contest/:tid/p/:pid', ContestProblemHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_detail_problem_submit', '/contest/:tid/p/:pid/submit', ContestProblemSubmitHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_code', '/contest/:tid/code', ContestCodeHandler, PERM.PERM_VIEW_CONTEST);
Route('contest_create', '/contest/create', ContestCreateHandler, PERM.PERM_CREATE_CONTEST);
}
global.Hydro.handler.contest = module.exports = apply;
global.Hydro.handler.contest = apply;
@@ -1,23 +1,14 @@
const { ObjectID } = require('mongodb');
const paginate = require('../lib/paginate');
const system = require('../model/system');
const user = require('../model/user');
const discussion = require('../model/discussion');
const document = require('../model/document');
const {
PERM: {
PERM_VIEW_DISCUSSION, PERM_EDIT_DISCUSSION, PERM_EDIT_DISCUSSION_REPLY,
PERM_DELETE_DISCUSSION, PERM_DELETE_DISCUSSION_REPLY, PERM_HIGHLIGHT_DISCUSSION,
PERM_CREATE_DISCUSSION, PERM_REPLY_DISCUSSION,
},
PRIV: {
PRIV_USER_PROFILE,
},
} = require('../model/builtin');
const { Route, Handler } = require('../service/server');
const { DiscussionNotFoundError, DocumentNotFoundError } = require('../error');
import { ObjectID } from 'mongodb';
import { DiscussionNotFoundError, DocumentNotFoundError } from '../error';
import paginate from '../lib/paginate';
import * as system from '../model/system';
import * as user from '../model/user';
import * as discussion from '../model/discussion';
import * as document from '../model/document';
import { PERM, PRIV } from '../model/builtin';
import { Route, Handler } from '../service/server';
const typeMapper = {
export const typeMapper = {
problem: document.TYPE_PROBLEM,
contest: document.TYPE_CONTEST,
node: document.TYPE_DISCUSSION_NODE,
@@ -29,7 +20,7 @@ class DiscussionHandler extends Handler {
async _prepare({
domainId, type, name, did, drid, drrid,
}) {
this.checkPerm(PERM_VIEW_DISCUSSION);
this.checkPerm(PERM.PERM_VIEW_DISCUSSION);
if (did) {
this.ddoc = await discussion.get(domainId, did);
if (!this.ddoc) throw new DiscussionNotFoundError(did);
@@ -124,8 +115,8 @@ class DiscussionNodeHandler extends DiscussionHandler {
class DiscussionCreateHandler extends DiscussionHandler {
async prepare() {
this.checkPriv(PRIV_USER_PROFILE);
this.checkPerm(PERM_CREATE_DISCUSSION);
this.checkPriv(PRIV.PRIV_USER_PROFILE);
this.checkPerm(PERM.PERM_CREATE_DISCUSSION);
}
async get({ type, name }) {
@@ -144,7 +135,7 @@ class DiscussionCreateHandler extends DiscussionHandler {
}) {
this.limitRate('add_discussion', 3600, 30);
if (ObjectID.isValid(name)) name = new ObjectID(name);
if (highlight) this.checkPerm(PERM_HIGHLIGHT_DISCUSSION);
if (highlight) this.checkPerm(PERM.PERM_HIGHLIGHT_DISCUSSION);
const did = await discussion.add(
domainId, typeMapper[type], name, this.user._id,
title, content, this.request.ip, highlight,
@@ -156,7 +147,7 @@ class DiscussionCreateHandler extends DiscussionHandler {
class DiscussionDetailHandler extends DiscussionHandler {
async get({ domainId, did, page = 1 }) {
const dsdoc = this.user.hasPriv(PRIV_USER_PROFILE)
const dsdoc = this.user.hasPriv(PRIV.PRIV_USER_PROFILE)
? await discussion.getStatus(domainId, did, this.user._id)
: null;
const [drdocs, pcount, drcount] = await paginate(
@@ -187,31 +178,31 @@ class DiscussionDetailHandler extends DiscussionHandler {
}
async post() {
this.checkPriv(PRIV_USER_PROFILE);
this.checkPriv(PRIV.PRIV_USER_PROFILE);
}
async postReply({ domainId, did, content }) {
this.checkPerm(PERM_REPLY_DISCUSSION);
this.checkPerm(PERM.PERM_REPLY_DISCUSSION);
this.limitRate('add_discussion', 3600, 30);
await discussion.addReply(domainId, did, this.user._id, content, this.request.ip);
this.back();
}
async postTailReply({ domainId, drid, content }) {
this.checkPerm(PERM_REPLY_DISCUSSION);
this.checkPerm(PERM.PERM_REPLY_DISCUSSION);
this.limitRate('add_discussion', 3600, 30);
await discussion.addTailReply(domainId, drid, this.user._id, content, this.request.ip);
this.back();
}
async postEditReply({ domainId, drid, content }) {
if (this.drdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_DISCUSSION_REPLY);
if (this.drdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_DISCUSSION_REPLY);
await discussion.editReply(domainId, drid, content);
this.back();
}
async postDeleteReply({ domainId, drid }) {
if (this.drdoc.owner !== this.user._id) this.checkPerm(PERM_DELETE_DISCUSSION_REPLY);
if (this.drdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_DELETE_DISCUSSION_REPLY);
await discussion.delReply(domainId, drid);
this.back();
}
@@ -219,13 +210,13 @@ class DiscussionDetailHandler extends DiscussionHandler {
async postEditTailReply({
domainId, drid, drrid, content,
}) {
if (this.drdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_DISCUSSION_REPLY);
if (this.drdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_DISCUSSION_REPLY);
await discussion.editTailReply(domainId, drid, drrid, content);
this.back();
}
async postDeleteTailReply({ domainId, drid, drrid }) {
if (this.drrdoc.owner !== this.user._id) this.checkPerm(PERM_DELETE_DISCUSSION_REPLY);
if (this.drrdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_DELETE_DISCUSSION_REPLY);
await discussion.delTailReply(domainId, drid, drrid);
this.back();
}
@@ -278,15 +269,15 @@ class DiscussionEditHandler extends DiscussionHandler {
async postUpdate({
domainId, did, title, content, highlight,
}) {
if (this.ddoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_DISCUSSION);
if (highlight && !this.ddoc.highlight) this.checkPerm(PERM_HIGHLIGHT_DISCUSSION);
if (this.ddoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_DISCUSSION);
if (highlight && !this.ddoc.highlight) this.checkPerm(PERM.PERM_HIGHLIGHT_DISCUSSION);
await discussion.edit(domainId, did, title, content, highlight);
this.response.body = { did };
this.response.redirect = this.url('discussion_detail', { did });
}
async postDelete({ domainId, did }) {
if (this.ddoc.owner !== this.user._id) this.checkPerm(PERM_DELETE_DISCUSSION);
if (this.ddoc.owner !== this.user._id) this.checkPerm(PERM.PERM_DELETE_DISCUSSION);
await discussion.del(domainId, did);
this.response.body = { type: this.ddoc.parentType, parent: this.ddoc.parentId };
this.response.redirect = this.url('discussion_node', {
@@ -296,7 +287,7 @@ class DiscussionEditHandler extends DiscussionHandler {
}
}
async function apply() {
export async function apply() {
Route('discussion_main', '/discuss', DiscussionMainHandler);
Route('discussion_detail', '/discuss/:did', DiscussionDetailHandler);
Route('discussion_edit', '/discuss/:did/edit', DiscussionEditHandler);
@@ -307,4 +298,4 @@ async function apply() {
Route('discussion_create', '/discuss/:type/:name/create', DiscussionCreateHandler);
}
global.Hydro.handler.discussion = module.exports = apply;
global.Hydro.handler.discussion = apply;
@@ -1,11 +1,11 @@
const user = require('../model/user');
const domain = require('../model/domain');
const system = require('../model/system');
const { DOMAIN_SETTINGS, DOMAIN_SETTINGS_BY_KEY } = require('../model/setting');
const { PERM: { PERM_EDIT_DOMAIN }, PERMS_BY_FAMILY } = require('../model/builtin');
const paginate = require('../lib/paginate');
const { Route, Handler } = require('../service/server');
const { RoleAlreadyExistError, ValidationError, PermissionError } = require('../error');
import { RoleAlreadyExistError, ValidationError, PermissionError } from '../error';
import * as user from '../model/user';
import * as domain from '../model/domain';
import * as system from '../model/system';
import { DOMAIN_SETTINGS, DOMAIN_SETTINGS_BY_KEY } from '../model/setting';
import { PERM, PERMS_BY_FAMILY } from '../model/builtin';
import paginate from '../lib/paginate';
import { Route, Handler } from '../service/server';
class DomainRankHandler extends Handler {
async get({ domainId, page = 1 }) {
@@ -55,7 +55,7 @@ class DomainCreateHandler extends Handler {
class ManageHandler extends Handler {
async prepare({ domainId }) {
this.checkPerm(PERM_EDIT_DOMAIN);
this.checkPerm(PERM.PERM_EDIT_DOMAIN);
this.domain = await domain.get(domainId);
}
}
@@ -178,18 +178,18 @@ class DomainRoleHandler extends ManageHandler {
this.back();
}
async postDelete({ roles }) {
async postDelete({ domainId, roles }) {
for (const role of roles) {
if (['root', 'default', 'guest'].includes(role)) {
throw new ValidationError('role');
}
}
await user.deleteRoles(roles);
await user.deleteRoles(domainId, roles);
this.back();
}
}
async function apply() {
export async function apply() {
Route('ranking', '/ranking', DomainRankHandler);
Route('domain_create', '/domain/create', DomainCreateHandler);
Route('domain_dashboard', '/domain/dashboard', DomainDashboardHandler);
@@ -199,4 +199,4 @@ async function apply() {
Route('domain_role', '/domain/role', DomainRoleHandler);
}
global.Hydro.handler.domain = module.exports = apply;
global.Hydro.handler.domain = apply;
+41 -49
View File
@@ -1,40 +1,32 @@
const fs = require('fs');
const {
import fs from 'fs';
import {
VerifyPasswordError, UserAlreadyExistError, InvalidTokenError,
NotFoundError,
} = require('../error');
const bus = require('../service/bus');
const {
} from '../error';
import * as bus from '../service/bus';
import {
Route, Connection, Handler, ConnectionHandler,
} = require('../service/server');
const misc = require('../lib/misc');
const md5 = require('../lib/md5');
const contest = require('../model/contest');
const message = require('../model/message');
const document = require('../model/document');
const system = require('../model/system');
const user = require('../model/user');
const file = require('../model/file');
const setting = require('../model/setting');
const domain = require('../model/domain');
const discussion = require('../model/discussion');
const token = require('../model/token');
const training = require('../model/training');
const {
PERM: {
PERM_VIEW_TRAINING, PERM_VIEW_CONTEST, PERM_VIEW_DISCUSSION,
PERM_VIEW_HOMEWORK,
},
PRIV: {
PRIV_USER_PROFILE, PRIV_DELETE_FILE, PRIV_DELETE_FILE_SELF,
},
} = require('../model/builtin');
} from '../service/server';
import * as misc from '../lib/misc';
import md5 from '../lib/md5';
import * as contest from '../model/contest';
import * as message from '../model/message';
import * as document from '../model/document';
import * as system from '../model/system';
import * as user from '../model/user';
import * as file from '../model/file';
import * as setting from '../model/setting';
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';
const { geoip, useragent } = global.Hydro.lib;
class HomeHandler extends Handler {
async homework(domainId) {
if (this.user.hasPerm(PERM_VIEW_HOMEWORK)) {
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'))
@@ -49,7 +41,7 @@ class HomeHandler extends Handler {
}
async contest(domainId) {
if (this.user.hasPerm(PERM_VIEW_CONTEST)) {
if (this.user.hasPerm(PERM.PERM_VIEW_CONTEST)) {
const tdocs = await contest.getMulti(domainId)
.sort('beginAt', -1)
.limit(await system.get('CONTESTS_ON_MAIN'))
@@ -63,7 +55,7 @@ class HomeHandler extends Handler {
}
async training(domainId) {
if (this.user.hasPerm(PERM_VIEW_TRAINING)) {
if (this.user.hasPerm(PERM.PERM_VIEW_TRAINING)) {
const tdocs = await training.getMulti(domainId)
.sort('_id', 1)
.limit(await system.get('TRAININGS_ON_MAIN'))
@@ -76,8 +68,8 @@ class HomeHandler extends Handler {
return [[], {}];
}
async discussion(domainId) {
if (this.user.hasPerm(PERM_VIEW_DISCUSSION)) {
async discussion(domainId): Promise<[any[], any]> {
if (this.user.hasPerm(PERM.PERM_VIEW_DISCUSSION)) {
const ddocs = await discussion.getMulti(domainId)
.limit(await system.get('DISCUSSIONS_ON_MAIN'))
.toArray();
@@ -147,10 +139,10 @@ class HomeSecurityHandler extends Handler {
this.back();
}
async postChangeMail({ currentPassword, mail }) {
async postChangeMail({ domainId, currentPassword, mail }) {
this.limitRate('send_mail', 3600, 30);
this.user.checkPassword(currentPassword);
const udoc = await user.getByMail(mail);
const udoc = await user.getByEmail(domainId, mail, true);
if (udoc) throw new UserAlreadyExistError(mail);
const [code] = await token.add(
token.TYPE_CHANGEMAIL,
@@ -216,12 +208,12 @@ class HomeSettingsHandler extends Handler {
}
class UserChangemailWithCodeHandler extends Handler {
async get({ code }) {
async get({ domainId, code }) {
const tdoc = await token.get(code, token.TYPE_CHANGEMAIL);
if (!tdoc || tdoc.uid !== this.user._id) {
throw new InvalidTokenError(code);
}
const udoc = await user.getByEmail(tdoc.mail);
const udoc = await user.getByEmail(domainId, tdoc.mail, true);
if (udoc) throw new UserAlreadyExistError(tdoc.mail);
await Promise.all([
user.setEmail(this.user._id, tdoc.mail),
@@ -271,7 +263,7 @@ class HomeMessagesHandler extends Handler {
}
async postDeleteMessage({ messageId }) {
await message.delete(messageId, this.user._id);
await message.del(messageId);
this.back();
}
}
@@ -293,29 +285,29 @@ class HomeMessagesConnectionHandler extends ConnectionHandler {
class HomeFileHandler extends Handler {
async get() {
const ufdocs = await file.getMulti({ owner: this.user._id }).toArray();
const fdict = await fs.getMetaDict(ufdocs.map((ufdoc) => ufdoc._id));
const fdict = await file.getMetaDict(ufdocs.map((ufdoc) => ufdoc._id));
this.response.template = 'home_file.html';
this.response.body = { ufdocs, fdict };
}
async postDelete(ufid) {
const ufdoc = await file.get(ufid);
if (ufdoc.owner !== this.user._id) this.checkPriv(PRIV_DELETE_FILE);
else this.checkPriv(PRIV_DELETE_FILE_SELF);
const ufdoc = await file.getMeta(ufid);
if (ufdoc.owner !== this.user._id) this.checkPriv(PRIV.PRIV_DELETE_FILE);
else this.checkPriv(PRIV.PRIV_DELETE_FILE_SELF);
const result = await file.del(ufdoc._id);
if (result) await file.decUsage(this.user._id, ufdoc.length);
if (result) await user.inc(this.user._id, 'usage', ufdoc.length);
this.back();
}
}
async function apply() {
Route('homepage', '/', HomeHandler);
Route('home_security', '/home/security', HomeSecurityHandler, PRIV_USER_PROFILE);
Route('user_changemail_with_code', '/home/changeMail/:code', UserChangemailWithCodeHandler, PRIV_USER_PROFILE);
Route('home_settings', '/home/settings/:category', HomeSettingsHandler, PRIV_USER_PROFILE);
Route('home_messages', '/home/messages', HomeMessagesHandler, PRIV_USER_PROFILE);
Route('home_file', '/home/file', HomeFileHandler, PRIV_USER_PROFILE);
Connection('home_messages_conn', '/home/messages-conn', HomeMessagesConnectionHandler, PRIV_USER_PROFILE);
Route('home_security', '/home/security', HomeSecurityHandler, PRIV.PRIV_USER_PROFILE);
Route('user_changemail_with_code', '/home/changeMail/:code', UserChangemailWithCodeHandler, PRIV.PRIV_USER_PROFILE);
Route('home_settings', '/home/settings/:category', HomeSettingsHandler, PRIV.PRIV_USER_PROFILE);
Route('home_messages', '/home/messages', HomeMessagesHandler, PRIV.PRIV_USER_PROFILE);
Route('home_file', '/home/file', HomeFileHandler, PRIV.PRIV_USER_PROFILE);
Connection('home_messages_conn', '/home/messages-conn', HomeMessagesConnectionHandler, PRIV.PRIV_USER_PROFILE);
}
global.Hydro.handler.home = module.exports = apply;
@@ -1,27 +1,21 @@
const yaml = require('js-yaml');
const moment = require('moment-timezone');
const { ObjectID } = require('mongodb');
const AdmZip = require('adm-zip');
const {
import yaml from 'js-yaml';
import moment from 'moment-timezone';
import { ObjectID } from 'mongodb';
import AdmZip from 'adm-zip';
import {
ValidationError, HomeworkNotLiveError, ProblemNotFoundError,
HomeworkNotAttendedError,
} = require('../error');
const { Route, Handler } = require('../service/server');
const {
PERM_VIEW_HOMEWORK, PERM_ATTEND_HOMEWORK, PERM_VIEW_PROBLEM,
PERM_SUBMIT_PROBLEM, PERM_CREATE_HOMEWORK, PERM_EDIT_HOMEWORK,
PERM_VIEW_HOMEWORK_SCOREBOARD, PERM_READ_RECORD_CODE,
} = require('../model/builtin').PERM;
const system = require('../model/system');
const user = require('../model/user');
const contest = require('../model/contest');
const discussion = require('../model/discussion');
const problem = require('../model/problem');
const record = require('../model/record');
const document = require('../model/document');
const paginate = require('../lib/paginate');
const misc = require('../lib/misc');
const ranked = require('../lib/rank');
} from '../error';
import { Route, Handler } from '../service/server';
import { PERM } from '../model/builtin';
import * as system from '../model/system';
import * as user from '../model/user';
import * as contest from '../model/contest';
import * as discussion from '../model/discussion';
import * as problem from '../model/problem';
import * as record from '../model/record';
import * as document from '../model/document';
import paginate from '../lib/paginate';
const HomeworkHandler = contest.ContestHandlerMixin(Handler);
@@ -31,7 +25,7 @@ class HomeworkMainHandler extends HomeworkHandler {
const calendar = [];
for (const tdoc of tdocs) {
const cal = { ...tdoc, url: `/homework/${tdoc.docId}` };
if (contest.isHomeworkExtended(tdoc) || contest.isDone(tdoc)) {
if (contest.isExtended(tdoc) || contest.isDone(tdoc)) {
cal.endAt = tdoc.endAt;
cal.penaltySince = tdoc.penaltySince;
} else {
@@ -93,7 +87,7 @@ class HomeworkDetailHandler extends HomeworkHandler {
}
async postAttend({ domainId, tid }) {
this.checkPerm(PERM_ATTEND_HOMEWORK);
this.checkPerm(PERM.PERM_ATTEND_HOMEWORK);
const tdoc = await contest.get(domainId, tid, document.TYPE_HOMEWORK);
if (contest.isDone(tdoc)) throw new HomeworkNotLiveError(tdoc.docId);
await contest.attend(domainId, tdoc.docId, this.user._id, document.TYPE_HOMEWORK);
@@ -103,7 +97,7 @@ class HomeworkDetailHandler extends HomeworkHandler {
class HomeworkDetailProblemHandler extends HomeworkHandler {
async prepare({ domainId, tid, pid }) {
this.checkPerm(PERM_VIEW_PROBLEM);
this.checkPerm(PERM.PERM_VIEW_PROBLEM);
[this.tdoc, this.pdoc, this.tsdoc] = await Promise.all([
contest.get(domainId, tid, document.TYPE_HOMEWORK),
problem.get(domainId, pid, this.user._id),
@@ -121,7 +115,7 @@ class HomeworkDetailProblemHandler extends HomeworkHandler {
if (!this.tdoc.pids.includes(pid)) throw new ProblemNotFoundError(domainId, pid, tid);
const path = [
['Hydro', 'homepage'],
['homework_main', '/homework'],
['homework_main', 'homework_main'],
[this.tdoc.title, 'homework_detail', { tid }, true],
[this.pdoc.title, null, null, true],
];
@@ -170,8 +164,8 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler {
await contest.updateStatus(domainId, tid, this.user._id,
rid, pid, false, 0, document.TYPE_HOMEWORK);
this.response.body = { tid, rid };
if (this.canShowRecord(this.tdoc)) this.response.redirect = `/record/${rid}`;
else this.response.redirect = `/homework/${tid}`;
if (this.canShowRecord(this.tdoc)) this.response.redirect = this.url('record_detail', { rid });
else this.response.redirect = this.url('homework_detail', { tid });
}
}
@@ -230,7 +224,8 @@ class HomeworkCreateHandler extends HomeworkHandler {
class HomeworkEditHandler extends HomeworkHandler {
async get({ domainId, tid }) {
const tdoc = await contest.get(domainId, tid, document.TYPE_HOMEWORK);
if (tdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_HOMEWORK);
if (tdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_HOMEWORK);
else this.checkPerm(PERM.PERM_EDIT_HOMEWORK_SELF);
const extensionDays = Math.round(
(tdoc.endAt.getTime() - tdoc.penaltySince.getTime()) / 36000 / 24,
) / 100;
@@ -262,7 +257,8 @@ class HomeworkEditHandler extends HomeworkHandler {
penaltyRules, pids, tid,
}) {
const tdoc = await contest.get(domainId, tid, document.TYPE_HOMEWORK);
if (tdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_HOMEWORK);
if (tdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_HOMEWORK);
else this.checkPerm(PERM.PERM_EDIT_HOMEWORK_SELF);
let beginAt;
let penaltySince;
try {
@@ -288,7 +284,7 @@ class HomeworkEditHandler extends HomeworkHandler {
|| tdoc.endAt !== endAt
|| tdoc.penaltySince !== penaltySince
|| new Set(tdoc.pids) !== new Set(pids)) {
await contest.recalcStatus(domainId, document.TYPE_HOMEWORK, tdoc.docId);
await contest.recalcStatus(domainId, tdoc.docId, document.TYPE_HOMEWORK);
}
this.response.body = { tid };
this.response.redirect = this.url('homework_detail', { tid });
@@ -327,7 +323,7 @@ class HomeworkScoreboardDownloadHandler extends HomeworkHandler {
class HomeworkCodeHandler extends HomeworkHandler {
async get({ domainId, tid }) {
this.checkPerm(PERM_READ_RECORD_CODE);
this.checkPerm(PERM.PERM_READ_RECORD_CODE);
this.limitRate('homework_code', 3600, 60);
const [tdoc, tsdocs] = await contest.getAndListStatus(
domainId, tid, document.TYPE_HOMEWORK,
@@ -352,155 +348,15 @@ class HomeworkCodeHandler extends HomeworkHandler {
}
async function apply() {
contest.isHomeworkExtended = (tdoc) => {
const now = new Date().getTime();
return tdoc.penaltySince.getTime() <= now && now < tdoc.endAt.getTime();
};
contest.RULES.homework = {
TEXT: 'Assignment',
check: () => { },
stat: (tdoc, journal) => {
const effective = {};
for (const j of journal) {
if (tdoc.pids.includes(j.pid)
&& !effective.includes(j.pid)
&& effective[j.pid].accept) {
effective[j.pid] = j;
}
}
function time(jdoc) {
const real = jdoc.rid.generationTime - tdoc.beginAt.getTime() / 1000;
return Math.floor(real);
}
function penaltyScore(jdoc) {
const { score } = jdoc;
const exceedSeconds = Math.floor(
jdoc.rid.generationTime - tdoc.penaltySince.getTime() / 1000,
);
if (exceedSeconds < 0) return score;
let coefficient = 1;
const keys = Object.keys(tdoc.penaltyRules)
.map((k) => parseFloat(k)).sort((a, b) => a - b);
for (const i of keys) {
if (i * 3600 <= exceedSeconds) coefficient = tdoc.penaltyRules[i];
else break;
}
return score * coefficient;
}
const detail = [];
for (const j of effective) {
detail.push({ ...j, penaltyScore: penaltyScore(j), time: time(j) });
}
return {
score: Math.sum(detail.map((d) => d.score)),
penaltyScore: Math.sum(detail.map((d) => d.penaltySince)),
time: Math.sum(detail.map((d) => d.time)),
detail,
};
},
showScoreboard: () => true,
showRecord: () => true,
scoreboard(isExport, _, tdoc, rankedTsdocs, udict, pdict) {
const columns = [
{ type: 'rank', value: _('Rank') },
{ type: 'user', value: _('User') },
{ type: 'total_score', value: _('Score') },
];
if (isExport) {
columns.push(
{ type: 'total_original_score', value: _('Original Score') },
{ type: 'total_time', value: _('Total Time (Seconds)') },
);
}
columns.push({ type: 'total_time_str', value: _('Total Time') });
for (const index in tdoc.pids) {
const pid = tdoc.pids[index];
if (isExport) {
columns.push(
{
type: 'problem_score',
value: '#{0} {1}'.format(index + 1, pdict[pid].title),
},
{
type: 'problem_original_score',
value: '#{0} {1}'.format(index + 1, _('Original Score')),
},
{
type: 'problem_time',
value: '#{0} {1}'.format(index + 1, _('Time (Seconds)')),
},
{
type: 'problem_time_str',
value: '#{0} {1}'.format(index + 1, _('Time')),
},
);
} else {
columns.push({
type: 'problem_detail',
value: '#{0}'.format(index + 1),
raw: pdict[pid],
});
}
}
const rows = [columns];
for (const [rank, tsdoc] of rankedTsdocs) {
const tsddict = {};
for (const item of tsdoc.journal || []) {
tsddict[item.pid] = item;
}
const row = [
{ type: 'string', value: rank },
{
type: 'user',
value: udict[tsdoc.uid].uname,
raw: udict[tsdoc.uid],
},
{
type: 'string',
value: tsdoc.penaltyScore || 0,
},
];
if (isExport) {
row.push({ type: 'string', value: tsdoc.score || 0 });
row.push({ type: 'string', value: tsdoc.time || 0.0 });
}
row.push({ type: 'string', value: misc.formatSeconds(tsdoc.time || 0) });
for (const pid of tdoc.pids) {
const rdoc = (tsddict[pid] || {}).rid;
const colScore = (tsddict[pid] || {}).penaltyScore || '-';
const colOriginalScore = (tsddict[pid] || {}).score || '-';
const colTime = (tsddict[pid] || {}).time || '-';
const colTimeStr = colTime !== '-' ? misc.formatSeconds(colTime || 0) : '-';
if (isExport) {
row.push(
{ type: 'string', value: colScore },
{ type: 'string', value: colOriginalScore },
{ type: 'string', value: colTime },
{ type: 'string', value: colTimeStr },
);
} else {
row.push({
type: 'record',
value: '{0} / {1}\n{2}'.format(colScore, colOriginalScore, colTimeStr),
raw: rdoc,
});
}
}
rows.push(row);
}
return rows;
},
rank: (tsdocs) => ranked(tsdocs, (a, b) => a.score === b.score),
};
Route('homework_main', '/homework', HomeworkMainHandler, PERM_VIEW_HOMEWORK);
Route('homework_create', '/homework/create', HomeworkCreateHandler, PERM_CREATE_HOMEWORK);
Route('homework_detail', '/homework/:tid', HomeworkDetailHandler, PERM_VIEW_HOMEWORK);
Route('homework_scoreboard', '/homework/:tid/scoreboard', HomeworkScoreboardHandler, PERM_VIEW_HOMEWORK_SCOREBOARD);
Route('homework_scoreboard', '/homework/:tid/scoreboard/download/:ext', HomeworkScoreboardDownloadHandler, PERM_VIEW_HOMEWORK_SCOREBOARD);
Route('homework_detail_problem', '/homework/:tid/p/:pid', HomeworkDetailProblemHandler, PERM_VIEW_HOMEWORK);
Route('homework_detail_problem_submit', '/homework/:tid/p/:pid/submit', HomeworkDetailProblemSubmitHandler, PERM_SUBMIT_PROBLEM);
Route('homework_code', '/homework/:tid/code', HomeworkCodeHandler, PERM_VIEW_HOMEWORK);
Route('homework_main', '/homework', HomeworkMainHandler, PERM.PERM_VIEW_HOMEWORK);
Route('homework_create', '/homework/create', HomeworkCreateHandler, PERM.PERM_CREATE_HOMEWORK);
Route('homework_detail', '/homework/:tid', HomeworkDetailHandler, PERM.PERM_VIEW_HOMEWORK);
Route('homework_scoreboard', '/homework/:tid/scoreboard', HomeworkScoreboardHandler, PERM.PERM_VIEW_HOMEWORK_SCOREBOARD);
Route('homework_scoreboard', '/homework/:tid/scoreboard/download/:ext', HomeworkScoreboardDownloadHandler, PERM.PERM_VIEW_HOMEWORK_SCOREBOARD);
Route('homework_detail_problem', '/homework/:tid/p/:pid', HomeworkDetailProblemHandler, PERM.PERM_VIEW_HOMEWORK);
Route('homework_detail_problem_submit', '/homework/:tid/p/:pid/submit', HomeworkDetailProblemSubmitHandler, PERM.PERM_SUBMIT_PROBLEM);
Route('homework_code', '/homework/:tid/code', HomeworkCodeHandler, PERM.PERM_VIEW_HOMEWORK);
Route('homework_edit', '/homework/:tid/edit', HomeworkEditHandler);
}
global.Hydro.handler.homework = module.exports = apply;
global.Hydro.handler.homework = apply;
@@ -1,14 +1,14 @@
const fs = require('fs');
const path = require('path');
const os = require('os');
const problem = require('../model/problem');
const { PERM_CREATE_PROBLEM } = require('../model/builtin').PERM;
const { Route, Handler } = require('../service/server');
const { ValidationError } = require('../error');
import fs from 'fs';
import path from 'path';
import os from 'os';
import { ValidationError } from '../error'
import * as problem from '../model/problem';
import { PERM } from '../model/builtin';
import { Route, Handler } from '../service/server'
class ProblemImportHandler extends Handler {
async prepare() {
this.checkPerm(PERM_CREATE_PROBLEM);
this.checkPerm(PERM.PERM_CREATE_PROBLEM);
}
async get() {
@@ -47,8 +47,8 @@ class ProblemImportHandler extends Handler {
}
}
async function apply() {
export async function apply() {
Route('problem_import', '/problem/import', ProblemImportHandler);
}
global.Hydro.handler.import = module.exports = apply;
global.Hydro.handler.import = apply;
@@ -1,18 +1,18 @@
const yaml = require('js-yaml');
const { parseTimeMS, parseMemoryMB } = require('../utils');
const record = require('../model/record');
const problem = require('../model/problem');
const builtin = require('../model/builtin');
const contest = require('../model/contest');
const user = require('../model/user');
const task = require('../model/task');
const bus = require('../service/bus');
const {
import yaml from 'js-yaml';
import { parseTimeMS, parseMemoryMB } from '../utils';
import * as record from '../model/record';
import * as problem from '../model/problem';
import * as builtin from '../model/builtin';
import * as contest from '../model/contest';
import * as user from '../model/user';
import * as task from '../model/task';
import * as bus from '../service/bus';
import {
Route, Handler, Connection, ConnectionHandler,
} = require('../service/server');
} from '../service/server';
async function _postJudge(rdoc) {
const accept = rdoc.status === builtin.STATUS_ACCEPTED;
const accept = rdoc.status === builtin.STATUS.STATUS_ACCEPTED;
bus.publish('record_change', rdoc);
if (rdoc.type === 'run') return;
const tasks = [];
@@ -24,7 +24,7 @@ async function _postJudge(rdoc) {
),
);
}
if (await problem.updateStatus(rdoc.pid, rdoc.uid, rdoc._id, rdoc.status)) {
if (await problem.updateStatus(rdoc.domainId, rdoc.pid, rdoc.uid, rdoc._id, rdoc.status)) {
if (accept && !rdoc.rejudged) {
tasks.push(
problem.inc(rdoc.domainId, rdoc.pid, 'nAccept', 1),
@@ -35,12 +35,12 @@ async function _postJudge(rdoc) {
await Promise.all(tasks);
}
async function next(body) {
export async function next(body) {
let rdoc = await record.get(body.domainId, body.rid);
const $set = {};
const $push = {};
const $set: any = {};
const $push: any = {};
if (body.case) {
const c = {};
const c: any = {};
c.memory = body.case.memory_kb || body.case.memory;
c.time = body.case.time_ms || body.case.time;
c.judgeText = body.case.judge_text || body.case.judgeText || body.case.message;
@@ -65,10 +65,10 @@ async function next(body) {
bus.publish('record_change', rdoc);
}
async function end(body) {
export async function end(body) {
let rdoc = await record.get(body.domainId, body.rid);
const $set = {};
const $push = {};
const $set: any = {};
const $push: any = {};
const $unset = { progress: '' };
if (body.judge_text) {
rdoc.judgeTexts.push(body.judge_text);
@@ -98,7 +98,7 @@ class PretestHandler extends Handler {
if (pid) {
const pdoc = await problem.get(domainId, pid);
if (pdoc.config) {
const config = yaml.safeLoad(pdoc.config);
const config: any = yaml.safeLoad(pdoc.config);
if (config.time) time = config.time;
if (config.memory) memory = config.memory;
}
@@ -155,19 +155,19 @@ class JudgeConnectionHandler extends ConnectionHandler {
async cleanup() {
if (this.processing) {
await record.reset(this.processing);
await record.reset(this.processing.domainId, this.processing.rid);
task.add(this.processing);
}
}
}
async function apply() {
export async function apply() {
Route('pretest', '/pretest', PretestHandler);
Route('judge', '/judge', JudgeHandler, builtin.PERM.PERM_JUDGE);
Connection('judge_conn', '/judge/conn', JudgeConnectionHandler, builtin.PERM.PERM_JUDGE);
Route('judge', '/judge', JudgeHandler, builtin.PRIV.PRIV_JUDGE);
Connection('judge_conn', '/judge/conn', JudgeConnectionHandler, builtin.PRIV.PRIV_JUDGE);
}
apply.next = next;
apply.end = end;
global.Hydro.handler.judge = module.exports = apply;
global.Hydro.handler.judge = apply;
@@ -1,14 +1,14 @@
const setting = require('../model/setting');
const system = require('../model/system');
const { STATUS, PRIV } = require('../model/builtin');
const record = require('../model/record');
const judge = require('./judge');
const {
import * as judge from './judge';
import { ValidationError } from '../error';
import * as check from '../check';
import * as setting from '../model/setting';
import * as system from '../model/system';
import { STATUS, PRIV } from '../model/builtin';
import * as record from '../model/record';
import {
Route, Connection, Handler, ConnectionHandler,
} = require('../service/server');
const hpm = require('../lib/hpm');
const loader = require('../loader');
const check = require('../check');
} from '../service/server';
import * as hpm from '../lib/hpm';
function set(key, value) {
if (setting.SYSTEM_SETTINGS_BY_KEY[key]) {
@@ -81,7 +81,6 @@ class SystemModuleHandler extends SystemHandler {
async get() {
this.response.body.path.push(['manage_module', null]);
this.response.body.installed = await hpm.getDetail();
this.response.active = loader.active;
this.response.template = 'manage_module.html';
}
+11 -11
View File
@@ -1,9 +1,9 @@
const { PRIV_JUDGE, PRIV_USER_PROFILE } = require('../model/builtin').PRIV;
const file = require('../model/file');
const user = require('../model/user');
const markdown = require('../lib/markdown');
const db = require('../service/db');
const { Route, Handler } = require('../service/server');
import { PRIV } from '../model/builtin';
import * as file from '../model/file';
import * as user from '../model/user';
import * as markdown from '../lib/markdown';
import * as db from '../service/db';
import { Route, Handler } from '../service/server';
const coll = db.collection('status');
@@ -11,7 +11,7 @@ class FileDownloadHandler extends Handler {
async get({ docId, secret, name }) {
if (name) name = Buffer.from(name, 'base64').toString();
this.response.attachment(name || docId);
this.response.body = await file.get(docId, secret);
this.response.body = await file.getWithSecret(docId, secret);
}
}
@@ -37,7 +37,7 @@ class StatusHandler extends Handler {
class StatusUpdateHandler extends Handler {
async post(args) {
this.checkPerm(PRIV_JUDGE);
this.checkPerm(PRIV.PRIV_JUDGE);
args.type = 'judger';
return coll.updateOne(
{ mid: args.mid, type: 'judger' },
@@ -49,7 +49,7 @@ class StatusUpdateHandler extends Handler {
class SwitchLanguageHandler extends Handler {
async get({ lang }) {
if (this.user.hasPriv(PRIV_USER_PROFILE)) {
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
await user.setById(this.user._id, { viewLang: lang });
} else this.session.viewLang = lang;
this.back();
@@ -70,7 +70,7 @@ class SockToken extends Handler {
}
}
async function apply() {
export async function apply() {
Route('file_download', '/fs/:docId/:secret', FileDownloadHandler);
Route('file_download_with_name', '/fs/:docId/:name/:secret', FileDownloadHandler);
Route('status', '/status', StatusHandler);
@@ -89,4 +89,4 @@ apply.updateStatus = function updateStatus(args) {
);
};
global.Hydro.handler.misc = module.exports = apply;
global.Hydro.handler.misc = apply;
@@ -1,7 +1,7 @@
/* eslint-disable no-empty-function */
/* eslint-disable class-methods-use-this */
const { Route, Handler } = require('../service/server');
const { NotFoundError } = require('../error');
import { NotFoundError } from '../error';
import { Route, Handler } from '../service/server';
class NotFoundHandler extends Handler {
async prepare() {
@@ -13,8 +13,8 @@ class NotFoundHandler extends Handler {
async post() { }
}
async function apply() {
export async function apply() {
Route('notfound', '*', NotFoundHandler);
}
global.Hydro.handler.notfound = module.exports = apply;
global.Hydro.handler.notfound = apply;
@@ -1,58 +1,47 @@
const paginate = require('../lib/paginate');
const validator = require('../lib/validator');
const file = require('../model/file');
const problem = require('../model/problem');
const record = require('../model/record');
const user = require('../model/user');
const solution = require('../model/solution');
const system = require('../model/system');
const {
PERM: {
PERM_VIEW_PROBLEM, PERM_VIEW_PROBLEM_HIDDEN, PERM_SUBMIT_PROBLEM,
PERM_CREATE_PROBLEM, PERM_READ_PROBLEM_DATA, PERM_EDIT_PROBLEM,
PERM_VIEW_PROBLEM_SOLUTION, PERM_CREATE_PROBLEM_SOLUTION,
PERM_EDIT_PROBLEM_SOLUTION, PERM_DELETE_PROBLEM_SOLUTION, PERM_EDIT_PROBLEM_SOLUTION_REPLY,
PERM_REPLY_PROBLEM_SOLUTION, PERM_EDIT_PROBLEM_SELF,
},
PRIV: {
PRIV_USER_PROFILE, PRIV_JUDGE,
},
} = require('../model/builtin');
const bus = require('../service/bus');
const {
import paginate from '../lib/paginate';
import * as validator from '../lib/validator';
import * as file from '../model/file';
import * as problem from '../model/problem';
import * as record from '../model/record';
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 * as bus from '../service/bus';
import {
Route, Connection, Handler, ConnectionHandler,
} = require('../service/server');
const {
} from '../service/server';
import {
NoProblemError, ProblemDataNotFoundError, BadRequestError,
SolutionNotFoundError,
} = require('../error');
} from '../error';
class ProblemHandler extends Handler {
async _prepare() {
this.checkPerm(PERM_VIEW_PROBLEM);
async __prepare() {
this.checkPerm(PERM.PERM_VIEW_PROBLEM);
}
async get({ domainId, page = 1, q = '' }) {
this.response.template = 'problem_main.html';
const query = {};
const query: any = {};
let psdict = {};
const path = [
const path: any = [
['Hydro', 'homepage'],
['problem_main', null],
];
if (q) {
q = q.toLowerCase();
const $regex = new RegExp(`\\A\\Q${q.replace(/\\E/gmi, /\\E\\E\\Q/gmi)}\\E`, 'gmi');
const $regex = new RegExp(`\\A\\Q${q}\\E`, 'gmi');
query.title = { $regex };
path.push([q, null, null, true]);
}
if (!this.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN)) query.hidden = false;
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) query.hidden = false;
const [pdocs, ppcount, pcount] = await paginate(
problem.getMulti(domainId, query).sort({ pid: 1 }),
page,
await system.get('PROBLEM_PER_PAGE'),
);
if (this.user.hasPriv(PRIV_USER_PROFILE)) {
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
psdict = await problem.getListStatus(
domainId, this.user._id, pdocs.map((pdoc) => pdoc.docId),
);
@@ -73,7 +62,7 @@ class ProblemHandler extends Handler {
}
async cleanup() {
if (this.response.template === 'problem_main.html' && this.preferJson) {
if (this.response.template === 'problem_main.html' && this.request.json) {
const {
path, page, pcount, ppcount, pdocs, psdict, category,
} = this.response.body;
@@ -98,7 +87,7 @@ class ProblemHandler extends Handler {
class ProblemCategoryHandler extends ProblemHandler {
async get({ domainId, page = 1, category }) {
this.response.template = 'problem_main.html';
const q = { $and: [] };
const q: any = { $and: [] };
for (const name of category) {
q.$and.push({
$or: [
@@ -108,13 +97,13 @@ class ProblemCategoryHandler extends ProblemHandler {
});
}
let psdict = {};
if (!this.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false;
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false;
const [pdocs, ppcount, pcount] = await paginate(
problem.getMulti(domainId, q).sort({ pid: 1 }),
page,
await system.get('PROBLEM_PER_PAGE'),
);
if (this.user.hasPriv(PRIV_USER_PROFILE)) {
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
psdict = await problem.getListStatus(
domainId, this.user._id, pdocs.map((pdoc) => pdoc.docId),
);
@@ -132,7 +121,7 @@ class ProblemCategoryHandler extends ProblemHandler {
class ProblemRandomHandler extends ProblemHandler {
async get({ domainId, category }) {
const q = category[0] ? { $and: [] } : {};
const q: any = category[0] ? { $and: [] } : {};
for (const name of category) {
if (name) {
q.$and.push({
@@ -143,7 +132,7 @@ class ProblemRandomHandler extends ProblemHandler {
});
}
}
if (!this.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false;
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false;
const pid = await problem.random(domainId, q);
if (!pid) throw new NoProblemError();
this.response.body = { pid };
@@ -157,7 +146,7 @@ class ProblemDetailHandler extends ProblemHandler {
if (pid) {
this.pdoc = await problem.get(domainId, pid, this.user._id);
if (this.pdoc.hidden && this.pdoc.owner !== this.user._id) {
this.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
}
if (this.pdoc) this.udoc = await user.getById(domainId, this.pdoc.owner);
}
@@ -168,7 +157,8 @@ class ProblemDetailHandler extends ProblemHandler {
};
}
async get() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async get(args: any) {
this.response.body.path = [
['Hydro', 'homepage'],
['problem_main', 'problem_main'],
@@ -260,8 +250,8 @@ class ProblemStatisticsHandler extends ProblemDetailHandler {
class ProblemManageHandler extends ProblemDetailHandler {
async prepare() {
if (this.pdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_PROBLEM);
else this.checkPerm(PERM_EDIT_PROBLEM_SELF);
if (this.pdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_PROBLEM);
else this.checkPerm(PERM.PERM_EDIT_PROBLEM_SELF);
}
}
@@ -335,8 +325,10 @@ class ProblemDataUploadHandler extends ProblemManageHandler {
class ProblemDataDownloadHandler extends ProblemDetailHandler {
async get({ pid }) {
if (this.user._id !== this.pdoc.owner) {
if (!this.user.hasPerm(PERM_READ_PROBLEM_DATA)) this.checkPriv(PRIV_JUDGE);
if (!this.user.hasPriv(PRIV.PRIV_JUDGE)) {
if (this.user._id !== this.pdoc.owner) {
this.checkPerm(PERM.PERM_READ_PROBLEM_DATA);
} else this.checkPerm(PERM.PERM_READ_PROBLEM_DATA_SELF);
}
if (!this.pdoc.data) throw new ProblemDataNotFoundError(pid);
else if (typeof this.pdoc.data === 'string') [, this.response.redirect] = this.pdoc.data.split('from:');
@@ -347,7 +339,7 @@ class ProblemDataDownloadHandler extends ProblemDetailHandler {
class ProblemSolutionHandler extends ProblemDetailHandler {
async get({ domainId, page = 1 }) {
this.response.template = 'problem_solution.html';
this.checkPerm(PERM_VIEW_PROBLEM_SOLUTION);
this.checkPerm(PERM.PERM_VIEW_PROBLEM_SOLUTION);
const [psdocs, pcount, pscount] = await paginate(
solution.getMulti(domainId, this.pdoc.docId),
page,
@@ -362,7 +354,7 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
for (const psrdoc of psdoc.reply) uids.push(psrdoc.owner);
}
}
const udict = await user.getList(uids);
const udict = await user.getList(domainId, uids);
const pssdict = solution.getListStatus(domainId, docids, this.user._id);
const path = [
['problem_main', 'problem_main'],
@@ -379,28 +371,31 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
}
async postSubmit({ domainId, content }) {
this.checkPerm(PERM_CREATE_PROBLEM_SOLUTION);
this.checkPerm(PERM.PERM_CREATE_PROBLEM_SOLUTION);
await solution.add(domainId, this.pdoc.docId, this.user._id, content);
this.back();
}
async postEditSolution({ domainId, content }) {
if (this.psdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_PROBLEM_SOLUTION);
if (this.psdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION);
else this.checkPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION_SELF);
this.psdoc = await solution.edit(domainId, this.psdoc.docId, content);
this.ctx.body.psdoc = this.psdoc;
this.back();
}
async postDeleteSolution({ domainId }) {
if (this.psdoc.owner !== this.user._id) this.checkPerm(PERM_DELETE_PROBLEM_SOLUTION);
if (this.psdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION);
else this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_SELF);
await solution.del(domainId, this.psdoc.docId);
this.back();
}
async postReply({ domainId, psid, content }) {
this.checkPerm(PERM_REPLY_PROBLEM_SOLUTION);
this.checkPerm(PERM.PERM_REPLY_PROBLEM_SOLUTION);
const psdoc = await solution.get(domainId, psid);
await solution.reply(domainId, psdoc.docId, this.user._id, content);
this.back();
}
async postEditReply({
@@ -408,14 +403,27 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
}) {
const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid);
if ((!psdoc) || psdoc.pid !== this.pdoc.docId) throw new SolutionNotFoundError(psid);
if (psrdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_PROBLEM_SOLUTION_REPLY);
if (!(psdoc.owner === this.user._id
&& this.user.hasPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF_SOLUTION))) {
if (!(psrdoc.owner === this.user._id
&& this.user.hasPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF))) {
this.checkPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION_REPLY);
}
}
await solution.editReply(domainId, psid, psrid, content);
this.back();
}
async postDeleteReply({ domainId, psid, psrid }) {
const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid);
if ((!psdoc) || psdoc.pid !== this.pdoc.docId) throw new SolutionNotFoundError(psid);
if (psrdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_PROBLEM_SOLUTION_REPLY);
if (!(psdoc.owner === this.user._id
&& this.user.hasPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF_SOLUTION))) {
if (!(psrdoc.owner === this.user._id
&& this.user.hasPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF))) {
this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_REPLY);
}
}
await solution.delReply(domainId, psid, psrid);
this.back();
}
@@ -435,7 +443,7 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
class ProblemSolutionRawHandler extends ProblemDetailHandler {
async get({ domainId, psid }) {
this.checkPerm(PERM_VIEW_PROBLEM_SOLUTION);
this.checkPerm(PERM.PERM_VIEW_PROBLEM_SOLUTION);
const psdoc = await solution.get(domainId, psid);
this.response.type = 'text/markdown';
this.response.body = psdoc.content;
@@ -443,10 +451,10 @@ class ProblemSolutionRawHandler extends ProblemDetailHandler {
}
class ProblemSolutionReplyRawHandler extends ProblemDetailHandler {
async get({ domainId, psid }) {
this.checkPerm(PERM_VIEW_PROBLEM_SOLUTION);
const [psdoc, psrdoc] = await solution.getReply(domainId, psid);
if ((!psdoc) || psdoc.pid !== this.pdoc.docId) throw new SolutionNotFoundError(psid);
async get({ domainId, psid, psrid }) {
this.checkPerm(PERM.PERM_VIEW_PROBLEM_SOLUTION);
const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid);
if ((!psdoc) || psdoc.pid !== this.pdoc.docId) throw new SolutionNotFoundError(psid, psrid);
this.response.type = 'text/markdown';
this.response.body = psrdoc.content;
}
@@ -455,7 +463,7 @@ class ProblemSolutionReplyRawHandler extends ProblemDetailHandler {
class ProblemCreateHandler extends Handler {
async get() {
this.response.template = 'problem_edit.html';
this.checkPerm(PERM_CREATE_PROBLEM);
this.checkPerm(PERM.PERM_CREATE_PROBLEM);
this.response.body = {
path: [
['Hydro', 'homepage'],
@@ -477,12 +485,12 @@ class ProblemCreateHandler extends Handler {
}
}
async function apply() {
export async function apply() {
Route('problem_main', '/p', ProblemHandler);
Route('problem_category', '/p/category/:category', ProblemCategoryHandler);
Route('problem_random', '/problem/random', ProblemRandomHandler);
Route('problem_detail', '/p/:pid', ProblemDetailHandler);
Route('problem_submit', '/p/:pid/submit', ProblemSubmitHandler, PERM_SUBMIT_PROBLEM);
Route('problem_submit', '/p/:pid/submit', ProblemSubmitHandler, PERM.PERM_SUBMIT_PROBLEM);
Route('problem_pretest', '/p/:pid/pretest', ProblemPretestHandler);
Route('problem_settings', '/p/:pid/settings', ProblemSettingsHandler);
Route('problem_statistics', '/p/:pid/statistics', ProblemStatisticsHandler);
@@ -496,4 +504,4 @@ async function apply() {
Connection('problem_pretest_conn', '/p/:pid/pretest-conn', ProblemPretestConnectionHandler);
}
global.Hydro.handler.problem = module.exports = apply;
global.Hydro.handler.problem = apply;
@@ -1,16 +1,16 @@
const { ObjectID } = require('mongodb');
const { PermissionError } = require('../error');
const { PERM_READ_RECORD_CODE, PERM_REJUDGE, PERM_VIEW_PROBLEM_HIDDEN } = require('../model/builtin').PERM;
const problem = require('../model/problem');
const record = require('../model/record');
const contest = require('../model/contest');
const system = require('../model/system');
const user = require('../model/user');
const paginate = require('../lib/paginate');
const bus = require('../service/bus');
const {
import { ObjectID } from 'mongodb';
import { PermissionError } from '../error';
import { PERM } 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';
import {
Route, Handler, Connection, ConnectionHandler,
} = require('../service/server');
} from '../service/server';
const RecordHandler = contest.ContestHandlerMixin(Handler);
@@ -19,7 +19,7 @@ class RecordListHandler extends RecordHandler {
domainId, page = 1, pid, tid, uidOrName,
}) {
this.response.template = 'record_main.html';
const q = { tid, hidden: false };
const q: any = { tid, hidden: false };
if (uidOrName) {
q.$or = [
{ unameLower: uidOrName.toLowerCase() },
@@ -61,7 +61,7 @@ class RecordDetailHandler extends RecordHandler {
const tdoc = await contest.get(domainId, rdoc.tid, rdoc.ttype);
if (!this.canShowRecord(tdoc, true)) throw new PermissionError(rid);
}
if (rdoc.uid !== this.user.uid && !this.user.hasPerm(PERM_READ_RECORD_CODE)) {
if (rdoc.uid !== this.user.uid && !this.user.hasPerm(PERM.PERM_READ_RECORD_CODE)) {
rdoc.code = null;
}
if (rdoc.type !== 'run') rdoc.stdout = rdoc.stderr = '';
@@ -85,7 +85,7 @@ class RecordDetailHandler extends RecordHandler {
class RecordRejudgeHandler extends Handler {
async post({ domainId, rid }) {
this.checkPerm(PERM_REJUDGE);
this.checkPerm(PERM.PERM_REJUDGE);
const rdoc = await record.get(domainId, rid);
if (rdoc) await record.rejudge(domainId, rid);
this.back();
@@ -131,7 +131,7 @@ class RecordMainConnectionHandler extends RecordConnectionHandler {
user.getById(this.domainId, rdoc.uid),
problem.get(this.domainId, rdoc.pid, null, false),
]);
if (pdoc && pdoc.hidden && !this.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN)) pdoc = null;
if (pdoc && pdoc.hidden && !this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) pdoc = null;
this.send({ html: await this.renderHTML('record_main_tr.html', { rdoc, udoc, pdoc }) });
}
}
@@ -165,7 +165,7 @@ class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(Connecti
}
}
async function apply() {
export async function apply() {
Route('record_main', '/record', RecordListHandler);
Route('record_detail', '/record/:rid', RecordDetailHandler);
Route('record_rejudge', '/record/:rid/rejudge', RecordRejudgeHandler);
@@ -173,4 +173,4 @@ async function apply() {
Connection('record_detail_conn', '/record-detail-conn', RecordDetailConnectionHandler);
}
global.Hydro.handler.record = module.exports = apply;
global.Hydro.handler.record = apply;
@@ -1,21 +1,14 @@
const assert = require('assert');
const { ValidationError, ProblemNotFoundError } = require('../error');
const paginate = require('../lib/paginate');
const {
PERM: {
PERM_VIEW_TRAINING, PERM_VIEW_PROBLEM_HIDDEN, PERM_CREATE_TRAINING,
PERM_EDIT_TRAINING, PERM_EDIT_TRAINING_SELF,
},
PRIV: {
PRIV_USER_PROFILE,
},
} = require('../model/builtin');
const problem = require('../model/problem');
const builtin = require('../model/builtin');
const training = require('../model/training');
const user = require('../model/user');
const system = require('../model/system');
const { Route, Handler } = require('../service/server');
import assert from 'assert';
import { ValidationError, ProblemNotFoundError } from '../error';
import paginate from '../lib/paginate';
import { PERM, PRIV } 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 } from '../service/server';
import { ObjectID } from 'mongodb';
async function _parseDagJson(domainId, dag) {
const parsed = [];
@@ -65,12 +58,12 @@ class TrainingMainHandler extends Handler {
page,
await system.get('TRAINING_PER_PAGE'),
);
const tids = new Set();
const tids: Set<ObjectID> = new Set();
for (const tdoc of tdocs) tids.add(tdoc.docId);
const tsdict = {};
let tdict = {};
if (this.user.hasPriv(PRIV_USER_PROFILE)) {
const enrolledTids = new Set();
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
const enrolledTids: Set<ObjectID> = new Set();
const tsdocs = await training.getMultiStatus(domainId, {
uid: this.user._id,
$or: [{ docId: { $in: Array.from(tids) } }, { enroll: 1 }],
@@ -84,7 +77,7 @@ class TrainingMainHandler extends Handler {
tdict = await training.getList(domainId, Array.from(enrolledTids));
}
}
for (const tdoc in tdocs) tdict[tdoc.docId] = tdoc;
for (const tdoc of tdocs) tdict[tdoc.docId] = tdoc;
const path = [
['Hydro', 'homepage'],
['training_main', null],
@@ -102,7 +95,7 @@ class TrainingDetailHandler extends Handler {
const pids = training.getPids(tdoc);
const [owner, pdict] = await Promise.all([
user.getById(domainId, tdoc.owner),
problem.getList(domainId, pids, this.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN)),
problem.getList(domainId, pids, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)),
]);
const psdict = await problem.getListStatus(domainId, this.user._id, pids);
const donePids = new Set();
@@ -123,7 +116,7 @@ class TrainingDetailHandler extends Handler {
const totalCount = node.pids.length;
const doneCount = Set.union(new Set(node.pids), donePids).size;
const nsdoc = {
progress: totalCount ? parseInt(100 * (doneCount / totalCount), 10) : 100,
progress: totalCount ? Math.floor(100 * (doneCount / totalCount)) : 100,
isDone: training.isDone(node, doneNids, donePids),
isProgress: training.isProgress(node, doneNids, donePids, progPids),
isOpen: training.isOpen(node, doneNids, donePids, progPids),
@@ -149,7 +142,7 @@ class TrainingDetailHandler extends Handler {
}
async postEnroll({ domainId, tid }) {
this.checkPriv(PRIV_USER_PROFILE);
this.checkPriv(PRIV.PRIV_USER_PROFILE);
const tdoc = await training.get(domainId, tid);
await training.enroll(domainId, tdoc.docId, this.user._id);
this.back();
@@ -186,8 +179,8 @@ class TrainingCreateHandler extends Handler {
);
}
}
for (const pdoc in pdocs) {
if (pdoc.hidden) this.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
for (const pdoc of pdocs) {
if (pdoc.hidden) this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
}
const tid = await training.add(domainId, title, content, this.user._id, dag, description);
this.response.body = { tid };
@@ -198,8 +191,8 @@ class TrainingCreateHandler extends Handler {
class TrainingEditHandler extends Handler {
async prepare({ domainId, tid }) {
this.tdoc = await training.get(domainId, tid);
if (this.tdoc.owner !== this.user._id) this.checkPerm(PERM_EDIT_TRAINING);
else this.checkPerm(PERM_EDIT_TRAINING_SELF);
if (this.tdoc.owner !== this.user._id) this.checkPerm(PERM.PERM_EDIT_TRAINING);
else this.checkPerm(PERM.PERM_EDIT_TRAINING_SELF);
}
async get({ tid }) {
@@ -238,8 +231,8 @@ class TrainingEditHandler extends Handler {
);
}
}
for (const pdoc in pdocs) {
if (pdoc.hidden) this.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
for (const pdoc of pdocs) {
if (pdoc.hidden) this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
}
await training.edit(domainId, tid, {
title, content, dag, description,
@@ -249,11 +242,11 @@ class TrainingEditHandler extends Handler {
}
}
async function apply() {
Route('training_main', '/training', TrainingMainHandler, PERM_VIEW_TRAINING);
Route('training_create', '/training/create', TrainingCreateHandler, PERM_CREATE_TRAINING);
Route('training_detail', '/training/:tid', TrainingDetailHandler, PERM_VIEW_TRAINING);
export async function apply() {
Route('training_main', '/training', TrainingMainHandler, PERM.PERM_VIEW_TRAINING);
Route('training_create', '/training/create', TrainingCreateHandler, PERM.PERM_CREATE_TRAINING);
Route('training_detail', '/training/:tid', TrainingDetailHandler, PERM.PERM_VIEW_TRAINING);
Route('training_edit', '/training/:tid/edit', TrainingEditHandler);
}
global.Hydro.handler.training = module.exports = apply;
global.Hydro.handler.training = apply;
+30 -33
View File
@@ -1,27 +1,20 @@
const superagent = require('superagent');
const moment = require('moment-timezone');
const { Route, Handler } = require('../service/server.js');
const user = require('../model/user');
const token = require('../model/token');
const record = require('../model/record');
const problem = require('../model/problem');
const task = require('../model/task');
const system = require('../model/system');
const { sendMail } = require('../lib/mail');
const misc = require('../lib/misc');
const {
import superagent from 'superagent';
import moment from 'moment-timezone';
import { Route, Handler } from '../service/server';
import * as user from '../model/user';
import * as token from '../model/token';
import * as record from '../model/record';
import * as problem from '../model/problem';
import * as task from '../model/task';
import * as system from '../model/system';
import { PERM, PRIV } from '../model/builtin';
import { sendMail } from '../lib/mail';
import * as misc from '../lib/misc';
import {
UserAlreadyExistError, InvalidTokenError, VerifyPasswordError,
UserNotFoundError, LoginError, SystemError,
BlacklistedError, UserFacingError,
} = require('../error');
const {
PERM: {
PERM_VIEW_PROBLEM_HIDDEN,
},
PRIV: {
PRIV_USER_PROFILE, PRIV_REGISTER_USER, PRIV_NONE,
},
} = require('../model/builtin');
} from '../error';
class UserLoginHandler extends Handler {
async get() {
@@ -41,7 +34,7 @@ class UserLoginHandler extends Handler {
if (!udoc) throw new LoginError(uname);
udoc.checkPassword(password);
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
if (udoc.priv === PRIV_NONE) throw new BlacklistedError(uname);
if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname);
this.session.uid = udoc._id;
this.session.save = rememberme;
this.response.redirect = this.request.referer.endsWith('/login') ? '/' : this.request.referer;
@@ -116,7 +109,7 @@ class UserLostPassHandler extends Handler {
async post({ mail }) {
if (!await system.get('smtp.user')) throw new SystemError('Cannot send mail');
const udoc = await user.getByEmail(mail);
const udoc = await user.getByEmail('system', mail);
if (!udoc) throw new UserNotFoundError(mail);
const [tid] = await token.add(
token.TYPE_LOSTPASS,
@@ -155,10 +148,14 @@ class UserDetailHandler extends Handler {
const rdocs = await record.getByUid(domainId, uid);
const pdict = await problem.getList(
domainId, rdocs.map((rdoc) => rdoc.pid),
this.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN), false,
this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), false,
);
// Remove sensitive data
if (!isSelfProfile && sdoc) sdoc.createIp = sdoc.updateIp = sdoc._id = '';
if (!isSelfProfile && sdoc) {
sdoc.createIp = '';
sdoc.updateIp = '';
sdoc._id = '';
}
this.response.template = 'user_detail.html';
this.response.body = {
isSelfProfile, udoc, sdoc, rdocs, pdict,
@@ -300,7 +297,7 @@ class OauthCallbackHandler extends Handler {
if (udoc) {
this.session.uid = udoc._id;
} else {
this.checkPriv(PRIV_REGISTER_USER);
this.checkPriv(PRIV.PRIV_REGISTER_USER);
let username = '';
r.uname = r.uname || [];
r.uname.push(String.random(16));
@@ -315,7 +312,7 @@ class OauthCallbackHandler extends Handler {
const uid = await user.create({
mail: r.email, uname: username, password: String.random(32), regip: this.request.ip,
});
const $set = {
const $set: any = {
oauth: args.type,
};
if (r.bio) $set.bio = r.bio;
@@ -326,18 +323,18 @@ class OauthCallbackHandler extends Handler {
}
}
async function apply() {
export async function apply() {
Route('user_login', '/login', UserLoginHandler);
Route('user_oauth', '/oauth/:type', OauthHandler);
Route('user_oauth_callback', '/oauth/:type/callback', OauthCallbackHandler);
Route('user_register', '/register', UserRegisterHandler, PRIV_REGISTER_USER);
Route('user_register_with_code', '/register/:code', UserRegisterWithCodeHandler, PRIV_REGISTER_USER);
Route('user_logout', '/logout', UserLogoutHandler, PRIV_USER_PROFILE);
Route('user_register', '/register', UserRegisterHandler, PRIV.PRIV_REGISTER_USER);
Route('user_register_with_code', '/register/:code', UserRegisterWithCodeHandler, PRIV.PRIV_REGISTER_USER);
Route('user_logout', '/logout', UserLogoutHandler, PRIV.PRIV_USER_PROFILE);
Route('user_lostpass', '/lostpass', UserLostPassHandler);
Route('user_lostpass_with_code', '/lostpass/:code', UserLostPassWithCodeHandler);
Route('user_search', '/user/search', UserSearchHandler);
Route('user_delete', '/user/delete', UserDeleteHandler, PRIV_USER_PROFILE);
Route('user_delete', '/user/delete', UserDeleteHandler, PRIV.PRIV_USER_PROFILE);
Route('user_detail', '/user/:uid', UserDetailHandler);
}
global.Hydro.handler.user = module.exports = apply;
global.Hydro.handler.user = apply;
@@ -1,5 +1,5 @@
const { Route, Handler } = require('../service/server');
const { NotFoundError } = require('../error');
import { NotFoundError } from '../error';
import { Route, Handler } from '../service/server';
class WikiHandler extends Handler {
async get({ category = 'wiki', page }) {
@@ -18,9 +18,9 @@ class WikiHandler extends Handler {
}
}
async function apply() {
export async function apply() {
Route('wiki', '/wiki/:page', WikiHandler);
Route('wiki_with_category', '/wiki/:category/:page', WikiHandler);
}
global.Hydro.handler.wiki = module.exports = apply;
global.Hydro.handler.wiki = apply;