系统设置中自定义UI的支持

This commit is contained in:
undefined committed 2020-07-12 13:36:12 +08:00
1 parent 11368bc831
commit 1722fbfaca
21 files changed
+284 -140

No files matched your search

+1 -1
View File
@@ -200,7 +200,7 @@ class ContestEditHandler extends ContestHandler {
class ContestProblemHandler extends ContestHandler {
@param('tid', Types.ObjectID)
@param('pid', Types.UnsignedInt)
async prepare(domainId: string, tid: ObjectID, pid: number) {
async _prepare(domainId: string, tid: ObjectID, pid: number) {
[this.tdoc, this.pdoc] = await Promise.all([
contest.get(domainId, tid),
problem.get(domainId, pid, this.user._id),
+5 -2
View File
@@ -1,6 +1,7 @@
import {
VerifyPasswordError, UserAlreadyExistError, InvalidTokenError,
NotFoundError,
UserNotFoundError,
} from '../error';
import * as bus from '../service/bus';
import {
@@ -141,7 +142,7 @@ class HomeSecurityHandler extends Handler {
async postChangeMail({ domainId, currentPassword, mail }) {
this.limitRate('send_mail', 3600, 30);
this.user.checkPassword(currentPassword);
const udoc = await user.getByEmail(domainId, mail, true);
const udoc = await user.getByEmail(domainId, mail);
if (udoc) throw new UserAlreadyExistError(mail);
const [code] = await token.add(
token.TYPE_CHANGEMAIL,
@@ -212,7 +213,7 @@ class UserChangemailWithCodeHandler extends Handler {
if (!tdoc || tdoc.uid !== this.user._id) {
throw new InvalidTokenError(code);
}
const udoc = await user.getByEmail(domainId, tdoc.mail, true);
const udoc = await user.getByEmail(domainId, tdoc.mail);
if (udoc) throw new UserAlreadyExistError(tdoc.mail);
await Promise.all([
user.setEmail(this.user._id, tdoc.mail),
@@ -253,6 +254,7 @@ class HomeMessagesHandler extends Handler {
async postSend({ uid, content }) {
const udoc = await user.getById('system', uid);
if (!udoc) throw new UserNotFoundError(uid);
const mdoc = await message.send(this.user._id, uid, content);
// TODO(twd2): improve here: projection
if (this.user._id !== uid) {
@@ -262,6 +264,7 @@ class HomeMessagesHandler extends Handler {
}
async postDeleteMessage({ messageId }) {
// TODO limitations
await message.del(messageId);
this.back();
}
+12 -4
View File
@@ -7,6 +7,7 @@ import {
ValidationError, HomeworkNotLiveError, ProblemNotFoundError,
HomeworkNotAttendedError,
} from '../error';
import { PenaltyRules } from '../interface';
import {
Route, Handler, Types, param,
} from '../service/server';
@@ -21,6 +22,12 @@ import * as document from '../model/document';
import paginate from '../lib/paginate';
import { isTitle, isContent } from '../lib/validator';
const validatePenaltyRules = (input: string) => {
const s = yaml.safeLoad(input);
return s;
};
const convertPenaltyRules = validatePenaltyRules;
const HomeworkHandler = contest.ContestHandlerMixin(Handler);
class HomeworkMainHandler extends HomeworkHandler {
@@ -28,7 +35,7 @@ class HomeworkMainHandler extends HomeworkHandler {
const tdocs = await contest.getMulti(domainId, {}, document.TYPE_HOMEWORK).toArray();
const calendar = [];
for (const tdoc of tdocs) {
const cal = { ...tdoc, url: `/homework/${tdoc.docId}` };
const cal = { ...tdoc, url: this.url('homework_detail', { tid: tdoc.docId }) };
if (contest.isExtended(tdoc) || contest.isDone(tdoc)) {
cal.endAt = tdoc.endAt;
cal.penaltySince = tdoc.penaltySince;
@@ -211,7 +218,7 @@ class HomeworkCreateHandler extends HomeworkHandler {
@param('penaltySinceDate', Types.Date)
@param('penaltySinceTime', Types.Time)
@param('extensionDays', Types.Float)
@param('penaltyRules', Types.String)
@param('penaltyRules', Types.String, validatePenaltyRules, convertPenaltyRules)
@param('title', Types.String, isTitle)
@param('content', Types.String, isContent)
@param('pids', Types.String)
@@ -219,7 +226,7 @@ class HomeworkCreateHandler extends HomeworkHandler {
async post(
domainId: string, beginAtDate: string, beginAtTime: string,
penaltySinceDate: string, penaltySinceTime: string, extensionDays: number,
penaltyRules: string, title: string, content: string, _pids: string, rated = false,
penaltyRules: PenaltyRules, title: string, content: string, _pids: string, rated = false,
) {
const pids = _pids.split(',').map((i) => {
if (isSafeInteger(parseInt(i, 10))) return parseInt(i, 10);
@@ -278,7 +285,7 @@ class HomeworkEditHandler extends HomeworkHandler {
@param('penaltySinceDate', Types.Date)
@param('penaltySinceTime', Types.Time)
@param('extensionDays', Types.Float)
@param('penaltyRules', Types.String)
@param('penaltyRules', Types.String, validatePenaltyRules, convertPenaltyRules)
@param('title', Types.String, isTitle)
@param('content', Types.String, isContent)
@param('pids', Types.String)
@@ -330,6 +337,7 @@ class HomeworkEditHandler extends HomeworkHandler {
class HomeworkScoreboardHandler extends HomeworkHandler {
@param('tid', Types.ObjectID)
async get(domainId: string, tid: ObjectID) {
console.log(123);
const [tdoc, rows, udict] = await this.getScoreboard(
domainId, tid, false, document.TYPE_HOMEWORK,
);
+1 -1
View File
@@ -168,7 +168,7 @@ class JudgeConnectionHandler extends ConnectionHandler {
async cleanup() {
if (this.processing) {
await record.reset(this.processing.domainId, this.processing.rid);
await record.reset(this.processing.domainId, this.processing.rid, false);
task.add(this.processing);
}
}
-1
View File
@@ -169,7 +169,6 @@ class SystemSettingHandler extends SystemHandler {
for (const key in args) {
if (typeof args[key] === 'object') {
for (const subkey in args[key]) {
console.log(`${key}.${subkey}`, set(`${key}.${subkey}`, args[key][subkey]));
if (typeof set(`${key}.${subkey}`, args[key][subkey]) !== 'undefined') {
tasks.push(system.set(`${key}.${subkey}`, set(`${key}.${subkey}`, args[key][subkey])));
}
+14
View File
@@ -1,5 +1,6 @@
import { ObjectID } from 'mongodb';
import { PRIV } from '../model/builtin';
import * as system from '../model/system';
import * as file from '../model/file';
import * as user from '../model/user';
import * as markdown from '../lib/markdown';
@@ -77,6 +78,18 @@ class SockToken extends Handler {
}
}
class UiSettingsHandler extends Handler {
async get() {
const [
header, nav, headerBackground,
] = await system.getMany([
'ui.header', 'ui.nav', 'ui.headerBackground',
]);
this.response.body = await this.renderHTML('extra.css', { header, nav, headerBackground });
this.response.type = 'text/css';
}
}
export async function apply() {
Route('file_download', '/fs/:fileId/:secret', FileDownloadHandler);
Route('file_download_with_name', '/fs/:fileId/:name/:secret', FileDownloadHandler);
@@ -85,6 +98,7 @@ export async function apply() {
Route('switch_language', '/language/:lang', SwitchLanguageHandler);
Route('markdown', '/markdown', MarkdownHandler);
Route('token', '/token', SockToken);
Route('ui', '/extra.css', UiSettingsHandler);
}
apply.updateStatus = function updateStatus(args) {
+4 -3
View File
@@ -62,7 +62,7 @@ class UserRegisterHandler extends Handler {
@param('mail', Types.String, isEmail)
async post(domainId: string, mail: string) {
if (await user.getByEmail('system', mail, true)) throw new UserAlreadyExistError(mail);
if (await user.getByEmail('system', mail)) throw new UserAlreadyExistError(mail);
this.limitRate('send_mail', 3600, 30);
const t = await token.add(
token.TYPE_REGISTRATION,
@@ -158,7 +158,8 @@ class UserDetailHandler extends Handler {
@param('uid', Types.Int)
async get(domainId: string, uid: number) {
const isSelfProfile = this.user._id === uid;
const udoc = await user.getById(domainId, uid, true);
const udoc = await user.getById(domainId, uid);
if (!udoc) throw new UserNotFoundError(uid);
const sdoc = await token.getMostRecentSessionByUid(uid);
const rdocs = await record.getByUid(domainId, uid);
const pdict = await problem.getList(
@@ -310,7 +311,7 @@ class OauthCallbackHandler extends Handler {
if (args.type === 'github') r = await this.github(args);
else if (args.type === 'google') r = await this.google(args);
else throw new UserFacingError('Oauth type');
const udoc = await user.getByEmail('system', r.email, true);
const udoc = await user.getByEmail('system', r.email);
if (udoc) {
this.session.uid = udoc._id;
} else {