From f055d79fefb2beedb5e774c73cb88786389ccff2 Mon Sep 17 00:00:00 2001 From: masnn Date: Thu, 9 Apr 2020 21:43:16 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=98=E7=9B=AE=E7=BC=96=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=95=B0=E6=8D=AE=E4=B8=8A=E4=BC=A0=EF=BC=8C?= =?UTF-8?q?=E8=AF=84=E6=B5=8B=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hydro/error.js | 1 - hydro/handler/judge.js | 7 +++-- hydro/handler/problem.js | 38 ++++++++++++++++++++++++---- hydro/handler/ui.js | 5 +++- hydro/lib/validator.js | 16 ++++++------ hydro/model/problem.js | 33 ++++++++++++++++-------- templates/partials/path.html | 2 +- templates/partials/problem_list.html | 2 +- templates/problem_upload.html | 4 +-- 9 files changed, 76 insertions(+), 32 deletions(-) diff --git a/hydro/error.js b/hydro/error.js index 3447ac18..d0daa718 100644 --- a/hydro/error.js +++ b/hydro/error.js @@ -1,7 +1,6 @@ class UserFacingError extends Error { constructor(type) { super(type); - this.template = 'error'; this.code = 500; //this.stack = ''; this.params = []; diff --git a/hydro/handler/judge.js b/hydro/handler/judge.js index d8e7af38..4f6d6869 100644 --- a/hydro/handler/judge.js +++ b/hydro/handler/judge.js @@ -2,6 +2,7 @@ const { requirePerm } = require('./tools'), { PERM_JUDGE } = require('../permission'), record = require('../model/record'), + problem = require('../model/problem'), bus = require('../service/bus'), queue = require('../service/queue'), { GET, POST } = require('../service/server'); @@ -15,11 +16,12 @@ GET('/judge/fetch', requirePerm(PERM_JUDGE), async ctx => { let rid = await queue.get('judge', false); if (rid) { let rdoc = await record.get(rid); + let pdoc = await problem.getById(rdoc.pid); let task = { event: 'judge', rid, type: 0, pid: rdoc.pid, - data: rdoc.data, + data: pdoc.data, lang: rdoc.lang, code: rdoc.code }; @@ -28,6 +30,7 @@ GET('/judge/fetch', requirePerm(PERM_JUDGE), async ctx => { else ctx.body = {}; }); POST('/judge/next', requirePerm(PERM_JUDGE), async ctx => { + console.log(ctx.request.body); let body = ctx.request.body; let rdoc = await record.get(body.rid); let $set = {}; @@ -40,7 +43,7 @@ POST('/judge/next', requirePerm(PERM_JUDGE), async ctx => { $set.judgeTexts = rdoc.judgeTexts; } if (body.compiler_text) { - rdoc.compilerTexts.push(body.compilerTexts); + rdoc.compilerTexts.push(body.compiler_text); $set.compilerTexts = rdoc.compilerTexts; } if (body.status) $set.status = body.status; diff --git a/hydro/handler/problem.js b/hydro/handler/problem.js index e448cbc5..b4f98c17 100644 --- a/hydro/handler/problem.js +++ b/hydro/handler/problem.js @@ -80,11 +80,12 @@ GET('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => { }; }); POST('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => { + let pdoc = await problem.get({ pid: ctx.params.pid }); let rid = await record.add({ uid: ctx.state.user._id, lang: ctx.request.body.lang, code: ctx.request.body.code, - pid: ctx.params.pid + pid: pdoc._id }); await queue.push('judge', rid); ctx.state.user.nSubmit++; @@ -94,7 +95,7 @@ POST('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => { GET('/p/:pid/settings', async ctx => { ctx.templateName = 'problem_settings.html'; let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id }); - if (pdoc.hidden) ctx.checkPerm(PERM_VIEW_PROBLEM_HIDDEN); + if (pdoc.owner != ctx.state.user._id) ctx.checkPerm(PERM_EDIT_PROBLEM); ctx.body = { path: [ ['Hydro', '/'], @@ -109,12 +110,36 @@ POST('/p/:pid/settings', async ctx => { // TODO(masnn) ctx.back(); }); +GET('/p/:pid/edit', async ctx => { + ctx.templateName = 'problem_edit.html'; + let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id }); + if (pdoc.owner != ctx.state.user._id) ctx.checkPerm(PERM_EDIT_PROBLEM); + ctx.body = { + path: [ + ['Hydro', '/'], + ['problem_main', '/p'], + [pdoc.title, `/p/${ctx.params.pid}`, true], + ['problem_edit', null] + ], + pdoc, page_name: 'problem_edit' + }; +}); +POST('/p/:pid/edit', async ctx => { + let title = validator.checkTitle(ctx.request.body.title); + let content = validator.checkContent(ctx.request.body.content); + let pid = validator.checkPid(ctx.request.body.pid); + let pdoc = await problem.get({ pid: ctx.params.pid }); + await problem.edit(pdoc._id, { + title, content, pid + }); + ctx.setRedirect = `/p/${pid}`; +}); GET('/p/:pid/upload', async ctx => { ctx.templateName = 'problem_upload.html'; let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id }); if (pdoc.owner != ctx.state.user._id) ctx.checkPerm(PERM_EDIT_PROBLEM); let md5; - if (typeof pdoc.data == 'object') { + if (pdoc.data && typeof pdoc.data == 'object') { let files = await gridfs.find({ _id: pdoc.data }).toArray(); md5 = files[0].md5; } @@ -133,11 +158,14 @@ POST('/p/:pid/upload', async ctx => { f.once('error', reject); }); let md5; - if (typeof pdoc.data == 'object') { + if (pdoc.data && typeof pdoc.data == 'object') { + gridfs.delete(pdoc.data); + } + pdoc = await problem.edit(pdoc._id, { data: f.id }); + if (pdoc.data && typeof pdoc.data == 'object') { let files = await gridfs.find({ _id: pdoc.data }).toArray(); md5 = files[0].md5; } - pdoc = await problem.edit(ctx.params.pid, { data: f.id }); ctx.body = { pdoc, md5 }; }); GET('/p/:pid/data', async ctx => { diff --git a/hydro/handler/ui.js b/hydro/handler/ui.js index 174d85ee..520b6f8c 100644 --- a/hydro/handler/ui.js +++ b/hydro/handler/ui.js @@ -128,7 +128,10 @@ MIDDLEWARE(async (ctx, next) => { } else { throw new NotFoundError(); } - } catch (error) { + } catch (e) { + let error; + if (ctx.body && ctx.body.error) error = ctx.body.error; + else error = e; if (error instanceof NotFoundError) ctx.status = 404; if (error.toString().startsWith('NotFoundError')) console.log(error); if (error.toString().startsWith('Template render error')) throw error; diff --git a/hydro/lib/validator.js b/hydro/lib/validator.js index f1132636..d67c43bd 100644 --- a/hydro/lib/validator.js +++ b/hydro/lib/validator.js @@ -7,21 +7,21 @@ const const isTitle = s => s && s.length < 64, - checkTitle = s => { if (!isTitle(s)) throw new ValidationError('title'); }, + checkTitle = s => { if (!isTitle(s)) throw new ValidationError('title'); else return s; }, isUid = s => RE_UID.test(s), - checkUid = s => { if (!isUid(s)) throw new ValidationError('uid'); }, + checkUid = s => { if (!isUid(s)) throw new ValidationError('uid'); else return s; }, isUname = s => RE_UNAME.test(s), - checkUname = s => { if (!isUname(s)) throw new ValidationError('uname'); }, + checkUname = s => { if (!isUname(s)) throw new ValidationError('uname'); else return s; }, isPassword = s => s.length >= 5, - checkPassword = s => { if (!isPassword(s)) throw new ValidationError('password'); }, + checkPassword = s => { if (!isPassword(s)) throw new ValidationError('password'); else return s; }, isEmail = s => RE_MAIL.test(s), - checkEmail = s => { if (!isEmail(s)) throw new ValidationError('mail'); }, + checkEmail = s => { if (!isEmail(s)) throw new ValidationError('mail'); else return s; }, isContent = s => s && s.length < 65536, - checkContent = s => { if (!isContent(s)) throw new ValidationError('content'); }, + checkContent = s => { if (!isContent(s)) throw new ValidationError('content'); else return s; }, isName = s => s && s.length < 256, - checkName = s => { if (!isName(s)) throw new ValidationError('name'); }, + checkName = s => { if (!isName(s)) throw new ValidationError('name'); else return s; }, isPid = s => RE_PID.test(s.toString()), - checkPid = s => { if (!RE_PID.test(s)) throw new ValidationError('pid'); }; + checkPid = s => { if (!RE_PID.test(s)) throw new ValidationError('pid'); else return s; }; module.exports = { isTitle, checkTitle, diff --git a/hydro/model/problem.js b/hydro/model/problem.js index 7155d344..a78216d2 100644 --- a/hydro/model/problem.js +++ b/hydro/model/problem.js @@ -1,6 +1,7 @@ const - validator = require('../lib/validator'), + { ObjectID } = require('bson'), { ProblemNotFoundError } = require('../error'), + validator = require('../lib/validator'), db = require('../service/db.js'), coll = db.collection('problem'), coll_status = db.collection('problem.status'); @@ -42,23 +43,32 @@ async function add({ return pid; } async function get({ pid, uid }) { - pid = parseInt(pid) || pid; - let pdoc = await coll.findOne({ pid }); + let query = {}; + if (pid.generationTime || pid.length == 24) query = { _id: new ObjectID(pid) }; + else query = { pid: parseInt(pid) || pid }; + let pdoc = await coll.findOne(query); if (!pdoc) throw new ProblemNotFoundError(pid); - pdoc.psdoc = uid ? - await coll_status.findOne({ pid, uid }) : - null; + if (uid) { + query.uid = uid; + pdoc.psdoc = await coll_status.findOne(query); + } + return 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(); } -async function edit(pid, $set) { +async function edit(_id, $set) { if ($set.title) validator.checkTitle($set.title); if ($set.content) validator.checkContent($set.content); - await coll.findOneAndUpdate({ pid }, { $set }); - let pdoc = await coll.findOne({ pid }); - if (!pdoc) throw new ProblemNotFoundError(pid); + await coll.findOneAndUpdate({ _id }, { $set }); + let pdoc = await getById(_id); + if (!pdoc) throw new ProblemNotFoundError(_id); return pdoc; } async function count(query) { @@ -80,5 +90,6 @@ module.exports = { getMany, edit, count, - random + random, + getById }; \ No newline at end of file diff --git a/templates/partials/path.html b/templates/partials/path.html index b669c3ed..d6b57b44 100644 --- a/templates/partials/path.html +++ b/templates/partials/path.html @@ -8,7 +8,7 @@ / {% if c[1] %}{{ c[0] if c[2] else _(c[0]) }}{% endif %} {%- endfor %} -

{{ path[path.length - 1][0] if path[path.length - 1][0] else _(path[path.length - 1][0]) }}

+

{{ path[path.length - 1][0] if path[path.length - 1][2] else _(path[path.length - 1][0]) }}

{% include "partials/hamburger.html" %} diff --git a/templates/partials/problem_list.html b/templates/partials/problem_list.html index 398b4df0..93af487f 100644 --- a/templates/partials/problem_list.html +++ b/templates/partials/problem_list.html @@ -3,7 +3,7 @@ {% import "components/problem.html" as problem with context %} {% import "components/nothing.html" as nothing with context %}
-{% if not pdocs %} +{% if not pdocs.length %} {{ nothing.render('Sorry, there is no problem in the problem set') }} {% else %} diff --git a/templates/problem_upload.html b/templates/problem_upload.html index 10736d76..c9edb37a 100644 --- a/templates/problem_upload.html +++ b/templates/problem_upload.html @@ -4,8 +4,8 @@ {% if (typeof(pdoc.data) == 'string') %}

{{ _('Current dataset comes from') }} {{ pdoc.data.split('from:')[1] }}

{% else %} -

{{ _('Current dataset: {0}').format(pdoc['data'].toString()|default(_('(None)'))) }}

-

{{ _('MD5: {0}').format(md5|default(_('(None)'))) }}

+

{{ _('Current dataset: {0}').format((pdoc['data'] or _('(None)')).toString()) }}

+

{{ _('MD5: {0}').format(md5 or _('(None)')) }}

{% endif %}

{{ _('New dataset') }}: