diff --git a/server/agent.js b/server/agent.js index c91b7f93..cb5495f3 100644 --- a/server/agent.js +++ b/server/agent.js @@ -45,6 +45,8 @@ const fs = Promise.promisifyAll(require('fs-extra')) const klaw = require('klaw') const Cron = require('cron').CronJob +const entryHelper = require('./helpers/entry') + // ---------------------------------------- // Start Cron // ---------------------------------------- @@ -94,8 +96,8 @@ db.onReady.then(() => { klaw(repoPath).on('data', function (item) { if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') { - let entryPath = entries.parsePath(entries.getEntryPathFromFullPath(item.path)) - let cachePath = entries.getCachePath(entryPath) + let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path)) + let cachePath = entryHelper.getCachePath(entryPath) // -> Purge outdated cache diff --git a/server/controllers/pages.js b/server/controllers/pages.js index 561a134d..801f64b1 100644 --- a/server/controllers/pages.js +++ b/server/controllers/pages.js @@ -4,6 +4,8 @@ const express = require('express') const router = express.Router() const _ = require('lodash') +const entryHelper = require('../helpers/entry') + // ========================================== // EDIT MODE // ========================================== @@ -16,7 +18,7 @@ router.get('/edit/*', (req, res, next) => { return res.render('error-forbidden') } - let safePath = entries.parsePath(_.replace(req.path, '/edit', '')) + let safePath = entryHelper.parsePath(_.replace(req.path, '/edit', '')) entries.fetchOriginal(safePath, { parseMarkdown: false, @@ -48,7 +50,7 @@ router.put('/edit/*', (req, res, next) => { }) } - let safePath = entries.parsePath(_.replace(req.path, '/edit', '')) + let safePath = entryHelper.parsePath(_.replace(req.path, '/edit', '')) entries.update(safePath, req.body.markdown, req.user).then(() => { return res.json({ @@ -78,7 +80,7 @@ router.get('/create/*', (req, res, next) => { }) } - let safePath = entries.parsePath(_.replace(req.path, '/create', '')) + let safePath = entryHelper.parsePath(_.replace(req.path, '/create', '')) entries.exists(safePath).then((docExists) => { if (!docExists) { @@ -116,7 +118,7 @@ router.put('/create/*', (req, res, next) => { }) } - let safePath = entries.parsePath(_.replace(req.path, '/create', '')) + let safePath = entryHelper.parsePath(_.replace(req.path, '/create', '')) entries.create(safePath, req.body.markdown, req.user).then(() => { return res.json({ @@ -153,7 +155,7 @@ router.use((req, res, next) => { * View source of a document */ router.get('/source/*', (req, res, next) => { - let safePath = entries.parsePath(_.replace(req.path, '/source', '')) + let safePath = entryHelper.parsePath(_.replace(req.path, '/source', '')) entries.fetchOriginal(safePath, { parseMarkdown: false, @@ -181,7 +183,7 @@ router.get('/source/*', (req, res, next) => { * View document */ router.get('/*', (req, res, next) => { - let safePath = entries.parsePath(req.path) + let safePath = entryHelper.parsePath(req.path) entries.fetch(safePath).then((pageData) => { if (pageData) { @@ -221,7 +223,7 @@ router.put('/*', (req, res, next) => { }) } - let safePath = entries.parsePath(req.path) + let safePath = entryHelper.parsePath(req.path) if (_.isEmpty(req.body.move)) { return res.json({ @@ -230,7 +232,7 @@ router.put('/*', (req, res, next) => { }) } - let safeNewPath = entries.parsePath(req.body.move) + let safeNewPath = entryHelper.parsePath(req.body.move) entries.move(safePath, safeNewPath, req.user).then(() => { res.json({ diff --git a/server/helpers/entry.js b/server/helpers/entry.js new file mode 100644 index 00000000..b32b133b --- /dev/null +++ b/server/helpers/entry.js @@ -0,0 +1,60 @@ +'use strict' + +const crypto = require('crypto') +const path = require('path') +const qs = require('querystring') +const _ = require('lodash') + +module.exports = { + /** + * Parse raw url path and make it safe + * + * @param {String} urlPath The url path + * @return {String} Safe entry path + */ + parsePath (urlPath) { + urlPath = qs.unescape(urlPath) + let wlist = new RegExp('(?!([^a-z0-9]|' + appdata.regex.cjk.source + '|[/-]))', 'g') + + urlPath = _.toLower(urlPath).replace(wlist, '') + + if (urlPath === '/') { + urlPath = 'home' + } + + let urlParts = _.filter(_.split(urlPath, '/'), (p) => { return !_.isEmpty(p) }) + + return _.join(urlParts, '/') + }, + + /** + * Gets the full original path of a document. + * + * @param {String} entryPath The entry path + * @return {String} The full path. + */ + getFullPath (entryPath) { + return path.join(appdata.repoPath, entryPath + '.md') + }, + + /** + * Gets the full cache path of a document. + * + * @param {String} entryPath The entry path + * @return {String} The full cache path. + */ + getCachePath (entryPath) { + return path.join(appdata.cachePath, crypto.createHash('md5').update(entryPath).digest('hex') + '.json') + }, + + /** + * Gets the entry path from full path. + * + * @param {String} fullPath The full path + * @return {String} The entry path + */ + getEntryPathFromFullPath (fullPath) { + let absRepoPath = path.resolve(ROOTPATH, appdata.repoPath) + return _.chain(fullPath).replace(absRepoPath, '').replace('.md', '').replace(new RegExp('\\\\', 'g'), '/').value() + } +} diff --git a/server/helpers/security.js b/server/helpers/security.js new file mode 100644 index 00000000..bb73d2d8 --- /dev/null +++ b/server/helpers/security.js @@ -0,0 +1,7 @@ +'use strict' + +module.exports = { + sanitizeCommitUser (user) { + + } +} diff --git a/server/libs/entries.js b/server/libs/entries.js index e8925e2a..9ebeddfa 100644 --- a/server/libs/entries.js +++ b/server/libs/entries.js @@ -4,8 +4,8 @@ const Promise = require('bluebird') const path = require('path') const fs = Promise.promisifyAll(require('fs-extra')) const _ = require('lodash') -const crypto = require('crypto') -const qs = require('querystring') + +const entryHelper = require('../helpers/entry') /** * Entries Model @@ -25,6 +25,8 @@ module.exports = { self._repoPath = path.resolve(ROOTPATH, appconfig.paths.repo) self._cachePath = path.resolve(ROOTPATH, appconfig.paths.data, 'cache') + appdata.repoPath = self._repoPath + appdata.cachePath = self._cachePath return self }, @@ -61,7 +63,7 @@ module.exports = { fetch (entryPath) { let self = this - let cpath = self.getCachePath(entryPath) + let cpath = entryHelper.getCachePath(entryPath) return fs.statAsync(cpath).then((st) => { return st.isFile() @@ -96,8 +98,8 @@ module.exports = { fetchOriginal (entryPath, options) { let self = this - let fpath = self.getFullPath(entryPath) - let cpath = self.getCachePath(entryPath) + let fpath = entryHelper.getFullPath(entryPath) + let cpath = entryHelper.getCachePath(entryPath) options = _.defaults(options, { parseMarkdown: true, @@ -157,27 +159,6 @@ module.exports = { }) }, - /** - * Parse raw url path and make it safe - * - * @param {String} urlPath The url path - * @return {String} Safe entry path - */ - parsePath (urlPath) { - urlPath = qs.unescape(urlPath) - let wlist = new RegExp('(?!([^a-z0-9]|' + appdata.regex.cjk.source + '|[/-]))', 'g') - - urlPath = _.toLower(urlPath).replace(wlist, '') - - if (urlPath === '/') { - urlPath = 'home' - } - - let urlParts = _.filter(_.split(urlPath, '/'), (p) => { return !_.isEmpty(p) }) - - return _.join(urlParts, '/') - }, - /** * Gets the parent information. * @@ -185,13 +166,11 @@ module.exports = { * @return {Promise} The parent information. */ getParentInfo (entryPath) { - let self = this - if (_.includes(entryPath, '/')) { let parentParts = _.initial(_.split(entryPath, '/')) let parentPath = _.join(parentParts, '/') let parentFile = _.last(parentParts) - let fpath = self.getFullPath(parentPath) + let fpath = entryHelper.getFullPath(parentPath) return fs.statAsync(fpath).then((st) => { if (st.isFile()) { @@ -213,37 +192,6 @@ module.exports = { } }, - /** - * Gets the full original path of a document. - * - * @param {String} entryPath The entry path - * @return {String} The full path. - */ - getFullPath (entryPath) { - return path.join(this._repoPath, entryPath + '.md') - }, - - /** - * Gets the full cache path of a document. - * - * @param {String} entryPath The entry path - * @return {String} The full cache path. - */ - getCachePath (entryPath) { - return path.join(this._cachePath, crypto.createHash('md5').update(entryPath).digest('hex') + '.json') - }, - - /** - * Gets the entry path from full path. - * - * @param {String} fullPath The full path - * @return {String} The entry path - */ - getEntryPathFromFullPath (fullPath) { - let absRepoPath = path.resolve(ROOTPATH, this._repoPath) - return _.chain(fullPath).replace(absRepoPath, '').replace('.md', '').replace(new RegExp('\\\\', 'g'), '/').value() - }, - /** * Update an existing document * @@ -254,7 +202,7 @@ module.exports = { */ update (entryPath, contents, author) { let self = this - let fpath = self.getFullPath(entryPath) + let fpath = entryHelper.getFullPath(entryPath) return fs.statAsync(fpath).then((st) => { if (st.isFile()) { @@ -385,8 +333,7 @@ module.exports = { * @return {Promise} True on success, false on failure */ makePersistent (entryPath, contents, author) { - let self = this - let fpath = self.getFullPath(entryPath) + let fpath = entryHelper.getFullPath(entryPath) return fs.outputFileAsync(fpath, contents).then(() => { return git.commitDocument(entryPath, author) @@ -412,7 +359,7 @@ module.exports = { return git.commitDocument(newEntryPath, author).then(() => { // Delete old cache version - let oldEntryCachePath = self.getCachePath(entryPath) + let oldEntryCachePath = entryHelper.getCachePath(entryPath) fs.unlinkAsync(oldEntryCachePath).catch((err) => { return true }) // eslint-disable-line handle-callback-err // Delete old index entry @@ -437,7 +384,7 @@ module.exports = { getStarter (entryPath) { let formattedTitle = _.startCase(_.last(_.split(entryPath, '/'))) - return fs.readFileAsync(path.join(ROOTPATH, 'client/content/create.md'), 'utf8').then((contents) => { + return fs.readFileAsync(path.join(SERVERPATH, 'app/content/create.md'), 'utf8').then((contents) => { return _.replace(contents, new RegExp('{TITLE}', 'g'), formattedTitle) }) },