From faec4744d74440fe6b421c05227e8cf3b595a125 Mon Sep 17 00:00:00 2001 From: masnn Date: Thu, 4 Jun 2020 13:27:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86=E5=9F=9F=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E4=B8=8E=E7=B3=BB=E7=BB=9F=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 2 +- hydro/handler/domain.js | 147 ++++++++++++++++++ hydro/handler/manage.js | 129 +-------------- hydro/handler/misc.js | 9 +- hydro/handler/user.js | 6 +- hydro/lib/nav.js | 2 +- hydro/loader.js | 2 +- hydro/model/setting.js | 1 + hydro/service/monitor.js | 2 +- module/module-pastebin/model.js | 21 +-- templates/domain_base.html | 33 ++++ templates/domain_dashboard.html | 22 +++ .../{manage_edit.html => domain_edit.html} | 5 +- ...permission.html => domain_permission.html} | 4 +- .../{manage_role.html => domain_role.html} | 4 +- .../{manage_user.html => domain_user.html} | 4 +- templates/home_file.html | 2 +- templates/manage_base.html | 11 -- templates/partials/setting.html | 7 + ....page.styl => domain_permission.page.styl} | 0 ...anage_role.page.js => domain_role.page.js} | 2 +- ...e_role.page.styl => domain_role.page.styl} | 0 ...anage_user.page.js => domain_user.page.js} | 2 +- ...e_user.page.styl => domain_user.page.styl} | 0 24 files changed, 249 insertions(+), 168 deletions(-) create mode 100644 hydro/handler/domain.js create mode 100644 templates/domain_base.html create mode 100644 templates/domain_dashboard.html rename templates/{manage_edit.html => domain_edit.html} (90%) rename templates/{manage_permission.html => domain_permission.html} (96%) rename templates/{manage_role.html => domain_role.html} (97%) rename templates/{manage_user.html => domain_user.html} (98%) rename ui/pages/{manage_permission.page.styl => domain_permission.page.styl} (100%) rename ui/pages/{manage_role.page.js => domain_role.page.js} (98%) rename ui/pages/{manage_role.page.styl => domain_role.page.styl} (100%) rename ui/pages/{manage_user.page.js => domain_user.page.js} (98%) rename ui/pages/{manage_user.page.styl => domain_user.page.styl} (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 233cfd787..c00e3487b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node_version: '13.x' + node-version: '13.x' - run: cd ui && yarn && yarn build:production && cd .. - uses: actions/upload-artifact@v1 with: diff --git a/hydro/handler/domain.js b/hydro/handler/domain.js new file mode 100644 index 000000000..ade24319f --- /dev/null +++ b/hydro/handler/domain.js @@ -0,0 +1,147 @@ +const user = require('../model/user'); +const domain = require('../model/domain'); +const { Route, Handler } = require('../service/server'); +const { PERM_MANAGE } = require('../permission'); +const { RoleAlreadyExistError, ValidationError } = require('../error'); + +class ManageHandler extends Handler { + async prepare({ domainId }) { + this.checkPerm(PERM_MANAGE); + this.domain = await domain.get(domainId); + } +} + +class DomainEditHandler extends ManageHandler { + async get() { + const path = [ + ['Hydro', '/'], + ['domain', '/domain'], + ['domain_edit', null], + ]; + this.response.template = 'domain_edit.html'; + this.response.body = { domain: this.domain, path }; + } + + async post({ + domainId, name, gravatar, bulletin, + }) { + await domain.edit(domainId, { name, gravatar, bulletin }); + this.response.redirect = '/domain/dashboard'; + } +} + +class DomainDashboardHandler extends ManageHandler { + async get() { + const path = [ + ['Hydro', '/'], + ['domain', '/domain'], + ['domain_dashboard', null], + ]; + this.response.template = 'domain_dashboard.html'; + this.response.body = { domain: this.domain, path }; + } +} + +class DomainUserHandler extends ManageHandler { + async get({ domainId }) { + const uids = []; + const rudocs = {}; + const [udocs, roles] = await Promise.all([ + user.getInDomain(domainId), + user.getRoles(domainId), + ]); + for (const role of roles) rudocs[role._id] = []; + for (const udoc of udocs) { + uids.push(udoc.uid); + // TODO Improve here + // eslint-disable-next-line no-await-in-loop + const ud = await user.getById(domainId, udoc.uid); + rudocs[udoc.role].push({ ...ud, role: udoc.role }); + } + const rolesSelect = roles.map((role) => [role._id, role._id]); + const udict = await user.getList(domainId, uids); + const path = [ + ['Hydro', '/'], + ['domain', '/domain'], + ['domain_user', null], + ]; + this.response.template = 'domain_user.html'; + this.response.body = { + roles, rolesSelect, rudocs, udict, path, domain: this.domain, + }; + } + + async postSetUser({ domainId, uid, role }) { + await user.setRole(domainId, uid, role); + this.back(); + } +} + +class DomainPermissionHandler extends ManageHandler { + async get({ domainId }) { + const roles = await user.getRoles(domainId); + const path = [ + ['Hydro', '/'], + ['domain', '/domain'], + ['domain_permission', null], + ]; + this.response.template = 'domain_permission.html'; + this.response.body = { roles, domain: this.domain, path }; + } + + async post({ domainId }) { + const roles = {}; + for (const role in this.request.body) { + if (this.request.body[role] instanceof Array) { + roles[role] = this.request.body[role].join(''); + } + } + await user.setRoles(domainId, roles); + this.back(); + } +} + +class DomainRoleHandler extends ManageHandler { + async get({ domainId }) { + const roles = await user.getRoles(domainId); + const path = [ + ['Hydro', '/'], + ['domain', '/domain'], + ['domain_role', null], + ]; + this.response.template = 'domain_role.html'; + this.response.body = { roles, domain: this.domain, path }; + } + + async postAdd({ domainId, role }) { + const [r, u] = await Promise.all([ + user.getRole(domainId, role), + user.getRole(domainId, 'default'), + ]); + if (r) throw new RoleAlreadyExistError(role); + await user.addRole(domainId, role, u.perm); + this.back(); + } + + async postDelete({ roles }) { + for (const role of roles) { + if (['root', 'default', 'guest'].includes(role)) { + throw new ValidationError('role'); + } + } + await user.deleteRoles(roles); + this.back(); + } +} + +async function apply() { + Route('/domain/dashboard', DomainDashboardHandler); + Route('/domain/edit', DomainEditHandler); + Route('/domain/user', DomainUserHandler); + Route('/domain/permission', DomainPermissionHandler); + Route('/domain/role', DomainRoleHandler); +} + +global.Hydro.handler.domain = module.exports = { + apply, +}; diff --git a/hydro/handler/manage.js b/hydro/handler/manage.js index 61409ad19..79590aa8d 100644 --- a/hydro/handler/manage.js +++ b/hydro/handler/manage.js @@ -1,4 +1,3 @@ -const user = require('../model/user'); const domain = require('../model/domain'); const setting = require('../model/setting'); const system = require('../model/system'); @@ -6,7 +5,7 @@ const { Route, Handler } = require('../service/server'); const { PERM_MANAGE } = require('../permission'); const hpm = require('../lib/hpm'); const loader = require('../loader'); -const { RoleAlreadyExistError, ValidationError, PermissionError } = require('../error'); +const { PermissionError } = require('../error'); class ManageHandler extends Handler { async prepare({ domainId }) { @@ -33,124 +32,6 @@ class ManageDashboardHandler extends ManageHandler { } } -class ManageEditHandler extends ManageHandler { - async get() { - const path = [ - ['Hydro', '/'], - ['manage', '/manage'], - ['manage_edit', null], - ]; - this.response.template = 'manage_edit.html'; - this.response.body = { domain: this.domain, path }; - } - - async post({ - domainId, name, gravatar, bulletin, - }) { - await domain.edit(domainId, { name, gravatar, bulletin }); - this.response.redirect = '/manage/dashboard'; - } -} - -class ManageUserHandler extends ManageHandler { - async get({ domainId }) { - // FIXME(masnn) UPDATE CODE - const uids = []; - const rudocs = {}; - const [udocs, roles] = await Promise.all([ - user.getInDomain(domainId), - user.getRoles(domainId), - ]); - for (const role of roles) rudocs[role._id] = []; - for (const udoc of udocs) { - uids.push(udoc.uid); - // TODO Improve here - // eslint-disable-next-line no-await-in-loop - const ud = await user.getById(domainId, udoc.uid); - rudocs[udoc.role].push({ ...ud, role: udoc.role }); - } - const rolesSelect = roles.map((role) => [role._id, role._id]); - const udict = await user.getList(domainId, uids); - const path = [ - ['Hydro', '/'], - ['manage', '/manage'], - ['manage_user', null], - ]; - this.response.template = 'manage_user.html'; - this.response.body = { - roles, rolesSelect, rudocs, udict, path, - }; - } - - async postSetUser({ domainId, uid, role }) { - await user.setRole(domainId, uid, role); - this.back(); - } -} - -class ManagePermissionHandler extends ManageHandler { - async get({ domainId }) { - const [roles, d] = await Promise.all([ - user.getRoles(domainId), - domain.get(domainId), - ]); - const path = [ - ['Hydro', '/'], - ['manage', '/manage'], - ['manage_permission', null], - ]; - this.response.template = 'manage_permission.html'; - this.response.body = { roles, domain: d, path }; - } - - async post({ domainId }) { - const roles = {}; - for (const role in this.request.body) { - if (this.request.body[role] instanceof Array) { - roles[role] = this.request.body[role].join(''); - } - } - await user.setRoles(domainId, roles); - this.back(); - } -} - -class ManageRoleHandler extends ManageHandler { - async get({ domainId }) { - const [roles, d] = await Promise.all([ - user.getRoles(domainId), - domain.get(domainId), - ]); - const path = [ - ['Hydro', '/'], - ['manage', '/manage'], - ['manage_role', null], - ]; - this.response.template = 'manage_role.html'; - this.response.body = { roles, domain: d, path }; - } - - async postAdd({ domainId, role }) { - const [r, u] = await Promise.all([ - user.getRole(domainId, role), - user.getRole(domainId, 'default'), - ]); - if (r) throw new RoleAlreadyExistError(role); - await user.addRole(domainId, role, u.perm); - this.back(); - } - - async postDelete({ roles }) { - for (const role of roles) { - if (['root', 'default', 'guest'].includes(role)) { - throw new ValidationError('role'); - } - } - await user.deleteRoles(roles); - this.back(); - } -} - class SystemHandler extends Handler { async prepare() { if (!this.user.priv) throw new PermissionError('???'); @@ -210,10 +91,6 @@ class SystemSettingHandler extends SystemHandler { async function apply() { Route('/manage', module.exports.ManageMainHandler); Route('/manage/dashboard', module.exports.ManageDashboardHandler); - Route('/manage/edit', module.exports.ManageEditHandler); - Route('/manage/user', module.exports.ManageUserHandler); - Route('/manage/permission', module.exports.ManagePermissionHandler); - Route('/manage/role', module.exports.ManageRoleHandler); Route('/manage/module', SystemModuleHandler); Route('/manage/setting', SystemSettingHandler); } @@ -221,10 +98,6 @@ async function apply() { global.Hydro.handler.manage = module.exports = { ManageMainHandler, ManageDashboardHandler, - ManageEditHandler, - ManageUserHandler, - ManagePermissionHandler, - ManageRoleHandler, SystemModuleHandler, SystemSettingHandler, apply, diff --git a/hydro/handler/misc.js b/hydro/handler/misc.js index 7caf7c5ea..66e18e5cf 100644 --- a/hydro/handler/misc.js +++ b/hydro/handler/misc.js @@ -32,7 +32,13 @@ class StatusHandler extends Handler { class StatusUpdateHandler extends Handler { async post(args) { this.checkPerm(PERM_JUDGE); - await coll.updateOne({ _id: args._id }, { $set: args }, { upsert: true }); + await coll.updateOne({ _id: args._id }, { $set: { ...args, type: 'judger' } }, { upsert: true }); + } +} + +class SwitchLanguageHandler extends Handler { + async get({ lang }) { + this.session.language = lang; } } @@ -41,6 +47,7 @@ async function apply() { Route('/fs/:id/:name/:secret', FileDownloadHandler); Route('/status', StatusHandler); Route('/status/update', StatusUpdateHandler); + Route('/language/:lang', SwitchLanguageHandler); } global.Hydro.handler.misc = module.exports = { diff --git a/hydro/handler/user.js b/hydro/handler/user.js index 287d860f6..f61420364 100644 --- a/hydro/handler/user.js +++ b/hydro/handler/user.js @@ -54,7 +54,7 @@ class UserRegisterHandler extends Handler { } async post({ mail }) { - if (await user.getByEmail(mail, true)) throw new UserAlreadyExistError(mail); + if (await user.getByEmail('system', mail, true)) throw new UserAlreadyExistError(mail); this.limitRate('send_mail', 3600, 30); const t = await token.add( token.TYPE_REGISTRATION, @@ -62,7 +62,9 @@ class UserRegisterHandler extends Handler { { mail }, ); if (await system.get('smtp.user')) { - const m = await this.renderHTML('user_register_mail', { url: `/register/${t[0]}` }); + const m = await this.renderHTML('user_register_mail.html', { + url: `${await system.get('baseurl')}/register/${t[0]}`, + }); await sendMail(mail, 'Sign Up', 'user_register_mail', m); this.response.template = 'user_register_mail_sent.html'; } else { diff --git a/hydro/lib/nav.js b/hydro/lib/nav.js index e36010850..4efd49d65 100644 --- a/hydro/lib/nav.js +++ b/hydro/lib/nav.js @@ -14,6 +14,6 @@ Item('/t', 'training_main', 'training', permission.PERM_VIEW_TRAINING); Item('/homework', 'homework_main', 'homework', permission.PERM_VIEW_HOMEWORK); Item('/discuss', 'discussion_main', 'discussion', permission.PERM_VIEW_DISCUSSION); Item('/c', 'contest_main', 'contest', permission.PERM_VIEW_CONTEST); -Item('/manage', 'manage', 'manage', permission.PERM_MANAGE); +Item('/domain', 'domain_dashboard', 'domain', permission.PERM_MANAGE); global.Hydro.lib.nav = module.exports = Item; diff --git a/hydro/loader.js b/hydro/loader.js index 1591550e4..19edfdd2d 100644 --- a/hydro/loader.js +++ b/hydro/loader.js @@ -252,7 +252,7 @@ async function load() { const builtinHandler = [ 'home', 'problem', 'record', 'judge', 'user', 'contest', 'training', 'discussion', 'manage', 'import', - 'misc', 'homework', + 'misc', 'homework', 'domain', ]; for (const i of builtinHandler) require(`./handler/${i}`); await model(); diff --git a/hydro/model/setting.js b/hydro/model/setting.js index 8345cf4cc..31d5de443 100644 --- a/hydro/model/setting.js +++ b/hydro/model/setting.js @@ -44,6 +44,7 @@ const SETTINGS_BY_KEY = {}; for (const setting in SETTINGS) SETTINGS_BY_KEY[setting.key] = setting; const SYSTEM_SETTINGS = [ + Setting('setting_basic', 'user.register', null, false, 'checkbox', 'Allow register'), Setting('setting_smtp', 'smtp.user', null, null, 'text', 'SMTP Username'), Setting('setting_smtp', 'smtp.pass', null, null, 'password', 'SMTP Password'), Setting('setting_smtp', 'smtp.host', null, null, 'text', 'SMTP Server Host'), diff --git a/hydro/service/monitor.js b/hydro/service/monitor.js index 8378289b7..7b97a48f1 100644 --- a/hydro/service/monitor.js +++ b/hydro/service/monitor.js @@ -16,7 +16,7 @@ async function postInit() { const info = await sysinfo.get(); await coll.updateOne( { _id: info._id }, - { $set: { ...info, updateAt: new Date() } }, + { $set: { ...info, updateAt: new Date(), type: 'server' } }, { upsert: true }, ); setInterval(update, 3 * 60 * 1000); diff --git a/module/module-pastebin/model.js b/module/module-pastebin/model.js index 4738ad994..7b3f59d7a 100644 --- a/module/module-pastebin/model.js +++ b/module/module-pastebin/model.js @@ -1,26 +1,27 @@ const { DocumentNotFoundError } = global.Hydro.error; -const { db } = global.Hydro.service; +const { document } = global.Hydro.model; -const coll = db.collection('pastebin'); +document.TYPE_PASTE = 101; -async function add({ +function add({ owner, language, expire, password, title, content, }) { - const doc = { - owner, password, expire, language, title, content, - }; - const res = await coll.insertOne(doc); - return res.insertedId; + return document.add( + 'system', content, owner, document.TYPE_PASTE, null, null, null, + { + language, expire, title, password, + }, + ); } async function get(_id) { - const doc = await coll.findOne({ _id }); + const doc = await document.get('system', document.TYPE_PASTE, _id); if (!doc) throw new DocumentNotFoundError(_id); return doc; } function del(_id) { - return coll.deleteOne({ _id }); + return document.deleteOne('system', document.TYPE_PASTE, _id); } global.Hydro.model.pastebin = module.exports = { add, get, del }; diff --git a/templates/domain_base.html b/templates/domain_base.html new file mode 100644 index 000000000..aefb890a5 --- /dev/null +++ b/templates/domain_base.html @@ -0,0 +1,33 @@ +{% extends "layout/basic.html" %} +{% block content %} +
+
+ {% block domain_content %}{% endblock %} +
+
+
+ +
+
+
+{% endblock %} diff --git a/templates/domain_dashboard.html b/templates/domain_dashboard.html new file mode 100644 index 000000000..935a2de5e --- /dev/null +++ b/templates/domain_dashboard.html @@ -0,0 +1,22 @@ +{% import "components/user.html" as user %} +{% extends "domain_base.html" %} +{% block domain_content %} +{% if domain.bulletin %} +
+
+ {{ domain.bulletin|markdown|safe }} +
+
+{% endif %} +
+
+

{{ _('Information') }}

+
+
+
+
{{ _('Gravatar') }}
+
{{ _('Name') }}
{{ domain.name }}
+
+
+
+{% endblock %} diff --git a/templates/manage_edit.html b/templates/domain_edit.html similarity index 90% rename from templates/manage_edit.html rename to templates/domain_edit.html index 876271704..0bd0f7235 100644 --- a/templates/manage_edit.html +++ b/templates/domain_edit.html @@ -1,6 +1,5 @@ -{% import "components/form.html" as form with context %} -{% extends "manage_base.html" %} -{% block manage_content %} +{% extends "domain_base.html" %} +{% block domain_content %}
diff --git a/templates/manage_permission.html b/templates/domain_permission.html similarity index 96% rename from templates/manage_permission.html rename to templates/domain_permission.html index f73dc7755..d2fb0fc23 100644 --- a/templates/manage_permission.html +++ b/templates/domain_permission.html @@ -1,5 +1,5 @@ -{% extends "manage_base.html" %} -{% block manage_content %} +{% extends "domain_base.html" %} +{% block domain_content %}
diff --git a/templates/manage_role.html b/templates/domain_role.html similarity index 97% rename from templates/manage_role.html rename to templates/domain_role.html index d76259ec5..0e4dd9b63 100644 --- a/templates/manage_role.html +++ b/templates/domain_role.html @@ -1,5 +1,5 @@ -{% extends "manage_base.html" %} -{% block manage_content %} +{% extends "domain_base.html" %} +{% block domain_content %}