mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 17:36:08 +08:00
模块管理器
This commit is contained in:
1 parent
04941936bc
commit
3e9b074e77
22 files changed
+191
-59
No files matched your search
@@ -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
@@ -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,
|
||||
};
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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: 您的角色
|
||||
|
||||
@@ -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">
|
||||
@@ -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">
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user