mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 17:38:19 +08:00
优化安装流程
This commit is contained in:
1 parent
63d55cedf4
commit
508f5644c3
30 files changed
+279
-139
No files matched your search
+2
-2
@@ -163,9 +163,9 @@ class RoleAlreadyExistError extends ForbiddenError {
|
||||
}
|
||||
|
||||
class ProblemNotFoundError extends NotFoundError {
|
||||
constructor(pid) {
|
||||
constructor(domainId, pid) {
|
||||
super('ProblemNotFoundError');
|
||||
this.params = [pid];
|
||||
this.params = [domainId, pid];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+34
-22
@@ -1,7 +1,9 @@
|
||||
const { ObjectID } = require('bson');
|
||||
const paginate = require('../lib/paginate');
|
||||
const system = require('../model/system');
|
||||
const user = require('../model/user');
|
||||
const discussion = require('../model/discussion');
|
||||
const document = require('../model/document');
|
||||
const { Route, Handler } = require('../service/server');
|
||||
const { DiscussionNotFoundError, DocumentNotFoundError } = require('../error');
|
||||
const {
|
||||
@@ -10,17 +12,24 @@ const {
|
||||
PERM_LOGGEDIN, PERM_CREATE_DISCUSSION, PERM_REPLY_DISCUSSION,
|
||||
} = require('../permission');
|
||||
|
||||
const typeMapper = {
|
||||
problem: document.TYPE_PROBLEM,
|
||||
contest: document.TYPE_CONTEST,
|
||||
node: document.TYPE_DISCUSSION_NODE,
|
||||
training: document.TYPE_TRAINING,
|
||||
homework: document.TYPE_HOMEWORK,
|
||||
};
|
||||
|
||||
class DiscussionHandler extends Handler {
|
||||
async _prepare({
|
||||
domainId, type = 'node', docId, name, did, drid, drrid,
|
||||
domainId, type, name, did, drid, drrid,
|
||||
}) {
|
||||
this.checkPerm(PERM_VIEW_DISCUSSION);
|
||||
docId = docId || name;
|
||||
if (did) {
|
||||
this.ddoc = await discussion.get(domainId, did);
|
||||
if (!this.ddoc) throw new DiscussionNotFoundError(did);
|
||||
type = this.ddoc.parentType;
|
||||
docId = this.ddoc.parentId;
|
||||
type = discussion.typeDisplay[this.ddoc.parentType];
|
||||
name = this.ddoc.parentId;
|
||||
if (drid) {
|
||||
this.drdoc = await discussion.getReply(domainId, drid, did);
|
||||
if (!this.drdoc) throw new DiscussionNotFoundError(drid);
|
||||
@@ -37,7 +46,11 @@ class DiscussionHandler extends Handler {
|
||||
// TODO(twd2): do more visibility check eg. contest
|
||||
// TODO(twd2): exclude problem/contest discussions?
|
||||
// TODO(iceboy): continuation based pagination.
|
||||
this.vnode = await discussion.getVnode(domainId, { parentType: type, parentId: docId }, this);
|
||||
if (ObjectID.isValid(name)) name = new ObjectID(name);
|
||||
this.vnode = await discussion.getVnode(domainId, {
|
||||
parentType: typeMapper[type],
|
||||
parentId: name,
|
||||
}, this);
|
||||
if (this.ddoc) {
|
||||
this.ddoc.parentType = this.ddoc.parentType || this.vnode.type;
|
||||
this.ddoc.parentId = this.ddoc.parentId || this.vnode.id;
|
||||
@@ -45,7 +58,7 @@ class DiscussionHandler extends Handler {
|
||||
}
|
||||
}
|
||||
|
||||
class DiscussionMainHandler extends DiscussionHandler {
|
||||
class DiscussionMainHandler extends Handler {
|
||||
async get({ domainId, page = 1 }) {
|
||||
const [ddocs, dpcount] = await paginate(
|
||||
discussion.getMulti(domainId),
|
||||
@@ -57,20 +70,20 @@ class DiscussionMainHandler extends DiscussionHandler {
|
||||
['Hydro', '/'],
|
||||
['discussion_main', null],
|
||||
];
|
||||
const vndict = await discussion.getListVnodes(domainId, ddocs, this);
|
||||
this.response.template = 'discussion_main_or_node.html';
|
||||
this.response.body = {
|
||||
ddocs, dpcount, udict, page, page_name: 'discussion_main', vnode: {}, path,
|
||||
ddocs, dpcount, udict, page, page_name: 'discussion_main', vndict, vnode: {}, path,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class DiscussionNodeHandler extends DiscussionHandler {
|
||||
async get({
|
||||
domainId, type = 'node', docId, name, page = 1,
|
||||
domainId, type, name, page = 1,
|
||||
}) {
|
||||
docId = docId || name;
|
||||
const [ddocs, dpcount] = await paginate(
|
||||
discussion.getMulti(domainId, { parentType: type, parentId: docId }),
|
||||
discussion.getMulti(domainId, { parentType: typeMapper[type], parentId: name }),
|
||||
page,
|
||||
await system.get('DISCUSSION_PER_PAGE'),
|
||||
);
|
||||
@@ -80,6 +93,7 @@ class DiscussionNodeHandler extends DiscussionHandler {
|
||||
['discussion_main', '/discuss'],
|
||||
[this.vnode.title, null, true],
|
||||
];
|
||||
const vndict = { [typeMapper[type]]: { [name]: this.vnode } };
|
||||
this.response.template = 'discussion_main_or_node.html';
|
||||
this.response.body = {
|
||||
ddocs,
|
||||
@@ -87,6 +101,7 @@ class DiscussionNodeHandler extends DiscussionHandler {
|
||||
udict,
|
||||
path,
|
||||
page,
|
||||
vndict,
|
||||
vnode: this.vnode,
|
||||
page_name: 'discussion_node',
|
||||
};
|
||||
@@ -99,12 +114,11 @@ class DiscussionCreateHandler extends DiscussionHandler {
|
||||
this.checkPerm(PERM_CREATE_DISCUSSION);
|
||||
}
|
||||
|
||||
async get({ type = 'node', docId, name }) {
|
||||
docId = docId || name;
|
||||
async get({ type, name }) {
|
||||
const path = [
|
||||
['Hydro', '/'],
|
||||
['discussion_main', '/discuss'],
|
||||
[this.vnode.title, `/discuss/${type}/${docId}`, true],
|
||||
[this.vnode.title, `/discuss/${type}/${name}`, true],
|
||||
['discussion_create', null],
|
||||
];
|
||||
this.response.template = 'discussion_create.html';
|
||||
@@ -112,13 +126,13 @@ class DiscussionCreateHandler extends DiscussionHandler {
|
||||
}
|
||||
|
||||
async post({
|
||||
domainId, type = 'node', docId, name, title, content, highlight,
|
||||
domainId, type, name, title, content, highlight,
|
||||
}) {
|
||||
docId = docId || name;
|
||||
this.limitRate('add_discussion', 3600, 30);
|
||||
if (ObjectID.isValid(name)) name = new ObjectID(name);
|
||||
if (highlight) this.checkPerm(PERM_HIGHLIGHT_DISCUSSION);
|
||||
const did = await discussion.add(
|
||||
domainId, type, docId, this.user._id,
|
||||
domainId, typeMapper[type], name, this.user._id,
|
||||
title, content, this.request.ip, highlight,
|
||||
);
|
||||
this.response.body = { did };
|
||||
@@ -136,7 +150,7 @@ class DiscussionDetailHandler extends DiscussionHandler {
|
||||
page,
|
||||
await system.get('REPLY_PER_PAGE'),
|
||||
);
|
||||
const uids = drdocs.map(domainId, (drdoc) => drdoc.owner);
|
||||
const uids = drdocs.map((drdoc) => drdoc.owner);
|
||||
uids.push(this.ddoc.owner);
|
||||
for (const drdoc of drdocs) {
|
||||
if (drdoc.reply) {
|
||||
@@ -149,7 +163,7 @@ class DiscussionDetailHandler extends DiscussionHandler {
|
||||
const path = [
|
||||
['Hydro', '/'],
|
||||
['discussion_main', '/discuss'],
|
||||
[this.vnode.title, `/discuss/${this.ddoc.parentType}`, true],
|
||||
[this.vnode.title, `/discuss/${discussion.typeDisplay[this.ddoc.parentType]}/${this.ddoc.parentId}`, true],
|
||||
[this.ddoc.title, null, true],
|
||||
];
|
||||
this.response.template = 'discussion_detail.html';
|
||||
@@ -275,10 +289,8 @@ async function apply() {
|
||||
Route('/discuss/:did/raw', module.exports.DiscussionDetailRawHandler);
|
||||
Route('/discuss/:did/:drid/raw', module.exports.DiscussionReplyRawHandler);
|
||||
Route('/discuss/:did/:drid/:drrid/raw', module.exports.DiscussionTailReplyRawHandler);
|
||||
Route('/discuss/node/:name', module.exports.DiscussionNodeHandler);
|
||||
Route('/discuss/node/:name/create', module.exports.DiscussionCreateHandler);
|
||||
Route('/discuss/:type/:docId', module.exports.DiscussionNodeHandler);
|
||||
Route('/discuss/:type/:docId/create', module.exports.DiscussionCreateHandler);
|
||||
Route('/discuss/:type/:name', module.exports.DiscussionNodeHandler);
|
||||
Route('/discuss/:type/:name/create', module.exports.DiscussionCreateHandler);
|
||||
}
|
||||
|
||||
global.Hydro.handler.discussion = module.exports = {
|
||||
|
||||
@@ -100,7 +100,6 @@ class HomeSecurityHandler extends Handler {
|
||||
|
||||
async get() {
|
||||
// TODO(iceboy): pagination? or limit session count for uid?
|
||||
// TODO(masnn): UA & IP
|
||||
const sessions = await token.getSessionListByUid(this.user._id);
|
||||
const parsed = [];
|
||||
for (const session of sessions) {
|
||||
@@ -173,8 +172,13 @@ class HomeSettingsHandler extends Handler {
|
||||
}
|
||||
|
||||
async post(args) {
|
||||
// FIXME validation
|
||||
await user.setById(args.domainId, this.user._id, args);
|
||||
const $set = {};
|
||||
for (const key in args) {
|
||||
if (setting.SETTINGS_BY_KEY[args]) {
|
||||
$set[key] = args[key];
|
||||
}
|
||||
}
|
||||
await user.setById(args.domainId, this.user._id, $set);
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -78,10 +78,21 @@ class SystemSettingHandler extends SystemHandler {
|
||||
if (typeof args[key] === 'object') {
|
||||
const subtasks = [];
|
||||
for (const sub in args[key]) {
|
||||
subtasks.push(system.set(`${key}.${sub}`, args[key][sub]));
|
||||
const s = setting.SYSTEM_SETTINGS_BY_KEY[`${key}.${sub}`];
|
||||
if (s) {
|
||||
if (s.ui === 'number') args[key][sub] = Number(args[key][sub]);
|
||||
console.log(s);
|
||||
subtasks.push(system.set(`${key}.${sub}`, args[key][sub]));
|
||||
}
|
||||
}
|
||||
tasks.push(Promise.all(subtasks));
|
||||
} else tasks.push(system.set(key, args[key]));
|
||||
} else {
|
||||
const s = setting.SYSTEM_SETTINGS_BY_KEY[key];
|
||||
if (s) {
|
||||
if (s.ui === 'number') args[key] = Number(args[key]);
|
||||
tasks.push(system.set(key, args[key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
await Promise.all(tasks);
|
||||
this.back();
|
||||
|
||||
@@ -25,9 +25,10 @@ class RecordListHandler extends RecordHandler {
|
||||
];
|
||||
}
|
||||
const rdocs = await record.getMany(domainId, q, { _id: -1 }, page, await system.get('RECORD_PER_PAGE'));
|
||||
console.log(rdocs);
|
||||
const [udict, pdict] = await Promise.all([
|
||||
user.getList(domainId, rdocs.map((rdoc) => rdoc.uid)),
|
||||
problem.getList(domainId, rdocs.map((rdoc) => rdoc.pid)),
|
||||
problem.getList(domainId, rdocs.map((rdoc) => rdoc.pid), false),
|
||||
]);
|
||||
const path = [
|
||||
['Hydro', '/'],
|
||||
|
||||
+1
-1
@@ -22,6 +22,6 @@ 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('/domain/dashboard', 'domain_dashboard', 'domain', permission.PERM_MANAGE);
|
||||
Item('/manage/dashboard', 'manage_dashboard', 'manage', null, (handler) => handler.user.priv === 1);
|
||||
Item('/manage/dashboard', 'manage', 'manage', null, (handler) => handler.user.priv === 1);
|
||||
|
||||
global.Hydro.lib.nav = module.exports = Item;
|
||||
@@ -242,7 +242,7 @@ async function edit(domainId, tid, $set, type = document.TYPE_CONTEST) {
|
||||
* @param {string} domainId
|
||||
* @param {ObjectID} tid
|
||||
* @param {number} type
|
||||
* @returns {Tdoc}
|
||||
* @returns {Promise<Tdoc>}
|
||||
*/
|
||||
async function get(domainId, tid, type = document.TYPE_CONTEST) {
|
||||
let tdoc;
|
||||
|
||||
@@ -2,9 +2,18 @@ const { ObjectID } = require('bson');
|
||||
const problem = require('./problem');
|
||||
const document = require('./document');
|
||||
const contest = require('./contest');
|
||||
const training = require('./training');
|
||||
const { PERM_VIEW_PROBLEM_HIDDEN } = require('../permission');
|
||||
const { DocumentNotFoundError } = require('../error');
|
||||
|
||||
const typeDisplay = {
|
||||
[document.TYPE_PROBLEM]: 'problem',
|
||||
[document.TYPE_CONTEST]: 'contest',
|
||||
[document.TYPE_DISCUSSION_NODE]: 'node',
|
||||
[document.TYPE_TRAINING]: 'training',
|
||||
[document.TYPE_HOMEWORK]: 'homework',
|
||||
};
|
||||
|
||||
function add(domainId, parentType, parentId, owner, title, content, ip = null, highlight = false) {
|
||||
return document.add(
|
||||
domainId, content, owner, document.TYPE_DISCUSSION,
|
||||
@@ -115,9 +124,7 @@ function getStatus(domainId, did, uid) {
|
||||
}
|
||||
|
||||
function addNode(domainId, _id, category) {
|
||||
return document.add(
|
||||
domainId, _id, 1, document.TYPE_DISCUSSION_NODE, null, null, null, { category },
|
||||
);
|
||||
return document.add(domainId, category, 1, document.TYPE_DISCUSSION_NODE, _id);
|
||||
}
|
||||
|
||||
function getNode(domainId, _id) {
|
||||
@@ -125,17 +132,32 @@ function getNode(domainId, _id) {
|
||||
}
|
||||
|
||||
async function getVnode(domainId, ddoc, handler) {
|
||||
if (ddoc.parentType === 'problem') {
|
||||
if (ddoc.parentType === document.TYPE_PROBLEM) {
|
||||
const pdoc = await problem.getById(domainId, ddoc.parentId);
|
||||
if (!pdoc) return null;
|
||||
if (pdoc.hidden && handler) handler.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
|
||||
return { ...pdoc, type: ddoc.parentType, id: ddoc.parentId };
|
||||
} if (ddoc.parentType === 'contest') {
|
||||
}
|
||||
if (ddoc.parentType === document.TYPE_CONTEST) {
|
||||
const tdoc = await contest.get(domainId, ddoc.parentId);
|
||||
return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId };
|
||||
} if (ddoc.parentType === 'node') {
|
||||
}
|
||||
if (ddoc.parentType === document.TYPE_DISCUSSION_NODE) {
|
||||
const ndoc = await getNode(domainId, ddoc.parentId);
|
||||
return { title: ndoc._id, type: ddoc.parentType, id: ddoc.parentId };
|
||||
return {
|
||||
...ndoc,
|
||||
title: ddoc.parentId,
|
||||
type: ddoc.parentType,
|
||||
id: ddoc.parentId,
|
||||
};
|
||||
}
|
||||
if (ddoc.parentType === document.TYPE_TRAINING) {
|
||||
const tdoc = await training.get(domainId, ddoc.parentId);
|
||||
return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId };
|
||||
}
|
||||
if (ddoc.parentType === document.TYPE_HOMEWORK) {
|
||||
const tdoc = await contest.get(domainId, ddoc.parentId, document.TYPE_HOMEWORK);
|
||||
return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId };
|
||||
}
|
||||
return {
|
||||
title: 'Missing Node',
|
||||
@@ -147,13 +169,15 @@ async function getVnode(domainId, ddoc, handler) {
|
||||
async function getListVnodes(domainId, ddocs, handler) {
|
||||
const res = {};
|
||||
for (const ddoc of ddocs) {
|
||||
if (!res[ddoc.parentType]) res[ddoc.parentType] = {};
|
||||
// FIXME no-await-in-loop
|
||||
res[ddoc._id] = await getVnode(domainId, ddoc, handler); // eslint-disable-line no-await-in-loop
|
||||
res[ddoc.parentType][ddoc.parentId] = await getVnode(domainId, ddoc, handler); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
global.Hydro.model.discussion = module.exports = {
|
||||
typeDisplay,
|
||||
add,
|
||||
get,
|
||||
edit,
|
||||
|
||||
+6
-2
@@ -30,8 +30,12 @@ function del(_id) {
|
||||
}
|
||||
|
||||
async function inc(_id) {
|
||||
const file = await coll.findOne({ _id });
|
||||
file.count++;
|
||||
const doc = await coll.findOneAndUpdate(
|
||||
{ _id },
|
||||
{ $inc: { count: 1 } },
|
||||
{ returnOriginal: false },
|
||||
);
|
||||
return (doc.value || {}).count;
|
||||
}
|
||||
|
||||
async function dec(_id) {
|
||||
|
||||
@@ -14,5 +14,6 @@ module.exports = {
|
||||
task: require('./task'),
|
||||
message: require('./message'),
|
||||
setting: require('./setting'),
|
||||
discussion: require('./discussion'),
|
||||
file: require('./file'),
|
||||
};
|
||||
@@ -45,7 +45,7 @@ async function get(domainId, pid, uid = null) {
|
||||
const pdoc = Number.isInteger(pid)
|
||||
? await document.get(domainId, document.TYPE_PROBLEM, pid)
|
||||
: (await document.getMulti(domainId, document.TYPE_PROBLEM, { pid }).toArray())[0];
|
||||
if (!pdoc) throw new ProblemNotFoundError(pid);
|
||||
if (!pdoc) throw new ProblemNotFoundError(domainId, pid);
|
||||
if (uid) {
|
||||
pdoc.psdoc = await document.getStatus(domainId, document.TYPE_PROBLEM, pdoc.docId, uid);
|
||||
}
|
||||
@@ -110,10 +110,15 @@ async function random(domainId, query) {
|
||||
} return null;
|
||||
}
|
||||
|
||||
async function getList(domainId, pids) {
|
||||
async function getList(domainId, pids, doThrow = true) {
|
||||
const r = {};
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
for (const pid of pids) r[pid] = await get(domainId, pid);
|
||||
if (doThrow) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
for (const pid of pids) r[pid] = await get(domainId, pid);
|
||||
} else {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
for (const pid of pids) r[pid] = await get(domainId, pid).catch((e) => e);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
+24
-11
@@ -41,7 +41,7 @@ const ACCOUNT_SETTINGS = [
|
||||
const SETTINGS = [...PREFERENCE_SETTINGS, ...ACCOUNT_SETTINGS];
|
||||
const SETTINGS_BY_KEY = {};
|
||||
|
||||
for (const setting in SETTINGS) SETTINGS_BY_KEY[setting.key] = setting;
|
||||
for (const setting of SETTINGS) SETTINGS_BY_KEY[setting.key] = setting;
|
||||
|
||||
const SYSTEM_SETTINGS = [
|
||||
Setting('setting_basic', 'user.register', null, false, 'checkbox', 'Allow register'),
|
||||
@@ -49,19 +49,32 @@ const SYSTEM_SETTINGS = [
|
||||
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'),
|
||||
Setting('setting_smtp', 'smtp.port', null, 465, 'text', 'SMTP Server Port'),
|
||||
Setting('setting_smtp', 'smtp.port', null, 465, 'number', 'SMTP Server Port'),
|
||||
Setting('setting_smtp', 'smtp.from', null, null, 'text', 'Mail From'),
|
||||
Setting('setting_smtp', 'smtp.secure', null, false, 'checkbox', 'SSL'),
|
||||
Setting('setting_server', 'listen.port', null, 8888, 'text', 'Server Port', ''),
|
||||
Setting('setting_constant', 'PROBLEM_PER_PAGE', null, 100, 'text', 'Problems per Page'),
|
||||
Setting('setting_constant', 'CONTEST_PER_PAGE', null, 20, 'text', 'Contests per Page'),
|
||||
Setting('setting_constant', 'DISCUSSION_PER_PAGE', null, 50, 'text', 'Discussion per Page'),
|
||||
Setting('setting_constant', 'RECORD_PER_PAGE', null, 100, 'text', 'Record per Page'),
|
||||
Setting('setting_constant', 'SOLUTION_PER_PAGE', null, 20, 'text', 'Solutions per Page'),
|
||||
Setting('setting_constant', 'TRAINING_PER_PAGE', null, 10, 'text', 'Training per Page'),
|
||||
Setting('setting_constant', 'REPLY_PER_PAGE', null, 50, 'text', 'Reply per Page'),
|
||||
Setting('setting_server', 'server.hostname', null, null, 'text', 'Server Hostname'),
|
||||
Setting('setting_server', 'server.host', null, null, 'text', 'Server Host'),
|
||||
Setting('setting_server', 'server.url', null, null, 'text', 'Server BaseURL'),
|
||||
Setting('setting_server', 'server.port', null, 8888, 'number', 'Server Port'),
|
||||
Setting('setting_constant', 'PROBLEM_PER_PAGE', null, 100, 'number', 'Problems per Page'),
|
||||
Setting('setting_constant', 'CONTEST_PER_PAGE', null, 20, 'number', 'Contests per Page'),
|
||||
Setting('setting_constant', 'DISCUSSION_PER_PAGE', null, 50, 'number', 'Discussion per Page'),
|
||||
Setting('setting_constant', 'RECORD_PER_PAGE', null, 100, 'number', 'Record per Page'),
|
||||
Setting('setting_constant', 'SOLUTION_PER_PAGE', null, 20, 'number', 'Solutions per Page'),
|
||||
Setting('setting_constant', 'TRAINING_PER_PAGE', null, 10, 'number', 'Training per Page'),
|
||||
Setting('setting_constant', 'REPLY_PER_PAGE', null, 50, 'number', 'Reply per Page'),
|
||||
];
|
||||
|
||||
const SYSTEM_SETTINGS_BY_KEY = {};
|
||||
|
||||
for (const setting of SYSTEM_SETTINGS) SYSTEM_SETTINGS_BY_KEY[setting.key] = setting;
|
||||
|
||||
global.Hydro.model.setting = module.exports = {
|
||||
Setting, PREFERENCE_SETTINGS, ACCOUNT_SETTINGS, SETTINGS, SETTINGS_BY_KEY, SYSTEM_SETTINGS,
|
||||
Setting,
|
||||
PREFERENCE_SETTINGS,
|
||||
ACCOUNT_SETTINGS,
|
||||
SETTINGS,
|
||||
SETTINGS_BY_KEY,
|
||||
SYSTEM_SETTINGS,
|
||||
SYSTEM_SETTINGS_BY_KEY,
|
||||
};
|
||||
@@ -19,7 +19,7 @@ const allowFail = async (func, ...args) => {
|
||||
return res;
|
||||
};
|
||||
|
||||
async function run(username, password) {
|
||||
async function run({ username, password } = {}) {
|
||||
const def = {
|
||||
PROBLEM_PER_PAGE: 100,
|
||||
RECORD_PER_PAGE: 100,
|
||||
@@ -39,7 +39,7 @@ async function run(username, password) {
|
||||
'smtp.pass': '',
|
||||
'smtp.secure': false,
|
||||
'db.ver': 1,
|
||||
'listen.port': 8888,
|
||||
'server.port': 8888,
|
||||
'session.keys': ['Hydro'],
|
||||
'session.secure': false,
|
||||
'session.saved_expire_seconds': 3600 * 24,
|
||||
@@ -49,7 +49,10 @@ async function run(username, password) {
|
||||
};
|
||||
let tasks = [];
|
||||
for (const key in def) {
|
||||
tasks.push(system.set(key, def[key]));
|
||||
tasks.push(system.get(key).then((value) => {
|
||||
if (!value) return system.set(key, def[key]);
|
||||
return Promise.resolve();
|
||||
}));
|
||||
}
|
||||
await Promise.all(tasks);
|
||||
tasks = [
|
||||
@@ -91,12 +94,6 @@ async function run(username, password) {
|
||||
}, { upsert: true }),
|
||||
);
|
||||
}
|
||||
for (const category in builtin.DEFAULT_NODES) {
|
||||
const nodes = builtin.DEFAULT_NODES[category];
|
||||
for (const node of nodes) {
|
||||
tasks.push(discussion.addNode(node.name, category));
|
||||
}
|
||||
}
|
||||
await Promise.all(tasks);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -10,9 +10,9 @@ mongourl += `${options.host}:${options.port}/${options.name}`;
|
||||
*/
|
||||
let db = null;
|
||||
Mongo.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopology: true })
|
||||
.then((Database) => {
|
||||
db = Database.db(options.name);
|
||||
db.Db = Database;
|
||||
.then((Client) => {
|
||||
db = Client.db(options.name);
|
||||
db.Client = Client;
|
||||
bus.publish('system_database_connected', null);
|
||||
});
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ class Handler {
|
||||
constructor(ctx) {
|
||||
this.ctx = ctx;
|
||||
this.request = {
|
||||
host: ctx.request.host,
|
||||
hostname: ctx.request.hostname,
|
||||
ip: ctx.request.ip,
|
||||
headers: ctx.request.headers,
|
||||
cookies: ctx.cookies,
|
||||
@@ -193,8 +195,8 @@ class Handler {
|
||||
token.TYPE_SESSION,
|
||||
this._handler.expireSeconds,
|
||||
{
|
||||
update_ip: this.request.ip,
|
||||
update_ua: this.request.headers['user-agent'] || '',
|
||||
updateIp: this.request.ip,
|
||||
updateUa: this.request.headers['user-agent'] || '',
|
||||
},
|
||||
) : { uid: 1 };
|
||||
if (!this.session) this.session = { uid: 1 };
|
||||
@@ -302,6 +304,9 @@ function Route(route, RouteHandler, permission = null) {
|
||||
const args = {
|
||||
...ctx.params, ...ctx.query, ...ctx.request.body, domainId: 'system',
|
||||
};
|
||||
if (h.request.host !== await system.get('server.host')) {
|
||||
args.domainId = h.request.url.split('//')[1].split(`.${await system.get('server.host')}`)[0] || '';
|
||||
}
|
||||
|
||||
if (h.___prepare) await h.___prepare(args);
|
||||
if (permission) h.checkPerm(permission);
|
||||
@@ -437,8 +442,8 @@ async function start() {
|
||||
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));
|
||||
app.use(router.routes()).use(router.allowedMethods());
|
||||
Route('*', Handler);
|
||||
server.listen(await system.get('listen.port'));
|
||||
console.log('Server listening at: %s', await system.get('listen.port'));
|
||||
server.listen(await system.get('server.port'));
|
||||
console.log('Server listening at: %s', await system.get('server.port'));
|
||||
}
|
||||
|
||||
global.Hydro.service.server = module.exports = {
|
||||
|
||||
+23
-18
@@ -1,8 +1,8 @@
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const http = require('http');
|
||||
const Koa = require('koa');
|
||||
const morgan = require('koa-morgan');
|
||||
const Body = require('koa-body');
|
||||
const Router = require('koa-router');
|
||||
const cache = require('koa-static-cache');
|
||||
@@ -19,20 +19,11 @@ class Loader {
|
||||
}
|
||||
}
|
||||
|
||||
class Nunjucks extends nunjucks.Environment {
|
||||
constructor() {
|
||||
super(new Loader(), { autoescape: true, trimBlocks: true });
|
||||
this.addFilter('json', (self) => JSON.stringify(self), false);
|
||||
this.addFilter('base64_encode', (s) => Buffer.from(s).toString('base64'));
|
||||
}
|
||||
}
|
||||
const env = new Nunjucks();
|
||||
const env = new nunjucks.Environment(new Loader(), { autoescape: true, trimBlocks: true });
|
||||
|
||||
function render(name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
env.render(name, {
|
||||
typeof: (o) => typeof o,
|
||||
static_url: (str) => `/${str}`,
|
||||
handler: { renderTitle: (str) => str },
|
||||
_: (str) => str,
|
||||
}, (err, res) => {
|
||||
if (err) reject(err);
|
||||
@@ -40,15 +31,16 @@ function render(name) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function setup() {
|
||||
const app = new Koa();
|
||||
const server = http.createServer(app.callback());
|
||||
const router = new Router();
|
||||
app.keys = ['Hydro'];
|
||||
app.use(cache(path.join(process.cwd(), '.uibuild'), {
|
||||
app.use(cache(path.join(os.tmpdir(), 'hydro', 'builtin'), {
|
||||
maxAge: 365 * 24 * 60 * 60,
|
||||
}));
|
||||
app.use(Body({ formidable: { maxFileSize: 256 * 1024 * 1024 } }));
|
||||
app.use(Body());
|
||||
router.get('/', async (ctx) => {
|
||||
ctx.body = await render('setup.html');
|
||||
ctx.response.type = 'text/html';
|
||||
@@ -66,9 +58,23 @@ async function setup() {
|
||||
useNewUrlParser: true, useUnifiedTopology: true,
|
||||
});
|
||||
const db = Database.db(name);
|
||||
// Check Write Access
|
||||
await db.collection('test').insertOne({ test: 'test' });
|
||||
await db.collection('test').deleteOne({ test: 'test' });
|
||||
await Promise.all([
|
||||
db.collection('system').updateOne(
|
||||
{ _id: 'server.host' },
|
||||
{ $set: { value: ctx.request.host } },
|
||||
{ upsert: true },
|
||||
),
|
||||
db.collection('system').updateOne(
|
||||
{ _id: 'server.hostname' },
|
||||
{ $set: { value: ctx.request.hostname } },
|
||||
{ upsert: true },
|
||||
),
|
||||
db.collection('system').updateOne(
|
||||
{ _id: 'server.url' },
|
||||
{ $set: { value: ctx.request.href } },
|
||||
{ upsert: true },
|
||||
),
|
||||
]);
|
||||
fs.writeFileSync(path.resolve(process.cwd(), 'config.json'), JSON.stringify({
|
||||
host, port, name, username, password,
|
||||
}));
|
||||
@@ -79,7 +85,6 @@ async function setup() {
|
||||
}
|
||||
});
|
||||
});
|
||||
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));
|
||||
app.use(router.routes()).use(router.allowedMethods());
|
||||
server.listen(8888);
|
||||
console.log('Server listening at: 8888');
|
||||
|
||||
Reference in new issue
Block a user