模块管理器

This commit is contained in:
undefined committed 2020-05-05 12:07:34 +08:00
1 parent 04941936bc
commit 3e9b074e77
22 files changed
+191 -59

No files matched your search

+1 -1
View File
@@ -9,7 +9,7 @@ process.stdin.on('data', async (input) => {
}
});
require('./loader')().catch((e) => {
require('./loader').load().catch((e) => {
console.error(e);
process.exit(1);
});
+23 -5
View File
@@ -1,6 +1,8 @@
const user = require('../model/user');
const { Route, Handler } = require('../service/server');
const { PERM_MANAGE } = require('../permission');
const hpm = require('../lib/hpm');
const loader = require('../loader');
const { RoleAlreadyExistError, ValidationError } = require('../error');
class ManageHandler extends Handler {
@@ -18,14 +20,14 @@ class ManageMainHandler extends ManageHandler {
class ManageDashboardHandler extends ManageHandler {
async get() {
this.response.template = 'domain_manage_dashboard.html';
this.response.template = 'manage_dashboard.html';
this.response.body = { system: this.system };
}
}
class ManageEditHandler extends ManageHandler {
async get() {
this.response.template = 'domain_manage_edit.html';
this.response.template = 'manage_edit.html';
this.response.body = { system: this.system };
}
@@ -54,7 +56,7 @@ class ManageUserHandler extends ManageHandler {
}
const rolesSelect = roles.map((role) => [role._id, role._id]);
const udict = await user.getList(uids);
this.response.template = 'domain_manage_user.html';
this.response.template = 'manage_user.html';
this.response.body = {
roles, rolesSelect, rudocs, udict, system,
};
@@ -72,7 +74,7 @@ class ManagePermissionHandler extends ManageHandler {
user.getRoles(),
user.getById(0),
]);
this.response.template = 'domain_manage_permission.html';
this.response.template = 'manage_permission.html';
this.response.body = { roles, system };
}
@@ -95,7 +97,7 @@ class ManageRoleHandler extends ManageHandler {
user.getRoles(),
user.getById(0),
]);
this.response.template = 'domain_manage_role.html';
this.response.template = 'manage_role.html';
this.response.body = { roles, system };
}
@@ -120,6 +122,20 @@ class ManageRoleHandler extends ManageHandler {
}
}
class ManageModuleHandler extends ManageHandler {
async get() {
const installed = await hpm.getInstalled();
const active = loader.active.map((module) => module.id);
this.response.body = { installed, active };
this.response.template = 'manage_module.html';
}
async postDelete({ id }) {
await hpm.del(id);
this.back();
}
}
async function apply() {
Route('/manage', module.exports.ManageMainHandler);
Route('/manage/dashboard', module.exports.ManageDashboardHandler);
@@ -127,6 +143,7 @@ async function apply() {
Route('/manage/user', module.exports.ManageUserHandler);
Route('/manage/permission', module.exports.ManagePermissionHandler);
Route('/manage/role', module.exports.ManageRoleHandler);
Route('/manage/module', module.exports.ManageModuleHandler);
}
global.Hydro.handler.manage = module.exports = {
@@ -136,5 +153,6 @@ global.Hydro.handler.manage = module.exports = {
ManageUserHandler,
ManagePermissionHandler,
ManageRoleHandler,
ManageModuleHandler,
apply,
};
+39
View File
@@ -0,0 +1,39 @@
/* eslint-disable import/no-dynamic-require */
/* eslint-disable no-await-in-loop */
/* eslint-disable no-eval */
const fs = require('fs');
const zlib = require('zlib');
const path = require('path');
const yaml = require('js-yaml');
const download = require('./download');
function root(name) {
return path.resolve(process.cwd(), name);
}
async function getInstalled() {
const files = fs.readdirSync(root('.build/module'));
const installed = [];
for (const file of files) {
if (file.endsWith('.hydro-module')) {
const f = fs.readFileSync(root(`.build/module/${file}`));
const s = fs.statSync(root(`.build/module/${file}`));
installed.push({
...yaml.safeLoad(zlib.gunzipSync(f)),
id: file.split('.')[0],
size: s.size,
});
}
}
return installed;
}
async function del(id) {
fs.unlinkSync(root(`.build/module/${id}.hydro-module`));
}
async function install(id, url) {
await download(url, root(`module/${id}.hydro-module`));
}
module.exports = { getInstalled, del, install };
+1 -1
View File
@@ -36,7 +36,7 @@ exports.paginate = function* paginate(page, numPages) {
yield ['last', numPages];
};
exports.format_size = function formatSize(size, base = 1) {
exports.size = function formatSize(size, base = 1) {
size *= base;
const unit = 1024;
const unitNames = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
+1 -1
View File
@@ -13,6 +13,6 @@ Item('/p', 'problem_main', 'problem', permission.PERM_VIEW_PROBLEM);
Item('/t', 'training_main', 'training', permission.PERM_VIEW_TRAINING);
Item('/discuss', 'discussion_main', 'discussion', permission.PERM_VIEW_DISCUSSION);
Item('/c', 'contest_main', 'contest', permission.PERM_VIEW_CONTEST);
Item('/manage', 'domain_manage', 'domain_manage', permission.PERM_MANAGE);
Item('/manage', 'manage', 'manage', permission.PERM_MANAGE);
global.Hydro.lib.nav = module.exports = Item;
+7 -7
View File
@@ -10,20 +10,20 @@ function root(name) {
return path.resolve(process.cwd(), name);
}
const installed = [];
const active = [];
async function preload() {
const files = fs.readdirSync(root('.build/module'));
for (const file of files) {
if (file.endsWith('.hydro-module')) {
const f = fs.readFileSync(root(`.build/module/${file}`));
installed.push({ ...yaml.safeLoad(zlib.gunzipSync(f)), id: file.split('.')[0] });
active.push({ ...yaml.safeLoad(zlib.gunzipSync(f)), id: file.split('.')[0] });
}
}
}
async function handler() {
for (const i of installed) {
for (const i of active) {
if (i.handler) {
console.time(`Handler init: ${i.id}`);
const module = {}; // eslint-disable-line no-unused-vars
@@ -35,7 +35,7 @@ async function handler() {
}
async function locale() {
for (const i of installed) {
for (const i of active) {
if (i.locale) {
global.Hydro.lib.i18n(i.locale);
console.log(`Locale init: ${i.id}`);
@@ -44,7 +44,7 @@ async function locale() {
}
async function template() {
for (const i of installed) {
for (const i of active) {
if (i.template) {
Object.assign(global.Hydro.template, i.template);
console.log(`Template init: ${i.id}`);
@@ -53,7 +53,7 @@ async function template() {
}
async function model() {
for (const i of installed) {
for (const i of active) {
if (i.model) {
console.time(`Model init: ${i.id}`);
const module = {};
@@ -125,4 +125,4 @@ async function load() {
server.start();
}
module.exports = load;
module.exports = { load, active };
+8 -8
View File
@@ -49,14 +49,14 @@ user_lostpass: Lost Password
user_register: Register
home_domain_create: Create Domain
domain_main: Main
domain_manage: Domain Manage
domain_manage_dashboard: Dashboard
domain_manage_discussion: Discussion Nodes
domain_manage_edit: Edit Info
domain_manage_join_applications: Join Applications
domain_manage_role: Domain Role
domain_manage_user: Domain User
domain_manage_permission: Domain Permission
manage: System Manage
manage_dashboard: Dashboard
manage_discussion: Discussion Nodes
manage_edit: Edit Info
manage_join_applications: Join Applications
manage_role: System Role
manage_user: System User
manage_permission: System Permission
timeago_locale: en
perm_general: General
perm_problem: Problems
+8 -8
View File
@@ -307,14 +307,14 @@ Create Domain: 创建域
Properties: 属性
Access Control: 访问控制
domain_main: 首页
domain_manage: 管理域
domain_manage_dashboard: 概况
domain_manage_discussion: 讨论节点
domain_manage_edit: 编辑域资料
domain_manage_join_applications: 加域申请
domain_manage_role: 管理角色
domain_manage_user: 管理用户
domain_manage_permission: 管理权限
manage: 管理域
manage_dashboard: 概况
manage_discussion: 讨论节点
manage_edit: 编辑域资料
manage_join_applications: 加域申请
manage_role: 管理角色
manage_user: 管理用户
manage_permission: 管理权限
domain_join: 加入域
'Join {0}': '加入 {0}'
You are not allowed to join the domain. The link is either invalid or expired.: 您无法加入该域,链接无效或已过期。
+7 -7
View File
@@ -301,13 +301,13 @@ Create Domain: 創建域
Properties: 屬性
Access Control: 訪問控制
domain_main: 首頁
domain_manage: 管理域
domain_manage_dashboard: 概況
domain_manage_edit: 編輯域資料
domain_manage_join_applications: 加域申請
domain_manage_role: 管理角色
domain_manage_user: 管理使用者
domain_manage_permission: 管理許可權
manage: 管理域
manage_dashboard: 概況
manage_edit: 編輯域資料
manage_join_applications: 加域申請
manage_role: 管理角色
manage_user: 管理使用者
manage_permission: 管理許可權
Update Permission: 更新許可權
Roles: 角色
Your role: 您的角色
+7 -6
View File
@@ -2,7 +2,7 @@
{% block content %}
<div class="row" data-sticky-parent>
<div class="medium-9 columns">
{% block domain_content %}{% endblock %}
{% block manage_content %}{% endblock %}
</div>
<div class="medium-3 columns"><div data-sticky="large">
<div class="section side">
@@ -12,8 +12,9 @@
<span class="icon icon-info"></span> {{ _('Properties') }}
</div>
<ol class="menu collapsed">
{{ sidemenu.render_item(null, 'domain_manage_dashboard', '/manage/dashboard') }}
{{ sidemenu.render_item(null, 'domain_manage_edit', '/manage/edit') }}
{{ sidemenu.render_item(null, 'manage_dashboard', '/manage/dashboard') }}
{{ sidemenu.render_item(null, 'manage_edit', '/manage/edit') }}
{{ sidemenu.render_item(null, 'manage_module', '/manage/module') }}
</ol>
</li>
<li class="menu__item">
@@ -21,9 +22,9 @@
<span class="icon icon-user"></span> {{ _('Access Control') }}
</div>
<ol class="menu collapsed">
{{ sidemenu.render_item(null, 'domain_manage_role', '/manage/role') }}
{{ sidemenu.render_item(null, 'domain_manage_user', '/manage/user') }}
{{ sidemenu.render_item(null, 'domain_manage_permission', '/manage/permission') }}
{{ sidemenu.render_item(null, 'manage_role', '/manage/role') }}
{{ sidemenu.render_item(null, 'manage_user', '/manage/user') }}
{{ sidemenu.render_item(null, 'manage_permission', '/manage/permission') }}
</ol>
</li>
</ol>
@@ -1,7 +1,7 @@
{% set page_name = "domain_manage_dashboard" %}
{% set page_name = "manage_dashboard" %}
{% import "components/user.html" as user %}
{% extends "manage_base.html" %}
{% block domain_content %}
{% block manage_content %}
{% if system.bio %}
<div class="section">
<div class="section__body typo">
@@ -1,7 +1,7 @@
{% set page_name = "domain_manage_edit" %}
{% set page_name = "manage_edit" %}
{% import "components/form.html" as form with context %}
{% extends "manage_base.html" %}
{% block domain_content %}
{% block manage_content %}
<div class="section">
<div class="section__body">
<form method="post">
+53
View File
@@ -0,0 +1,53 @@
{% set page_name = "manage_module" %}
{% extends "manage_base.html" %}
{% block manage_content %}
<div class="section">
<div class="section__header">
<h1 class="section__title">{{ _('Installed Modules') }}</h1>
<div class="section__tools">
<a class="primary rounded button" href="/manage/module/add" target="_blank"><span class="icon icon-add"></span> {{ _('Add module') }}</a>
<a class="tool-button" href="/wiki/help#module"><span class="icon icon-help"></span> {{ _("What's module?") }}</a>
</div>
</div>
<div class="section__body no-padding">
<table class="data-table">
<colgroup>
<col class="col--id">
<col class="col--desc">
<col class="col--size">
<col class="col--version">
<col class="col--action">
</colgroup>
<thead>
<tr>
<th class="col--id">{{ _('ID') }}</th>
<th class="col--desc">{{ _('Description') }}</th>
<th class="col--size">{{ _('Size') }}</th>
<th class="col--version">{{ _('Version') }}</th>
<th class="col--action">{{ _('Action') }}</th>
</tr>
</thead>
<tbody>
{% for module in installed %}
<tr>
<td class="col--id">{{ module.id }}{{ _('(Active)') if active.includes(module.id) else '' }}</td>
<td class="col--desc">{{ module.description|default(_('None')) }}</td>
<td class="col--size">{{ size(module.size) if module.size else '?' }}</td>
<td class="col--version">{{ module.version|default('?') }}</td>
<td class="col--action">
<a class="typo-a" href="/manage/module/download/{{ module.id }}">{{ _('Download') }}</a>
<form method="post">
<input type="hidden" name="operation" value="delete">
<input type="hidden" name="id" value="{{ module.id }}">
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
<input type="submit" class="typo-a" value="{{ _('Delete') }}">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
@@ -1,6 +1,6 @@
{% set page_name = "domain_manage_permission" %}
{% set page_name = "manage_permission" %}
{% extends "manage_base.html" %}
{% block domain_content %}
{% block manage_content %}
<form method="post">
<div class="section">
<div class="section__header">
@@ -1,6 +1,6 @@
{% set page_name = "domain_manage_role" %}
{% set page_name = "manage_role" %}
{% extends "manage_base.html" %}
{% block domain_content %}
{% block manage_content %}
<div style="display: none" class="dialog__body--create-role">
<div>
<div class="row"><div class="columns">
@@ -1,6 +1,6 @@
{% set page_name = "domain_manage_user" %}
{% set page_name = "manage_user" %}
{% extends "manage_base.html" %}
{% block domain_content %}
{% block manage_content %}
<div style="display: none" class="dialog__body--add-user">
<div>
<div class="row"><div class="columns">
+21
View File
@@ -0,0 +1,21 @@
.page--manage_module
.col--id
width: 70px
line-height: 1
.col--desc
width: rem(160px)
border-left: 1px solid $table-border-color
.col--size
width: 35px
.col--version
width: 40px
.col--action
width: rem(75px)
+mobile()
.col--desc, .col--version
display: none
@@ -1,4 +1,4 @@
.page--domain_manage_permission
.page--manage_permission
.col--p
width: 80px
text-align: center
@@ -9,7 +9,7 @@ import tpl from 'vj/utils/tpl';
import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
const page = new NamedPage('domain_manage_role', () => {
const page = new NamedPage('manage_role', () => {
const createRoleDialog = new ActionDialog({
$body: $('.dialog__body--create-role > div'),
onDispatch(action) {
@@ -1,4 +1,4 @@
.page--domain_manage_role
.page--manage_role
.col--checkbox
width: 60px
@@ -10,7 +10,7 @@ import tpl from 'vj/utils/tpl';
import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
const page = new NamedPage('domain_manage_user', () => {
const page = new NamedPage('manage_user', () => {
const addUserSelector = UserSelectAutoComplete.getOrConstruct($('.dialog__body--add-user [name="user"]'));
const addUserDialog = new ActionDialog({
$body: $('.dialog__body--add-user > div'),
@@ -1,4 +1,4 @@
.page--domain_manage_user
.page--manage_user
.col--checkbox
width: 60px