diff --git a/hydro/development.js b/hydro/development.js index ed0fd0a6..c704553c 100644 --- a/hydro/development.js +++ b/hydro/development.js @@ -19,11 +19,13 @@ process.on('restart', async () => { const path = require('path'); const i18n = require('./lib/i18n'); i18n(path.resolve(__dirname, '..', 'locales', 'zh_CN.yaml'), 'zh_CN'); - +i18n(path.resolve(__dirname, '..', 'locales', 'zh_TW.yaml'), 'zh_TW'); +i18n(path.resolve(__dirname, '..', 'locales', 'en.yaml'), 'en'); const EventEmitter = require('events'); global.bus = new EventEmitter(); async function run() { + require('./utils'); require('./service/db'); await new Promise((resolve) => { global.bus.once('connected', () => { diff --git a/hydro/handler/ui.js b/hydro/handler/ui.js index 20b034f7..a8a9f015 100644 --- a/hydro/handler/ui.js +++ b/hydro/handler/ui.js @@ -8,7 +8,7 @@ const options = require('../options'), perm = require('../permission'), builtin = require('../model/builtin'), - md5 = require('../lib/md5'), + misc=require('../lib/misc'), { MIDDLEWARE } = require('../service/server'), { NotFoundError } = require('../error'); @@ -29,33 +29,6 @@ class Markdown extends MarkdownIt { } } const md = new Markdown(); -function datetime_span(dt, { relative = true } = {}) { - if (dt.generationTime) dt = new Date(dt.generationTime * 1000); - else if (typeof dt == 'number' || typeof dt == 'string') dt = new Date(dt); - return '{2}'.format( - relative ? ' relative' : '', - dt.getTime() / 1000, - dt.toLocaleString() - ); -} -function* paginate(page, num_pages) { - let radius = 2, first, last; - if (page > 1) { - yield ['first', 1]; - yield ['previous', page - 1]; - } - if (page <= radius) [first, last] = [1, Math.min(1 + radius * 2, num_pages)]; - else if (page >= num_pages - radius) [first, last] = [Math.max(1, num_pages - radius * 2), num_pages]; - else[first, last] = [page - radius, page + radius]; - if (first > 1) yield ['ellipsis', 0]; - for (let page0 = first; page0 < last + 1; page0++) { - if (page0 != page) yield ['page', page0]; - else yield ['current', page]; - } - if (last < num_pages) yield ['ellipsis', 0]; - if (page < num_pages) yield ['next', page + 1]; - yield ['last', num_pages]; -} class Nunjucks extends nunjucks.Environment { constructor() { super( @@ -71,25 +44,14 @@ class Nunjucks extends nunjucks.Environment { this.addFilter('markdown', function (self) { return md.render(self); }); - this.addFilter('gravatar_url', function (email, size) { - return `//gravatar.loli.net/avatar/${md5(email.toString().trim().toLowerCase())}?d=mm&s=${size}`; - }); - this.addFilter('format_size', function (size, base = 1) { - size *= base; - let unit = 1024; - let unit_names = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; - for (let unit_name of unit_names) { - if (size < unit) return '{0} {1}'.format(Math.round(size), unit_name); - size /= unit; - } - return '{0} {1}'.format(Math.round(size * unit), unit_names[unit_names.length - 1]); - }); + this.addFilter('gravatar_url', misc.gravatar_url); + this.addFilter('format_size', misc.format_size); this.addGlobal('typeof', o => typeof o); this.addGlobal('console', console); this.addGlobal('static_url', str => `/${str}`); this.addGlobal('reverse_url', str => str); - this.addGlobal('datetime_span', datetime_span); - this.addGlobal('paginate', paginate); + this.addGlobal('datetime_span', misc.datetime_span); + this.addGlobal('paginate', misc.paginate); this.addGlobal('perm', perm); this.addGlobal('builtin', builtin); this.addGlobal('status', builtin.STATUS); diff --git a/hydro/install.js b/hydro/install.js index 4fe4564f..e052f57a 100644 --- a/hydro/install.js +++ b/hydro/install.js @@ -1,7 +1,7 @@ const Mongo = require('mongodb'), builtin = require('./model/builtin'), - { pwhash } = require('./utils'), + pwhash = require('./lib/pwhash'), options = require('./options'); async function run() { diff --git a/hydro/lib/misc.js b/hydro/lib/misc.js new file mode 100644 index 00000000..73f8df49 --- /dev/null +++ b/hydro/lib/misc.js @@ -0,0 +1,41 @@ +const md5 = require('./md5'); +exports.gravatar_url = function (email, size) { + return `//gravatar.loli.net/avatar/${md5((email || '').toString().trim().toLowerCase())}?d=mm&s=${size}`; +}; +exports.datetime_span = function (dt, { relative = true } = {}) { + if (dt.generationTime) dt = new Date(dt.generationTime * 1000); + else if (typeof dt == 'number' || typeof dt == 'string') dt = new Date(dt); + return '{2}'.format( + relative ? ' relative' : '', + dt.getTime() / 1000, + dt.toLocaleString() + ); +}; +exports.paginate = function* (page, num_pages) { + let radius = 2, first, last; + if (page > 1) { + yield ['first', 1]; + yield ['previous', page - 1]; + } + if (page <= radius) [first, last] = [1, Math.min(1 + radius * 2, num_pages)]; + else if (page >= num_pages - radius) [first, last] = [Math.max(1, num_pages - radius * 2), num_pages]; + else[first, last] = [page - radius, page + radius]; + if (first > 1) yield ['ellipsis', 0]; + for (let page0 = first; page0 < last + 1; page0++) { + if (page0 != page) yield ['page', page0]; + else yield ['current', page]; + } + if (last < num_pages) yield ['ellipsis', 0]; + if (page < num_pages) yield ['next', page + 1]; + yield ['last', num_pages]; +}; +exports.format_size = function (size, base = 1) { + size *= base; + let unit = 1024; + let unit_names = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; + for (let unit_name of unit_names) { + if (size < unit) return '{0} {1}'.format(Math.round(size), unit_name); + size /= unit; + } + return '{0} {1}'.format(Math.round(size * unit), unit_names[unit_names.length - 1]); +}; \ No newline at end of file diff --git a/hydro/lib/pwhash.js b/hydro/lib/pwhash.js new file mode 100644 index 00000000..c39493e0 --- /dev/null +++ b/hydro/lib/pwhash.js @@ -0,0 +1,26 @@ +const crypto = require('crypto'); +module.exports = { + _b64encode: str => new Buffer(str).toString('base64'), + _b64decode: str => new Buffer(str, 'base64').toString(), + _md5: str => crypto.createHash('md5').update(str).digest('hex'), + _sha1: str => crypto.createHash('sha1').update(str).digest('hex'), + /** + * @param {string} password + * @param {string} salt + * @param {string} hash + */ + check(password, salt, hash) { + return hash == this.hash(password, salt); + }, + /** + * @param {string} password + * @param {string} salt + */ + hash(password, salt) { + let res = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha256'); + return res.toString('Hex'); + }, + salt() { + return String.random(); + } +}; \ No newline at end of file diff --git a/hydro/model/user.js b/hydro/model/user.js index ecd6019a..e57fcca5 100644 --- a/hydro/model/user.js +++ b/hydro/model/user.js @@ -1,7 +1,7 @@ const system = require('./system'), { UserNotFoundError, UserAlreadyExistError } = require('../error'), - { pwhash } = require('../utils'), + pwhash = require('./lib/pwhash'), validator = require('../lib/validator'), db = require('../service/db'), coll = db.collection('user'), diff --git a/hydro/service/server.js b/hydro/service/server.js index fbb24169..671aea1a 100644 --- a/hydro/service/server.js +++ b/hydro/service/server.js @@ -60,6 +60,7 @@ function ROUTE(route, handler) { let args = Object.assign({}, ctx.params, ctx.query, ctx.request.body); if (args.content) validator.checkContent(args.content); if (args.title) validator.checkContent(args.title); + if (args.uid) args.uid = parseInt(validator.checkUid(args.uid)); if (h._prepare) await h._prepare(args); if (h.prepare) await h.prepare(args); if (h[`_${method}`]) await h[`_${method}`](args); diff --git a/hydro/utils.js b/hydro/utils.js index 44739488..b19867cb 100644 --- a/hydro/utils.js +++ b/hydro/utils.js @@ -1,14 +1,12 @@ -const - crypto = require('crypto'), - map = [ - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', - 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', - '9', '0' - ]; +const map = [ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '0' +]; String.random = function (digit) { let str = ''; @@ -16,29 +14,3 @@ String.random = function (digit) { str += map[Math.floor(Math.random() * 62)]; return str; }; - -exports.pwhash = { - _b64encode: str => new Buffer(str).toString('base64'), - _b64decode: str => new Buffer(str, 'base64').toString(), - _md5: str => crypto.createHash('md5').update(str).digest('hex'), - _sha1: str => crypto.createHash('sha1').update(str).digest('hex'), - /** - * @param {string} password - * @param {string} salt - * @param {string} hash - */ - check(password, salt, hash) { - return hash == this.hash(password, salt); - }, - /** - * @param {string} password - * @param {string} salt - */ - hash(password, salt) { - let res = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha256'); - return res.toString('Hex'); - }, - salt() { - return String.random(); - } -}; diff --git a/templates/components/comments_discussion.html b/templates/components/comments_discussion.html index eb010a35..9d51fb90 100644 --- a/templates/components/comments_discussion.html +++ b/templates/components/comments_discussion.html @@ -26,26 +26,6 @@ {% endmacro %} -{% macro comment_operations(doc) %} -
-{% if handler.has_perm(reply_post_perm) %} - -{% endif %} -{% if doc.owner == handler.state.user._id or handler.has_perm(comment_edit_perm) %} - -{% endif %} -{% if doc.owner == handler.state.user._id or handler.has_perm(comment_delete_perm) %} - -{% endif %} -
-{% endmacro %} - {% macro reply_operations(doc, rdoc) %}
{% if handler.has_perm(reply_post_perm) %} @@ -135,7 +115,23 @@ {{ user.render_inline(udoc, avatar=false) }} @ {{ datetime_span(doc['_id'])|safe }}
- {{ comment_operations(doc) }} +
+ {% if handler.has_perm(reply_post_perm) %} + + {% endif %} + {% if doc.owner == handler.state.user._id or handler.has_perm(comment_edit_perm) %} + + {% endif %} + {% if doc.owner == handler.state.user._id or handler.has_perm(comment_delete_perm) %} + + {% endif %} +
{{ doc['content']|markdown|safe }} diff --git a/templates/components/comments_solution.html b/templates/components/comments_solution.html index ea74fa92..66d857a2 100644 --- a/templates/components/comments_solution.html +++ b/templates/components/comments_solution.html @@ -130,7 +130,7 @@ {% endif %}
-
+
{{ doc['content']|markdown|safe }}
@@ -160,7 +160,7 @@ {% endif %}
-
+
{{ rdoc['content']|markdown|safe }}