diff --git a/hydro/handler/contest.js b/hydro/handler/contest.js index d26d4bf6c..ebb10c80f 100644 --- a/hydro/handler/contest.js +++ b/hydro/handler/contest.js @@ -250,15 +250,12 @@ class ContestCreateHandler extends ContestHandler { } async post({ title, content, rule, beginAtDate, beginAtTime, duration, pids }) { let beginAt, endAt; - console.log(beginAtDate, beginAtTime); try { beginAt = new Date(Date.parse(`${beginAtDate} ${beginAtTime.replace('-', ':')}`)); - console.log(beginAt, duration); } catch (e) { throw new ValidationError('beginAtDate', 'beginAtTime'); } endAt = new Date(beginAt.getTime() + duration * 3600 * 1000); - console.log(endAt); if (beginAt >= endAt) throw new ValidationError('duration'); await this.verifyProblems(pids); let tid = await contest.add(title, content, this.user._id, rule, beginAt, endAt, pids); diff --git a/hydro/handler/judge.js b/hydro/handler/judge.js index 3ea79bb96..a88bc4294 100644 --- a/hydro/handler/judge.js +++ b/hydro/handler/judge.js @@ -56,10 +56,12 @@ async function end(body) { } class JudgeHandler extends Handler { - async prepare(){ + async prepare() { this.checkPerm(PERM_JUDGE); } - async get() { + async get({ check = false }) { + this.response.body = {}; + if (check) return; let rid = await queue.get('judge', false); if (rid) { let rdoc = await record.get(rid); @@ -74,7 +76,6 @@ class JudgeHandler extends Handler { }; this.response.body = { task }; } - else this.response.body = {}; } async post_next() { await next(this.request.body); diff --git a/hydro/handler/problem.js b/hydro/handler/problem.js index 58998e0a9..bbeda8206 100644 --- a/hydro/handler/problem.js +++ b/hydro/handler/problem.js @@ -56,7 +56,7 @@ class ProblemDetailHandler extends ProblemHandler { this.response.template = 'problem_detail.html'; this.uid = this.user._id; this.pid = pid; - if (pid) this.pdoc = await problem.get(this); + if (pid) this.pdoc = await problem.get(this.pid, this.uid); if (this.pdoc.hidden && this.pdoc.owner != this.uid) this.checkPerm(PERM_VIEW_PROBLEM_HIDDEN); if (this.pdoc) this.udoc = await user.getById(this.pdoc.owner); this.response.body = { @@ -115,7 +115,7 @@ class ProblemManageHandler extends ProblemDetailHandler { class ProblemSettingsHandler extends ProblemManageHandler { async get() { this.response.template = 'problem_settings.html'; - this.ctx.body.path = [ + this.response.body.path = [ ['Hydro', '/'], ['problem_main', '/p'], [this.pdoc.title, `/p/${this.pid}`, true], @@ -141,15 +141,14 @@ class ProblemEditHandler extends ProblemManageHandler { } async post({ title, content }) { let pid = validator.checkPid(this.request.body.pid); - let pdoc = await problem.get({ pid: this.params.pid }); + let pdoc = await problem.get(this.params.pid); await problem.edit(pdoc._id, { title, content, pid }); this.response.redirect = `/p/${pid}`; } } class ProblemDataUploadHandler extends ProblemManageHandler { - constructor(ctx) { - super(ctx); + async prepare(){ this.response.template = 'problem_upload.html'; } async get() { diff --git a/hydro/handler/record.js b/hydro/handler/record.js index 28883b0f3..7e32d6112 100644 --- a/hydro/handler/record.js +++ b/hydro/handler/record.js @@ -17,7 +17,7 @@ class RecordListHandler extends Handler { let pdict = {}, udict = {}; for (let rdoc of rdocs) { udict[rdoc.uid] = await user.getById(rdoc.uid); - pdict[rdoc.pid] = await problem.get({ pid: rdoc.pid, uid: this.user._id }); + pdict[rdoc.pid] = await problem.get(rdoc.pid, this.user._id); } this.response.body = { path: [ @@ -51,7 +51,7 @@ class RecordRejudgeHandler extends Handler { await record.reset(rid); await queue.push('judge', rid); } - this.response.back(); + this.back(); } } class RecordConnectionHandler extends ConnectionHandler { @@ -70,7 +70,7 @@ class RecordConnectionHandler extends ConnectionHandler { async onRecordChange(data) { let rdoc = data.value; if (rdoc.tid && rdoc.tid.toString() != this.tid) return; - let [udoc, pdoc] = await Promise.all([user.getById(rdoc.uid), problem.get({ pid: rdoc.pid })]); + let [udoc, pdoc] = await Promise.all([user.getById(rdoc.uid), problem.getById(rdoc.pid)]); if (pdoc.hidden && !this.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN)) pdoc = null; this.send({ html: await this.renderHTML('record_main_tr.html', { rdoc, udoc, pdoc }) }); } diff --git a/hydro/install.js b/hydro/install.js index e052f57a1..8cb493b33 100644 --- a/hydro/install.js +++ b/hydro/install.js @@ -1,8 +1,11 @@ +require('./utils'); const Mongo = require('mongodb'), + { defaults } = require('lodash'), builtin = require('./model/builtin'), pwhash = require('./lib/pwhash'), - options = require('./options'); + options = require('./options'), + { udoc } = require('../interfaces'); async function run() { let mongourl = 'mongodb://'; @@ -13,30 +16,47 @@ async function run() { let coll_user = db.collection('user'); let coll_role = db.collection('role'); let coll_blacklist = db.collection('blacklist'); - async function createRootUser() { + let coll_token = db.collection('token'); + async function createUser() { let salt = pwhash.salt(); - await coll_user.insertOne({ - _id: -1, - email: 'root@hydro', - emailLower: 'root@hydro', - uname: 'Root', - unameLower: 'root', - password: pwhash.hash('root', salt), - salt, - regat: new Date(), - regip: '127.0.0.1', - loginat: new Date(), - loginip: '127.0.0.1', - gravatar: 'root@hydro', - role: 'admin' - }); + await coll_user.insertMany([ + defaults({ + _id: 0, + uname: 'Hydro', + unameLower: 'hydro', + mail: 'hydro@hydro', + mailLower: 'hydro@hydro', + role: 'guest' + }, udoc), + defaults({ + _id: 1, + mail: 'guest@hydro', + mailLower: 'guest@hydro', + uname: 'Guest', + unameLower: 'guest', + role: 'guest' + }, udoc), + defaults({ + _id: -1, + mail: 'root@hydro', + mailLower: 'root@hydro', + uname: 'Root', + unameLower: 'root', + hash: pwhash.hash('rootroot', salt), + salt, + gravatar: 'root@hydro', + role: 'admin' + }, udoc) + ]); } await coll_user.createIndex('unameLower', { unique: true }); - await coll_user.createIndex('emailLower', { sparse: true }); + await coll_user.createIndex('mailLower', { sparse: true }); await coll_role.insertMany(builtin.BUILTIN_ROLES); await coll_user.insertMany(builtin.BUILTIN_USERS); await coll_blacklist.createIndex('expireAt', { expireAfterSeconds: 0 }); - await createRootUser(); + await coll_token.createIndex([{ uid: 1 }, { tokenType: 1 }, { updateAt: -1 }], { sparse: true }); + await coll_token.createIndex('expireAt', { expireAfterSeconds: 0 }); + await createUser(); console.log('Installed'); process.exit(0); } diff --git a/hydro/interface.js b/hydro/interface.js new file mode 100644 index 000000000..b804ebed8 --- /dev/null +++ b/hydro/interface.js @@ -0,0 +1,72 @@ +const { ObjectID } = require('bson'); +exports.udoc = { + _id: 0, + mail: '', + mailLower: '', + uname: '', + unameLower: '', + salt: '', + hash: '', + hashType: 'hydro', + nAccept: 0, + nSubmit: 0, + nLike: 0, + bio: '', + gender: 0, + regat: new Date(), + regip: '0.0.0.0', + gravatar: '', + loginat: new Date(), + loginip: '0.0.0.0' +}; +/* +export interface Pdoc { + _id: ObjectID + pid: string + owner: number + title: string + content: string + nSubmit: number + nAccept: number + tag: string[] + category: string[], + data: ObjectID | null + hidden: boolean +} +export interface TestCase { + time: number, + memory: number, + status: number, + message: string +} +export interface Rdoc { + _id: ObjectID, + pid: ObjectID, + owner: number, + lang: string, + code: string, + score: number, + memory: number, + time: number, + judgeTexts: string[], + compilerTexts: string[], + testCases: TestCase[], + rejudged: boolean, + judger: string, + judgeAt: Date, + status: number +} +export interface Bdoc { + _id: string, + expireAt: Date +} +export interface Tdoc { + _id: ObjectID + beginAt: Date + endAt: Date + attend: number + title: string + content: string + pids: ObjectID[] +} +*/ \ No newline at end of file diff --git a/hydro/interface.ts b/hydro/interface.ts index a705e6faf..76236fcc2 100644 --- a/hydro/interface.ts +++ b/hydro/interface.ts @@ -1,18 +1,33 @@ -export class User { +import { ObjectID } from 'bson'; + +export interface Udoc { _id: number - email: string - emailLower: string + mail: string + mailLower: string uname: string unameLower: string salt: string hash: string - displayName: string = '' - nAccept: number = 0 - nSubmit: number = 0 - perm: string = '0' - constructor(user) { } - hasPerm(perm) { } - checkPassword(password) { } + hashType: string + nAccept: number + nSubmit: number + nLike: number + perm: string + hasPerm: Function + checkPassword: Function +} +export interface Pdoc { + _id: ObjectID + pid: string + owner: number + title: string + content: string + nSubmit: number + nAccept: number + tag: string[] + category: string[], + data: ObjectID | null + hidden: boolean } export interface TestCase { time: number, @@ -20,10 +35,10 @@ export interface TestCase { status: number, message: string } -export interface Record { - _id: import('bson').ObjectID, - pid: string | boolean, - creator: number, +export interface Rdoc { + _id: ObjectID, + pid: ObjectID, + owner: number, lang: string, code: string, score: number, @@ -32,18 +47,21 @@ export interface Record { judgeTexts: string[], compilerTexts: string[], testCases: TestCase[], + rejudged: boolean, judger: string, judgeAt: Date, status: number } -export interface Problem { - _id: number | string, - title: string, - content: string, - timeLimit: number, - memoryLimit: number, - nSubmit: number, - nAccept: number, - tags: string[], - categories: string[] +export interface Bdoc { + _id: string, + expireAt: Date +} +export interface Tdoc { + _id: ObjectID + beginAt: Date + endAt: Date + attend: number + title: string + content: string + pids: ObjectID[] } \ No newline at end of file diff --git a/hydro/model/blacklist.js b/hydro/model/blacklist.js index bb78cd7e5..6d8f2c7e9 100644 --- a/hydro/model/blacklist.js +++ b/hydro/model/blacklist.js @@ -2,11 +2,15 @@ const db = require('../service/db.js'), coll = db.collection('blacklist'); -module.exports = { - add(ip) { - let expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000); - return coll.findOneAndUpdate({ _id: ip }, { $set: { expireAt } }, { upsert: true }); - }, - get: ip => coll.findOne({ _id: ip }), - delete: ip => coll.deleteOne({ _id: ip }) -}; \ No newline at end of file +async function add(ip) { + let expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000); + return coll.findOneAndUpdate({ _id: ip }, { $set: { expireAt } }, { upsert: true }); +} +function get(ip) { + return coll.findOne({ _id: ip }); +} +function del(ip) { + return coll.deleteOne({ _id: ip }); +} + +module.exports = { add, get, del }; diff --git a/hydro/model/builtin.js b/hydro/model/builtin.js index c88e7a686..ece50b0ed 100644 --- a/hydro/model/builtin.js +++ b/hydro/model/builtin.js @@ -1,37 +1,4 @@ const perm = require('../permission'); -const BUILTIN_USERS = [ - { - _id: 0, - uname: 'Hydro', - unameLower: 'hydro', - email: '', - emailLower: '', - salt: '', - hash: '', - gender: 'other', - regat: new Date(), - regip: '127.0.0.1', - gravatar: '', - loginat: new Date(), - loginip: '127.0.0.1', - role: 'guest' - }, - { - _id: 1, - email: 'guest@hydro', - emailLower: 'guest@hydro', - uname: 'Guest', - unameLower: 'guest', - hash: '', - salt: '', - regat: new Date(), - regip: '127.0.0.1', - loginat: new Date(), - loginip: '127.0.0.1', - gravatar: 'guest@hydro', - role: 'guest' - } -]; const BUILTIN_ROLES = [ { _id: 'guest', perm: perm.PERM_BASIC }, { _id: 'default', perm: perm.PERM_DEFAULT }, @@ -262,6 +229,6 @@ const STATUS_CODES = { 30: 'ignored' }; module.exports = { - BUILTIN_USERS, BUILTIN_ROLES, CATEGORIES, VIEW_LANGS, FOOTER_EXTRA_HTMLS, LANGS, + BUILTIN_ROLES, CATEGORIES, VIEW_LANGS, FOOTER_EXTRA_HTMLS, LANGS, LANG_TEXTS, LANG_HIGHLIGHT_ID, STATUS, STATUS_TEXTS, STATUS_CODES }; \ No newline at end of file diff --git a/hydro/model/contest.js b/hydro/model/contest.js index 4ea3b9279..02b6eb4ad 100644 --- a/hydro/model/contest.js +++ b/hydro/model/contest.js @@ -5,13 +5,28 @@ const coll = db.collection('contest'), coll_status = db.collection('contest.status'); - const RULES = { homework: require('../module/contest/homework'), oi: require('../module/contest/oi'), acm: require('../module/contest/acm') }; +/** + * @typedef {import('bson').ObjectID} ObjectID + * @typedef {import('../interface').Tdoc} Tdoc + */ + +/** + * @param {string} title + * @param {string} content + * @param {number} owner + * @param {string} rule + * @param {Date} beginAt + * @param {Date} endAt + * @param {ObjectID[]} pids + * @param {object} data + * @returns {ObjectID} tid + */ async function add(title, content, owner, rule, beginAt = new Date(), endAt = new Date(), pids = [], data = {}) { validator.checkTitle(title); @@ -23,6 +38,11 @@ async function add(title, content, owner, rule, let res = await coll.insertOne(data); return res.insertedId; } +/** + * @param {ObjectID} tid + * @param {object} $set + * @returns {Tdoc} tdoc after modification + */ async function edit(tid, $set) { if ($set.title) validator.checkTitle($set.title); if ($set.content) validator.checkIntro($set.content); @@ -36,6 +56,10 @@ async function edit(tid, $set) { await coll.findOneAndUpdate({ tid }, { $set }); return tdoc; } +/** + * @param {ObjectID} tid + * @returns {Tdoc} + */ async function get(tid) { let tdoc = await coll.findOne({ _id: tid }); if (!tdoc) throw new ContestNotFoundError(tid); diff --git a/hydro/model/problem.js b/hydro/model/problem.js index 7f48f6b17..a214f0d3c 100644 --- a/hydro/model/problem.js +++ b/hydro/model/problem.js @@ -6,6 +6,12 @@ const coll = db.collection('problem'), coll_status = db.collection('problem.status'); +/** + * @typedef {import('../interface').Pdoc} Pdoc + * @typedef {import('bson').ObjectID} ObjectID + * @typedef {import('mongodb').Cursor} Cursor + */ + /** * @param {string} title * @param {string} content @@ -42,7 +48,12 @@ async function add({ }); return pid; } -async function get({ pid, uid }) { +/** + * @param {string|ObjectID} pid + * @param {number} uid + * @returns {Pdoc} + */ +async function get(pid, uid = null) { let query = {}; if (pid.generationTime || pid.length == 24) query = { _id: new ObjectID(pid) }; else query = { pid: parseInt(pid) || pid }; @@ -54,18 +65,36 @@ async function get({ pid, uid }) { } return pdoc; } +/** + * @param {ObjectID} pid + * @returns {Pdoc} + */ async function getById(_id) { _id = new ObjectID(_id); let pdoc = await coll.findOne({ _id }); if (!pdoc) throw new ProblemNotFoundError(_id); return pdoc; } -async function getMany(query, sort, page, limit) { - return await coll.find(query).sort(sort).skip((page - 1) * limit).limit(limit).toArray(); +/** + * @param {string|ObjectID} pid + * @param {number} uid + * @returns {Pdoc[]} + */ +function getMany(query, sort, page, limit) { + return coll.find(query).sort(sort).skip((page - 1) * limit).limit(limit).toArray(); } +/** + * @param {object} query + * @returns {Cursor} + */ function getMulti(query) { return coll.find(query); } +/** + * @param {ObjectID} _id + * @param {object} query + * @returns {Pdoc} + */ async function edit(_id, $set) { if ($set.title) validator.checkTitle($set.title); if ($set.content) validator.checkContent($set.content); @@ -74,6 +103,10 @@ async function edit(_id, $set) { if (!pdoc) throw new ProblemNotFoundError(_id); return pdoc; } +/** + * @param {object} query + * @returns {number} + */ async function count(query) { return await coll.find(query).count(); } @@ -87,7 +120,7 @@ async function random(query) { } async function getList(pids) { let r = {}; - for (let pid of pids) r[pid] = await get({pid}); + for (let pid of pids) r[pid] = await get({ pid }); return r; } diff --git a/hydro/model/record.js b/hydro/model/record.js index 926fb2b57..7f5c649a3 100644 --- a/hydro/model/record.js +++ b/hydro/model/record.js @@ -55,7 +55,8 @@ async function reset(rid) { judgeTexts: [], compilerTexts: [], judgeAt: null, - judger: null + judger: null, + rejudged: true }); } async function count(query) { @@ -66,6 +67,9 @@ async function getList(rids) { for (let rid of rids) r[rid] = await get(rid); return r; } +function getUserInProblemMulti(uid, pid) { + return coll.find({ owner: uid, pid }); +} module.exports = { add, @@ -74,5 +78,6 @@ module.exports = { update, count, reset, - getList + getList, + getUserInProblemMulti }; \ No newline at end of file diff --git a/hydro/model/token.js b/hydro/model/token.js index e01a6277a..0ee36d25c 100644 --- a/hydro/model/token.js +++ b/hydro/model/token.js @@ -67,9 +67,5 @@ module.exports = { }, async getMostRecentSessionByUid(uid) { return await coll.findOne({ uid, token_type: this.TYPE_SESSION }, { sort: { updateAt: -1 } }); - }, - init: () => Promise.all([ - coll.createIndex([{ uid: 1 }, { tokenType: 1 }, { updateAt: -1 }], { sparse: true }), - coll.createIndex('expireAt', { expireAfterSeconds: 0 }) - ]) -}; \ No newline at end of file + } +}; diff --git a/hydro/model/user.js b/hydro/model/user.js index bc23b0c26..575adffcb 100644 --- a/hydro/model/user.js +++ b/hydro/model/user.js @@ -10,7 +10,7 @@ const class USER { constructor(user) { this._id = user._id; - this.email = user.email; + this.mail = user.mail; this.uname = user.uname; this.salt = user.salt; this.hash = user.hash; @@ -52,12 +52,12 @@ async function getByUname(uname) { udoc.perm = role.perm; return new USER(udoc); } -async function getByEmail(email, ignoreMissing = false) { - let emailLower = email.trim().toLowerCase(); - let udoc = await coll.findOne({ emailLower }); +async function getByEmail(mail, ignoreMissing = false) { + let mailLower = mail.trim().toLowerCase(); + let udoc = await coll.findOne({ mailLower }); if (!udoc) { if (ignoreMissing) return null; - else throw new UserNotFoundError(email); + else throw new UserNotFoundError(mail); } let role = await coll_role.findOne({ _id: udoc.role || 'default' }); udoc.perm = role.perm; @@ -70,9 +70,9 @@ async function setPassword(uid, password) { $set: { salt, hash: pwhash.hash(password, salt) } }); } -async function setEmail(uid, email) { - validator.checkEmail(email); - return await setById(uid, { email, emailLower: email.trim().toLowerCase() }); +async function setEmail(uid, mail) { + validator.checkEmail(mail); + return await setById(uid, { mail, mailLower: mail.trim().toLowerCase() }); } function setById(uid, args) { coll.findOneAndUpdate({ _id: uid }, { $set: args }); @@ -88,17 +88,17 @@ async function changePassword(uid, currentPassword, newPassword) { $set: { salt, hash: pwhash.hash(newPassword, salt) } }); } -async function create({ uid, email, uname, password, regip = '127.0.0.1', role = 'default' }) { +async function create({ uid, mail, uname, password, regip = '127.0.0.1', role = 'default' }) { validator.checkUname(uname); validator.checkPassword(password); - validator.checkEmail(email); + validator.checkEmail(mail); let salt = pwhash.salt(); if (!uid) uid = system.incUserCounter(); try { await coll.insertOne({ _id: uid, - email, - emailLower: email.trim().toLowerCase(), + mail, + mailLower: mail.trim().toLowerCase(), uname, unameLower: uname.trim().toLowerCase(), password: pwhash.hash(password, salt), @@ -108,7 +108,7 @@ async function create({ uid, email, uname, password, regip = '127.0.0.1', role = loginat: new Date(), loginip: regip, role, - gravatar: email + gravatar: mail }); } catch (e) { throw new UserAlreadyExistError([uid, uname, email]); diff --git a/hydro/options.js b/hydro/options.js index ea0f3cb36..a02b45db8 100644 --- a/hydro/options.js +++ b/hydro/options.js @@ -1,6 +1,6 @@ const yaml = require('js-yaml'), - { defaults } = require('lodash'), + { defaultsDeep } = require('lodash'), fs = require('fs'), path = require('path'); @@ -47,7 +47,7 @@ let options = { try { let t = yaml.safeLoad(fs.readFileSync(path.resolve(process.cwd(), 'config.yaml'))); - options = defaults(t, options); + options = defaultsDeep(t, options); } catch (e) { console.error('Cannot load config'); } diff --git a/hydro/service/bus.js b/hydro/service/bus.js index d675fc90d..f1c82aeb1 100644 --- a/hydro/service/bus.js +++ b/hydro/service/bus.js @@ -12,4 +12,4 @@ module.exports = { publish(event, data) { bus.emit(event, { value: data, event }); } -}; \ No newline at end of file +}; diff --git a/hydro/service/server.js b/hydro/service/server.js index f622c5781..571f09981 100644 --- a/hydro/service/server.js +++ b/hydro/service/server.js @@ -13,7 +13,8 @@ const blacklist = require('../model/blacklist'), token = require('../model/token'), opcount = require('../model/opcount'), - { UserNotFoundError, BlacklistedError, PermissionError } = require('../error'); + { UserNotFoundError, BlacklistedError, PermissionError, + NotFoundError } = require('../error'); const options = require('../options'); let http = options.listen.https ? require('https') : require('http'); @@ -49,7 +50,7 @@ class Handler { this.response = { body: '', type: '', - status: 404, + status: null, template: null, redirect: null, attachment: name => ctx.attachment(name) @@ -102,9 +103,10 @@ class Handler { await opcount.inc(op, this.request.ip, period_secs, max_operations); } back() { - this.ctx.redirect(this.request.headers.referer || '/'); + this.response.redirect = this.request.headers.referer || '/'; } async ___prepare() { + this.now = new Date(); this._handler.sid = this.request.cookies.get('sid'); this._handler.save = this.request.cookies.get('save'); this._handler.tokenType = token.TYPE_SESSION; @@ -119,9 +121,8 @@ class Handler { let bdoc = await blacklist.get(this.request.ip); if (bdoc) throw new BlacklistedError(this.request.ip); this.user = await user.getById(this.session.uid); - console.log(this.user, this.session.uid); if (!this.user) throw new UserNotFoundError(this.session.uid); - this.csrf_token = (await token.add(token.TYPE_CSRF_TOKEN, 600, this.request.path))[0]; + this.csrf_token = (await token.add(token.TYPE_CSRF_TOKEN, 600, { path: this.request.path }))[0]; this.preferJson = (this.request.headers['accept'] || '').includes('application/json'); } async ___cleanup() { @@ -135,6 +136,10 @@ class Handler { await this.saveCookie(); } async renderBody() { + if (!(this.response.body || this.response.template)) { + this.response.body = { error: new NotFoundError() }; + this.response.template = 'error.html'; + } if (!this.preferJson) if (this.response.body || this.response.template) { if (this.request.query.noTemplate || this.preferJson) return; @@ -150,9 +155,11 @@ class Handler { this.ctx.response.status = 302; this.ctx.redirect(this.response.redirect); } else { - if (this.response.body) this.ctx.body = this.response.body; + if (this.response.body != null) { + this.ctx.response.body = this.response.body; + this.ctx.response.status = this.response.status || 200; + } if (this.response.type) this.ctx.response.type = this.response.type; - if (this.response.status) this.ctx.response.status = this.response.status; } } async saveCookie() { @@ -210,7 +217,6 @@ function Route(route, handler) { if (h[`_${method}`]) await h[`_${method}`](args); if (h[method]) await h[method](args); - console.log(ctx.request.body); if (method == 'post' && ctx.request.body.operation) { if (h[`${method}_${ctx.request.body.operation}`]) await h[`${method}_${ctx.request.body.operation}`](args); @@ -231,20 +237,22 @@ class ConnectionHandler { * @param {import('sockjs').Connection} conn */ constructor(conn) { + let that = this; this.conn = conn; this.request = { cookies: { get(name) { - return conn.cookies[name]; + return that.request.cookies[name]; }, set() { } }, params: {}, headers: conn.headers }; + this._handler = {}; let p = (conn.url.split('?')[1] || '').split('&'); for (let i in p) p[i] = p[i].split('='); - for (let i in p) conn.params[p[i][0]] = decodeURIComponent(p[i][1]); + for (let i in p) this.request.params[p[i][0]] = decodeURIComponent(p[i][1]); } renderHTML(name, context) { console.time(name); @@ -292,7 +300,7 @@ function Connection(prefix, handler) { sock.on('connection', async conn => { let h = new handler(conn); try { - let args = Object.assign({}, h.conn.params); + let args = Object.assign({}, h.request.params); if (args.uid) args.uid = parseInt(validator.checkUid(args.uid)); if (args.page) args.page = parseInt(args.page); @@ -313,6 +321,7 @@ function Connection(prefix, handler) { if (h.___cleanup) await h.___cleanup(args); }); } catch (e) { + console.log(e); if (h.onerror) await h.onerror(e); } }); diff --git a/templates/components/problem.html b/templates/components/problem.html index 3f9c17991..fa9b38a3b 100644 --- a/templates/components/problem.html +++ b/templates/components/problem.html @@ -4,9 +4,7 @@ {%- if tdoc is none %} href="/p/{{ pdoc.pid }}" {%- elif tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST %} - href="{{ reverse_url('contest_detail_problem', domain_id=pdoc['domain_id'], pid=pdoc['_id'], tid=tdoc['doc_id']) }}" - {%- elif tdoc['doc_type'] == vj4.model.document.TYPE_HOMEWORK %} - href="{{ reverse_url('homework_detail_problem', domain_id=pdoc['domain_id'], pid=pdoc['_id'], tid=tdoc['doc_id']) }}" + href="/t/{{ tdoc._id }}/{{ pdoc._id }}" {%- endif %} > {%- endif %} diff --git a/templates/components/record.html b/templates/components/record.html index fb9843bb3..4573925d8 100644 --- a/templates/components/record.html +++ b/templates/components/record.html @@ -1,9 +1,9 @@ {% macro render_status_td(rdoc, rid_key='_id') %} -