refactor: migrate to PostgreSQL + Sequelize
This commit is contained in:
+8
-8
@@ -1,6 +1,6 @@
|
||||
// ===========================================
|
||||
// Wiki.js - Background Agent
|
||||
// 1.0.0
|
||||
// 1.0.1
|
||||
// Licensed under AGPLv3
|
||||
// ===========================================
|
||||
|
||||
@@ -12,7 +12,7 @@ global.ROOTPATH = ROOTPATH
|
||||
global.SERVERPATH = SERVERPATH
|
||||
const IS_DEBUG = process.env.NODE_ENV === 'development'
|
||||
|
||||
let appconf = require('./libs/config')()
|
||||
let appconf = require('./modules/config')()
|
||||
global.appconfig = appconf.config
|
||||
global.appdata = appconf.data
|
||||
|
||||
@@ -20,7 +20,7 @@ global.appdata = appconf.data
|
||||
// Load Winston
|
||||
// ----------------------------------------
|
||||
|
||||
global.winston = require('./libs/logger')(IS_DEBUG, 'AGENT')
|
||||
global.winston = require('./modules/logger')(IS_DEBUG, 'AGENT')
|
||||
|
||||
// ----------------------------------------
|
||||
// Load global modules
|
||||
@@ -28,12 +28,12 @@ global.winston = require('./libs/logger')(IS_DEBUG, 'AGENT')
|
||||
|
||||
global.winston.info('Background Agent is initializing...')
|
||||
|
||||
global.db = require('./libs/db').init()
|
||||
global.upl = require('./libs/uploads-agent').init()
|
||||
global.git = require('./libs/git').init()
|
||||
global.entries = require('./libs/entries').init()
|
||||
global.db = require('./modules/db').init()
|
||||
global.upl = require('./modules/uploads-agent').init()
|
||||
global.git = require('./modules/git').init()
|
||||
global.entries = require('./modules/entries').init()
|
||||
global.lang = require('i18next')
|
||||
global.mark = require('./libs/markdown')
|
||||
global.mark = require('./modules/markdown')
|
||||
|
||||
// ----------------------------------------
|
||||
// Load modules
|
||||
|
||||
@@ -64,6 +64,15 @@ defaults:
|
||||
code:
|
||||
dark: true
|
||||
colorize: true
|
||||
authProviders:
|
||||
- local
|
||||
- microsoft
|
||||
- google
|
||||
- facebook
|
||||
- github
|
||||
- slack
|
||||
- ldap
|
||||
- azure
|
||||
colors:
|
||||
- red
|
||||
- pink
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
'use strict'
|
||||
|
||||
/* global db, lang */
|
||||
/* global wiki */
|
||||
|
||||
const Promise = require('bluebird')
|
||||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const passport = require('passport')
|
||||
const ExpressBrute = require('express-brute')
|
||||
const ExpressBruteMongooseStore = require('express-brute-mongoose')
|
||||
const ExpressBruteRedisStore = require('express-brute-redis')
|
||||
const moment = require('moment')
|
||||
|
||||
/**
|
||||
* Setup Express-Brute
|
||||
*/
|
||||
const EBstore = new ExpressBruteMongooseStore(db.Bruteforce)
|
||||
const EBstore = new ExpressBruteRedisStore({
|
||||
client: wiki.redis
|
||||
})
|
||||
const bruteforce = new ExpressBrute(EBstore, {
|
||||
freeRetries: 5,
|
||||
minWait: 60 * 1000,
|
||||
@@ -22,8 +24,8 @@ const bruteforce = new ExpressBrute(EBstore, {
|
||||
failCallback (req, res, next, nextValidRequestDate) {
|
||||
req.flash('alert', {
|
||||
class: 'error',
|
||||
title: lang.t('auth:errors.toomanyattempts'),
|
||||
message: lang.t('auth:errors.toomanyattemptsmsg', { time: moment(nextValidRequestDate).fromNow() }),
|
||||
title: wiki.lang.t('auth:errors.toomanyattempts'),
|
||||
message: wiki.lang.t('auth:errors.toomanyattemptsmsg', { time: moment(nextValidRequestDate).fromNow() }),
|
||||
iconClass: 'fa-times'
|
||||
})
|
||||
res.redirect('/login')
|
||||
@@ -73,13 +75,13 @@ router.post('/login', bruteforce.prevent, function (req, res, next) {
|
||||
// LOGIN FAIL
|
||||
if (err.message === 'INVALID_LOGIN') {
|
||||
req.flash('alert', {
|
||||
title: lang.t('auth:errors.invalidlogin'),
|
||||
message: lang.t('auth:errors.invalidloginmsg')
|
||||
title: wiki.lang.t('auth:errors.invalidlogin'),
|
||||
message: wiki.lang.t('auth:errors.invalidloginmsg')
|
||||
})
|
||||
return res.redirect('/login')
|
||||
} else {
|
||||
req.flash('alert', {
|
||||
title: lang.t('auth:errors.loginerror'),
|
||||
title: wiki.lang.t('auth:errors.loginerror'),
|
||||
message: err.message
|
||||
})
|
||||
return res.redirect('/login')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global git, lang, lcdata, upl */
|
||||
/* global wiki */
|
||||
|
||||
const express = require('express')
|
||||
const router = express.Router()
|
||||
@@ -12,7 +12,7 @@ const fs = Promise.promisifyAll(require('fs-extra'))
|
||||
const path = require('path')
|
||||
const _ = require('lodash')
|
||||
|
||||
const validPathRe = new RegExp('^([a-z0-9/-' + appdata.regex.cjk + appdata.regex.arabic + ']+\\.[a-z0-9]+)$')
|
||||
const validPathRe = new RegExp('^([a-z0-9/-' + wiki.data.regex.cjk + wiki.data.regex.arabic + ']+\\.[a-z0-9]+)$')
|
||||
const validPathThumbsRe = new RegExp('^([a-z0-9]+\\.png)$')
|
||||
|
||||
// ==========================================
|
||||
@@ -28,7 +28,7 @@ router.get('/t/*', (req, res, next) => {
|
||||
// todo: Authentication-based access
|
||||
|
||||
res.sendFile(fileName, {
|
||||
root: lcdata.getThumbsPath(),
|
||||
root: wiki.disk.getThumbsPath(),
|
||||
dotfiles: 'deny'
|
||||
}, (err) => {
|
||||
if (err) {
|
||||
@@ -37,12 +37,12 @@ router.get('/t/*', (req, res, next) => {
|
||||
})
|
||||
})
|
||||
|
||||
router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
|
||||
router.post('/img', wiki.disk.uploadImgHandler, (req, res, next) => {
|
||||
let destFolder = _.chain(req.body.folder).trim().toLower().value()
|
||||
|
||||
upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
|
||||
wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
|
||||
if (!destFolderPath) {
|
||||
res.json({ ok: false, msg: lang.t('errors:invalidfolder') })
|
||||
res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
|
||||
let destFilename = ''
|
||||
let destFilePath = ''
|
||||
|
||||
return lcdata.validateUploadsFilename(f.originalname, destFolder, true).then((fname) => {
|
||||
return wiki.disk.validateUploadsFilename(f.originalname, destFolder, true).then((fname) => {
|
||||
destFilename = fname
|
||||
destFilePath = path.resolve(destFolderPath, destFilename)
|
||||
|
||||
@@ -60,7 +60,7 @@ router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
|
||||
|
||||
let mimeInfo = fileType(buf)
|
||||
if (!_.includes(['image/png', 'image/jpeg', 'image/gif', 'image/webp'], mimeInfo.mime)) {
|
||||
return Promise.reject(new Error(lang.t('errors:invalidfiletype')))
|
||||
return Promise.reject(new Error(wiki.lang.t('errors:invalidfiletype')))
|
||||
}
|
||||
return true
|
||||
}).then(() => {
|
||||
@@ -94,12 +94,12 @@ router.post('/img', lcdata.uploadImgHandler, (req, res, next) => {
|
||||
})
|
||||
})
|
||||
|
||||
router.post('/file', lcdata.uploadFileHandler, (req, res, next) => {
|
||||
router.post('/file', wiki.disk.uploadFileHandler, (req, res, next) => {
|
||||
let destFolder = _.chain(req.body.folder).trim().toLower().value()
|
||||
|
||||
upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
|
||||
wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
|
||||
if (!destFolderPath) {
|
||||
res.json({ ok: false, msg: lang.t('errors:invalidfolder') })
|
||||
res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ router.post('/file', lcdata.uploadFileHandler, (req, res, next) => {
|
||||
let destFilename = ''
|
||||
let destFilePath = ''
|
||||
|
||||
return lcdata.validateUploadsFilename(f.originalname, destFolder, false).then((fname) => {
|
||||
return wiki.disk.validateUploadsFilename(f.originalname, destFolder, false).then((fname) => {
|
||||
destFilename = fname
|
||||
destFilePath = path.resolve(destFolderPath, destFilename)
|
||||
|
||||
@@ -150,7 +150,7 @@ router.get('/*', (req, res, next) => {
|
||||
// todo: Authentication-based access
|
||||
|
||||
res.sendFile(fileName, {
|
||||
root: git.getRepoPath() + '/uploads/',
|
||||
root: wiki.git.getRepoPath() + '/uploads/',
|
||||
dotfiles: 'deny'
|
||||
}, (err) => {
|
||||
if (err) {
|
||||
|
||||
+63
-65
@@ -2,47 +2,48 @@
|
||||
|
||||
// ===========================================
|
||||
// Wiki.js
|
||||
// 1.0.0
|
||||
// 1.0.1
|
||||
// Licensed under AGPLv3
|
||||
// ===========================================
|
||||
|
||||
const path = require('path')
|
||||
const ROOTPATH = process.cwd()
|
||||
const SERVERPATH = path.join(ROOTPATH, 'server')
|
||||
|
||||
global.ROOTPATH = ROOTPATH
|
||||
global.SERVERPATH = SERVERPATH
|
||||
const IS_DEBUG = process.env.NODE_ENV === 'development'
|
||||
let wiki = {
|
||||
IS_DEBUG: process.env.NODE_ENV === 'development',
|
||||
ROOTPATH: process.cwd(),
|
||||
SERVERPATH: path.join(process.cwd(), 'server')
|
||||
}
|
||||
global.wiki = wiki
|
||||
|
||||
process.env.VIPS_WARNING = false
|
||||
|
||||
// if (IS_DEBUG) {
|
||||
// if (wiki.IS_DEBUG) {
|
||||
// require('@glimpse/glimpse').init()
|
||||
// }
|
||||
|
||||
let appconf = require('./libs/config')()
|
||||
global.appconfig = appconf.config
|
||||
global.appdata = appconf.data
|
||||
let appconf = require('./modules/config')()
|
||||
wiki.config = appconf.config
|
||||
wiki.data = appconf.data
|
||||
|
||||
// ----------------------------------------
|
||||
// Load Winston
|
||||
// ----------------------------------------
|
||||
|
||||
global.winston = require('./libs/logger')(IS_DEBUG, 'SERVER')
|
||||
global.winston.info('Wiki.js is initializing...')
|
||||
wiki.logger = require('./modules/logger')(wiki.IS_DEBUG, 'SERVER')
|
||||
wiki.logger.info('Wiki.js is initializing...')
|
||||
|
||||
// ----------------------------------------
|
||||
// Load global modules
|
||||
// ----------------------------------------
|
||||
|
||||
global.lcdata = require('./libs/local').init()
|
||||
global.db = require('./libs/db').init()
|
||||
global.entries = require('./libs/entries').init()
|
||||
global.git = require('./libs/git').init(false)
|
||||
global.lang = require('i18next')
|
||||
global.mark = require('./libs/markdown')
|
||||
global.search = require('./libs/search').init()
|
||||
global.upl = require('./libs/uploads').init()
|
||||
wiki.disk = require('./modules/disk').init()
|
||||
wiki.db = require('./modules/db').init()
|
||||
wiki.entries = require('./modules/entries').init()
|
||||
wiki.git = require('./modules/git').init(false)
|
||||
wiki.lang = require('i18next')
|
||||
wiki.mark = require('./modules/markdown')
|
||||
wiki.redis = require('./modules/redis').init()
|
||||
wiki.search = require('./modules/search').init()
|
||||
wiki.upl = require('./modules/uploads').init()
|
||||
|
||||
// ----------------------------------------
|
||||
// Load modules
|
||||
@@ -61,19 +62,19 @@ const i18nBackend = require('i18next-node-fs-backend')
|
||||
const passport = require('passport')
|
||||
const passportSocketIo = require('passport.socketio')
|
||||
const session = require('express-session')
|
||||
const SessionMongoStore = require('connect-mongo')(session)
|
||||
const SessionRedisStore = require('connect-redis')(session)
|
||||
const graceful = require('node-graceful')
|
||||
const socketio = require('socket.io')
|
||||
|
||||
var mw = autoload(path.join(SERVERPATH, '/middlewares'))
|
||||
var ctrl = autoload(path.join(SERVERPATH, '/controllers'))
|
||||
var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares'))
|
||||
var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers'))
|
||||
|
||||
// ----------------------------------------
|
||||
// Define Express App
|
||||
// ----------------------------------------
|
||||
|
||||
const app = express()
|
||||
global.app = app
|
||||
wiki.app = app
|
||||
app.use(compression())
|
||||
|
||||
// ----------------------------------------
|
||||
@@ -86,8 +87,8 @@ app.use(mw.security)
|
||||
// Public Assets
|
||||
// ----------------------------------------
|
||||
|
||||
app.use(favicon(path.join(ROOTPATH, 'assets', 'favicon.ico')))
|
||||
app.use(express.static(path.join(ROOTPATH, 'assets'), {
|
||||
app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico')))
|
||||
app.use(express.static(path.join(wiki.ROOTPATH, 'assets'), {
|
||||
index: false,
|
||||
maxAge: '7d'
|
||||
}))
|
||||
@@ -96,20 +97,19 @@ app.use(express.static(path.join(ROOTPATH, 'assets'), {
|
||||
// Passport Authentication
|
||||
// ----------------------------------------
|
||||
|
||||
require('./libs/auth')(passport)
|
||||
global.rights = require('./libs/rights')
|
||||
global.rights.init()
|
||||
require('./modules/auth')(passport)
|
||||
wiki.rights = require('./modules/rights')
|
||||
wiki.rights.init()
|
||||
|
||||
let sessionStore = new SessionMongoStore({
|
||||
mongooseConnection: global.db.connection,
|
||||
touchAfter: 15
|
||||
let sessionStore = new SessionRedisStore({
|
||||
client: wiki.redis
|
||||
})
|
||||
|
||||
app.use(cookieParser())
|
||||
app.use(session({
|
||||
name: 'wikijs.sid',
|
||||
store: sessionStore,
|
||||
secret: appconfig.sessionSecret,
|
||||
secret: wiki.config.sessionSecret,
|
||||
resave: false,
|
||||
saveUninitialized: false
|
||||
}))
|
||||
@@ -127,26 +127,24 @@ app.use(mw.seo)
|
||||
// Localization Engine
|
||||
// ----------------------------------------
|
||||
|
||||
global.lang
|
||||
.use(i18nBackend)
|
||||
.init({
|
||||
load: 'languageOnly',
|
||||
ns: ['common', 'admin', 'auth', 'errors', 'git'],
|
||||
defaultNS: 'common',
|
||||
saveMissing: false,
|
||||
preload: [appconfig.lang],
|
||||
lng: appconfig.lang,
|
||||
fallbackLng: 'en',
|
||||
backend: {
|
||||
loadPath: path.join(SERVERPATH, 'locales/{{lng}}/{{ns}}.json')
|
||||
}
|
||||
})
|
||||
wiki.lang.use(i18nBackend).init({
|
||||
load: 'languageOnly',
|
||||
ns: ['common', 'admin', 'auth', 'errors', 'git'],
|
||||
defaultNS: 'common',
|
||||
saveMissing: false,
|
||||
preload: [wiki.config.lang],
|
||||
lng: wiki.config.lang,
|
||||
fallbackLng: 'en',
|
||||
backend: {
|
||||
loadPath: path.join(wiki.SERVERPATH, 'locales/{{lng}}/{{ns}}.json')
|
||||
}
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// View Engine Setup
|
||||
// ----------------------------------------
|
||||
|
||||
app.set('views', path.join(SERVERPATH, 'views'))
|
||||
app.set('views', path.join(wiki.SERVERPATH, 'views'))
|
||||
app.set('view engine', 'pug')
|
||||
|
||||
app.use(bodyParser.json({ limit: '1mb' }))
|
||||
@@ -157,10 +155,10 @@ app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' }))
|
||||
// ----------------------------------------
|
||||
|
||||
app.locals._ = require('lodash')
|
||||
app.locals.t = global.lang.t.bind(global.lang)
|
||||
app.locals.t = wiki.lang.t.bind(wiki.lang)
|
||||
app.locals.moment = require('moment')
|
||||
app.locals.moment.locale(appconfig.lang)
|
||||
app.locals.appconfig = appconfig
|
||||
app.locals.moment.locale(wiki.config.lang)
|
||||
app.locals.appconfig = wiki.config
|
||||
app.use(mw.flash)
|
||||
|
||||
// ----------------------------------------
|
||||
@@ -187,7 +185,7 @@ app.use(function (err, req, res, next) {
|
||||
res.status(err.status || 500)
|
||||
res.render('error', {
|
||||
message: err.message,
|
||||
error: IS_DEBUG ? err : {}
|
||||
error: wiki.IS_DEBUG ? err : {}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -195,13 +193,13 @@ app.use(function (err, req, res, next) {
|
||||
// Start HTTP server
|
||||
// ----------------------------------------
|
||||
|
||||
global.winston.info('Starting HTTP/WS server on port ' + appconfig.port + '...')
|
||||
wiki.logger.info('Starting HTTP/WS server on port ' + wiki.config.port + '...')
|
||||
|
||||
app.set('port', appconfig.port)
|
||||
app.set('port', wiki.config.port)
|
||||
var server = http.createServer(app)
|
||||
var io = socketio(server)
|
||||
|
||||
server.listen(appconfig.port)
|
||||
server.listen(wiki.config.port)
|
||||
server.on('error', (error) => {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error
|
||||
@@ -210,10 +208,10 @@ server.on('error', (error) => {
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
global.winston.error('Listening on port ' + appconfig.port + ' requires elevated privileges!')
|
||||
wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!')
|
||||
return process.exit(1)
|
||||
case 'EADDRINUSE':
|
||||
global.winston.error('Port ' + appconfig.port + ' is already in use!')
|
||||
wiki.logger.error('Port ' + wiki.config.port + ' is already in use!')
|
||||
return process.exit(1)
|
||||
default:
|
||||
throw error
|
||||
@@ -221,7 +219,7 @@ server.on('error', (error) => {
|
||||
})
|
||||
|
||||
server.on('listening', () => {
|
||||
global.winston.info('HTTP/WS server started successfully! [RUNNING]')
|
||||
wiki.logger.info('HTTP/WS server started successfully! [RUNNING]')
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
@@ -231,7 +229,7 @@ server.on('listening', () => {
|
||||
io.use(passportSocketIo.authorize({
|
||||
key: 'wikijs.sid',
|
||||
store: sessionStore,
|
||||
secret: appconfig.sessionSecret,
|
||||
secret: wiki.config.sessionSecret,
|
||||
cookieParser,
|
||||
success: (data, accept) => {
|
||||
accept()
|
||||
@@ -247,7 +245,7 @@ io.on('connection', ctrl.ws)
|
||||
// Start child processes
|
||||
// ----------------------------------------
|
||||
|
||||
let bgAgent = fork(path.join(SERVERPATH, 'agent.js'))
|
||||
let bgAgent = fork(path.join(wiki.SERVERPATH, 'agent.js'))
|
||||
|
||||
bgAgent.on('message', m => {
|
||||
if (!m.action) {
|
||||
@@ -256,7 +254,7 @@ bgAgent.on('message', m => {
|
||||
|
||||
switch (m.action) {
|
||||
case 'searchAdd':
|
||||
global.search.add(m.content)
|
||||
wiki.search.add(m.content)
|
||||
break
|
||||
}
|
||||
})
|
||||
@@ -266,11 +264,11 @@ bgAgent.on('message', m => {
|
||||
// ----------------------------------------
|
||||
|
||||
graceful.on('exit', () => {
|
||||
global.winston.info('- SHUTTING DOWN - Terminating Background Agent...')
|
||||
wiki.logger.info('- SHUTTING DOWN - Terminating Background Agent...')
|
||||
bgAgent.kill()
|
||||
global.winston.info('- SHUTTING DOWN - Performing git sync...')
|
||||
wiki.logger.info('- SHUTTING DOWN - Performing git sync...')
|
||||
return global.git.resync().then(() => {
|
||||
global.winston.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.')
|
||||
wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.')
|
||||
process.exit()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
/* global ROOTPATH, appconfig, winston */
|
||||
|
||||
const modb = require('mongoose')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* MongoDB module
|
||||
*
|
||||
* @return {Object} MongoDB wrapper instance
|
||||
*/
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Initialize DB
|
||||
*
|
||||
* @return {Object} DB instance
|
||||
*/
|
||||
init() {
|
||||
let self = this
|
||||
|
||||
let dbModelsPath = path.join(SERVERPATH, 'models')
|
||||
|
||||
modb.Promise = require('bluebird')
|
||||
|
||||
// Event handlers
|
||||
|
||||
modb.connection.on('error', err => {
|
||||
winston.error('Failed to connect to MongoDB instance.')
|
||||
return err
|
||||
})
|
||||
modb.connection.once('open', function () {
|
||||
winston.log('Connected to MongoDB instance.')
|
||||
})
|
||||
|
||||
// Store connection handle
|
||||
|
||||
self.connection = modb.connection
|
||||
self.ObjectId = modb.Types.ObjectId
|
||||
|
||||
// Load DB Models
|
||||
|
||||
fs
|
||||
.readdirSync(dbModelsPath)
|
||||
.filter(function (file) {
|
||||
return (file.indexOf('.') !== 0)
|
||||
})
|
||||
.forEach(function (file) {
|
||||
let modelName = _.upperFirst(_.camelCase(_.split(file, '.')[0]))
|
||||
self[modelName] = require(path.join(dbModelsPath, file))
|
||||
})
|
||||
|
||||
// Connect
|
||||
|
||||
self.onReady = modb.connect(appconfig.db, { useMongoClient: true })
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Associate DB Model relations
|
||||
*/
|
||||
module.exports = db => {
|
||||
db.User.belongsToMany(db.Group, { through: 'UserGroups' })
|
||||
db.Group.hasMany(db.Right, { as: 'GroupRights' })
|
||||
db.File.belongsTo(db.Folder)
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const Mongoose = require('mongoose')
|
||||
|
||||
/**
|
||||
* BruteForce schema
|
||||
*
|
||||
* @type {<Mongoose.Schema>}
|
||||
*/
|
||||
var bruteForceSchema = Mongoose.Schema({
|
||||
_id: { type: String, index: 1 },
|
||||
data: {
|
||||
count: Number,
|
||||
lastRequest: Date,
|
||||
firstRequest: Date
|
||||
},
|
||||
expires: { type: Date, index: { expires: '1d' } }
|
||||
})
|
||||
|
||||
module.exports = Mongoose.model('Bruteforce', bruteForceSchema)
|
||||
@@ -0,0 +1,56 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Document schema
|
||||
*/
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
let documentSchema = sequelize.define('setting', {
|
||||
path: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
title: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
len: [2, 255]
|
||||
}
|
||||
},
|
||||
subtitle: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
parentPath: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
parentTitle: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
isDirectory: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
},
|
||||
isEntry: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
version: true,
|
||||
indexes: [
|
||||
{
|
||||
unique: true,
|
||||
fields: ['path']
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
return documentSchema
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const Mongoose = require('mongoose')
|
||||
|
||||
/**
|
||||
* Entry schema
|
||||
*
|
||||
* @type {<Mongoose.Schema>}
|
||||
*/
|
||||
var entrySchema = Mongoose.Schema({
|
||||
_id: String,
|
||||
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
minlength: 2
|
||||
},
|
||||
subtitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
parentTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
parentPath: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isDirectory: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isEntry: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}, {
|
||||
timestamps: {}
|
||||
})
|
||||
|
||||
module.exports = Mongoose.model('Entry', entrySchema)
|
||||
@@ -0,0 +1,44 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* File schema
|
||||
*/
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
let fileSchema = sequelize.define('file', {
|
||||
category: {
|
||||
type: DataTypes.ENUM('binary', 'image'),
|
||||
allowNull: false,
|
||||
defaultValue: 'binary'
|
||||
},
|
||||
mime: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: 'application/octet-stream'
|
||||
},
|
||||
extra: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true
|
||||
},
|
||||
filename: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
basename: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
filesize: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
isInt: true,
|
||||
min: 0
|
||||
}
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
version: true
|
||||
})
|
||||
|
||||
return fileSchema
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Folder schema
|
||||
*/
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
let folderSchema = sequelize.define('folder', {
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
version: true,
|
||||
indexes: [
|
||||
{
|
||||
unique: true,
|
||||
fields: ['name']
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
return folderSchema
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Group schema
|
||||
*/
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
let groupSchema = sequelize.define('group', {
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
version: true
|
||||
})
|
||||
|
||||
return groupSchema
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Right schema
|
||||
*/
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
let rightSchema = sequelize.define('right', {
|
||||
path: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
role: {
|
||||
type: DataTypes.ENUM('read', 'write', 'manage'),
|
||||
allowNull: false,
|
||||
defaultValue: 'read'
|
||||
},
|
||||
exact: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
},
|
||||
allow: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
version: true,
|
||||
indexes: [
|
||||
{
|
||||
fields: ['path']
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
return rightSchema
|
||||
}
|
||||
+22
-16
@@ -1,22 +1,28 @@
|
||||
'use strict'
|
||||
|
||||
const Mongoose = require('mongoose')
|
||||
|
||||
/**
|
||||
* Settings schema
|
||||
*
|
||||
* @type {<Mongoose.Schema>}
|
||||
*/
|
||||
var settingSchema = Mongoose.Schema({
|
||||
key: {
|
||||
type: String,
|
||||
required: true,
|
||||
index: true
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}, { timestamps: {} })
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
let settingSchema = sequelize.define('setting', {
|
||||
key: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
config: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: false
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
version: true,
|
||||
indexes: [
|
||||
{
|
||||
unique: true,
|
||||
fields: ['key']
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
module.exports = Mongoose.model('Setting', settingSchema)
|
||||
return settingSchema
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const Mongoose = require('mongoose')
|
||||
|
||||
/**
|
||||
* Upload File schema
|
||||
*
|
||||
* @type {<Mongoose.Schema>}
|
||||
*/
|
||||
var uplFileSchema = Mongoose.Schema({
|
||||
|
||||
_id: String,
|
||||
|
||||
category: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'binary'
|
||||
},
|
||||
mime: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'application/octet-stream'
|
||||
},
|
||||
extra: {
|
||||
type: Object
|
||||
},
|
||||
folder: {
|
||||
type: String,
|
||||
ref: 'UplFolder'
|
||||
},
|
||||
filename: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
basename: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
filesize: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
|
||||
}, { timestamps: {} })
|
||||
|
||||
module.exports = Mongoose.model('UplFile', uplFileSchema)
|
||||
@@ -1,21 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const Mongoose = require('mongoose')
|
||||
|
||||
/**
|
||||
* Upload Folder schema
|
||||
*
|
||||
* @type {<Mongoose.Schema>}
|
||||
*/
|
||||
var uplFolderSchema = Mongoose.Schema({
|
||||
|
||||
_id: String,
|
||||
|
||||
name: {
|
||||
type: String,
|
||||
index: true
|
||||
}
|
||||
|
||||
}, { timestamps: {} })
|
||||
|
||||
module.exports = Mongoose.model('UplFolder', uplFolderSchema)
|
||||
+96
-92
@@ -1,109 +1,113 @@
|
||||
'use strict'
|
||||
|
||||
/* global db, lang */
|
||||
/* global wiki */
|
||||
|
||||
const Mongoose = require('mongoose')
|
||||
const Promise = require('bluebird')
|
||||
const bcrypt = require('bcryptjs-then')
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* Users schema
|
||||
*
|
||||
* @type {<Mongoose.Schema>}
|
||||
*/
|
||||
var userSchema = Mongoose.Schema({
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
let userSchema = sequelize.define('user', {
|
||||
email: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
isEmail: true
|
||||
}
|
||||
},
|
||||
provider: {
|
||||
type: DataTypes.ENUM(wiki.data.authProviders),
|
||||
allowNull: false
|
||||
},
|
||||
providerId: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
password: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
role: {
|
||||
type: DataTypes.ENUM('admin', 'user', 'guest'),
|
||||
allowNull: false
|
||||
}
|
||||
}, {
|
||||
timestamps: true,
|
||||
version: true,
|
||||
indexes: [
|
||||
{
|
||||
unique: true,
|
||||
fields: ['provider', 'email']
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
index: true
|
||||
},
|
||||
|
||||
provider: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
|
||||
providerId: {
|
||||
type: String
|
||||
},
|
||||
|
||||
password: {
|
||||
type: String
|
||||
},
|
||||
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
|
||||
rights: [{
|
||||
role: String,
|
||||
path: String,
|
||||
exact: Boolean,
|
||||
deny: Boolean
|
||||
}]
|
||||
|
||||
}, { timestamps: {} })
|
||||
|
||||
userSchema.statics.processProfile = (profile) => {
|
||||
let primaryEmail = ''
|
||||
if (_.isArray(profile.emails)) {
|
||||
let e = _.find(profile.emails, ['primary', true])
|
||||
primaryEmail = (e) ? e.value : _.first(profile.emails).value
|
||||
} else if (_.isString(profile.email) && profile.email.length > 5) {
|
||||
primaryEmail = profile.email
|
||||
} else if (_.isString(profile.mail) && profile.mail.length > 5) {
|
||||
primaryEmail = profile.mail
|
||||
} else if (profile.user && profile.user.email && profile.user.email.length > 5) {
|
||||
primaryEmail = profile.user.email
|
||||
} else {
|
||||
return Promise.reject(new Error(lang.t('auth:errors.invaliduseremail')))
|
||||
userSchema.prototype.validatePassword = function (rawPwd) {
|
||||
return bcrypt.compare(rawPwd, this.password).then((isValid) => {
|
||||
return (isValid) ? true : Promise.reject(new Error(wiki.lang.t('auth:errors:invalidlogin')))
|
||||
})
|
||||
}
|
||||
|
||||
profile.provider = _.lowerCase(profile.provider)
|
||||
primaryEmail = _.toLower(primaryEmail)
|
||||
|
||||
return db.User.findOneAndUpdate({
|
||||
email: primaryEmail,
|
||||
provider: profile.provider
|
||||
}, {
|
||||
email: primaryEmail,
|
||||
provider: profile.provider,
|
||||
providerId: profile.id,
|
||||
name: profile.displayName || _.split(primaryEmail, '@')[0]
|
||||
}, {
|
||||
new: true
|
||||
}).then((user) => {
|
||||
// Handle unregistered accounts
|
||||
if (!user && profile.provider !== 'local' && (appconfig.auth.defaultReadAccess || profile.provider === 'ldap' || profile.provider === 'azure')) {
|
||||
let nUsr = {
|
||||
email: primaryEmail,
|
||||
provider: profile.provider,
|
||||
providerId: profile.id,
|
||||
password: '',
|
||||
name: profile.displayName || profile.name || profile.cn,
|
||||
rights: [{
|
||||
role: 'read',
|
||||
path: '/',
|
||||
exact: false,
|
||||
deny: false
|
||||
}]
|
||||
}
|
||||
return db.User.create(nUsr)
|
||||
userSchema.processProfile = (profile) => {
|
||||
let primaryEmail = ''
|
||||
if (_.isArray(profile.emails)) {
|
||||
let e = _.find(profile.emails, ['primary', true])
|
||||
primaryEmail = (e) ? e.value : _.first(profile.emails).value
|
||||
} else if (_.isString(profile.email) && profile.email.length > 5) {
|
||||
primaryEmail = profile.email
|
||||
} else if (_.isString(profile.mail) && profile.mail.length > 5) {
|
||||
primaryEmail = profile.mail
|
||||
} else if (profile.user && profile.user.email && profile.user.email.length > 5) {
|
||||
primaryEmail = profile.user.email
|
||||
} else {
|
||||
return Promise.reject(new Error(wiki.lang.t('auth:errors.invaliduseremail')))
|
||||
}
|
||||
return user || Promise.reject(new Error(lang.t('auth:errors:notyetauthorized')))
|
||||
})
|
||||
}
|
||||
|
||||
userSchema.statics.hashPassword = (rawPwd) => {
|
||||
return bcrypt.hash(rawPwd)
|
||||
}
|
||||
profile.provider = _.lowerCase(profile.provider)
|
||||
primaryEmail = _.toLower(primaryEmail)
|
||||
|
||||
userSchema.methods.validatePassword = function (rawPwd) {
|
||||
return bcrypt.compare(rawPwd, this.password).then((isValid) => {
|
||||
return (isValid) ? true : Promise.reject(new Error(lang.t('auth:errors:invalidlogin')))
|
||||
})
|
||||
}
|
||||
return wiki.db.User.findOneAndUpdate({
|
||||
email: primaryEmail,
|
||||
provider: profile.provider
|
||||
}, {
|
||||
email: primaryEmail,
|
||||
provider: profile.provider,
|
||||
providerId: profile.id,
|
||||
name: profile.displayName || _.split(primaryEmail, '@')[0]
|
||||
}, {
|
||||
new: true
|
||||
}).then((user) => {
|
||||
// Handle unregistered accounts
|
||||
if (!user && profile.provider !== 'local' && (appconfig.auth.defaultReadAccess || profile.provider === 'ldap' || profile.provider === 'azure')) {
|
||||
let nUsr = {
|
||||
email: primaryEmail,
|
||||
provider: profile.provider,
|
||||
providerId: profile.id,
|
||||
password: '',
|
||||
name: profile.displayName || profile.name || profile.cn,
|
||||
rights: [{
|
||||
role: 'read',
|
||||
path: '/',
|
||||
exact: false,
|
||||
deny: false
|
||||
}]
|
||||
}
|
||||
return db.User.create(nUsr)
|
||||
}
|
||||
return user || Promise.reject(new Error(wiki.lang.t('auth:errors:notyetauthorized')))
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = Mongoose.model('User', userSchema)
|
||||
userSchema.hashPassword = (rawPwd) => {
|
||||
return bcrypt.hash(rawPwd)
|
||||
}
|
||||
|
||||
return userSchema
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global appconfig, appdata, db, lang, winston */
|
||||
/* global wiki */
|
||||
|
||||
const fs = require('fs')
|
||||
|
||||
@@ -12,11 +12,11 @@ module.exports = function (passport) {
|
||||
})
|
||||
|
||||
passport.deserializeUser(function (id, done) {
|
||||
db.User.findById(id).then((user) => {
|
||||
wiki.db.User.findById(id).then((user) => {
|
||||
if (user) {
|
||||
done(null, user)
|
||||
} else {
|
||||
done(new Error(lang.t('auth:errors:usernotfound')), null)
|
||||
done(new Error(wiki.lang.t('auth:errors:usernotfound')), null)
|
||||
}
|
||||
return true
|
||||
}).catch((err) => {
|
||||
@@ -26,14 +26,14 @@ module.exports = function (passport) {
|
||||
|
||||
// Local Account
|
||||
|
||||
if (appconfig.auth.local && appconfig.auth.local.enabled) {
|
||||
if (wiki.config.auth.local && wiki.config.auth.local.enabled) {
|
||||
const LocalStrategy = require('passport-local').Strategy
|
||||
passport.use('local',
|
||||
new LocalStrategy({
|
||||
usernameField: 'email',
|
||||
passwordField: 'password'
|
||||
}, (uEmail, uPassword, done) => {
|
||||
db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => {
|
||||
wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => {
|
||||
if (user) {
|
||||
return user.validatePassword(uPassword).then(() => {
|
||||
return done(null, user) || true
|
||||
@@ -52,15 +52,15 @@ module.exports = function (passport) {
|
||||
|
||||
// Google ID
|
||||
|
||||
if (appconfig.auth.google && appconfig.auth.google.enabled) {
|
||||
if (wiki.config.auth.google && wiki.config.auth.google.enabled) {
|
||||
const GoogleStrategy = require('passport-google-oauth20').Strategy
|
||||
passport.use('google',
|
||||
new GoogleStrategy({
|
||||
clientID: appconfig.auth.google.clientId,
|
||||
clientSecret: appconfig.auth.google.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/google/callback'
|
||||
clientID: wiki.config.auth.google.clientId,
|
||||
clientSecret: wiki.config.auth.google.clientSecret,
|
||||
callbackURL: wiki.config.host + '/login/google/callback'
|
||||
}, (accessToken, refreshToken, profile, cb) => {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
wiki.db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
@@ -71,15 +71,15 @@ module.exports = function (passport) {
|
||||
|
||||
// Microsoft Accounts
|
||||
|
||||
if (appconfig.auth.microsoft && appconfig.auth.microsoft.enabled) {
|
||||
if (wiki.config.auth.microsoft && wiki.config.auth.microsoft.enabled) {
|
||||
const WindowsLiveStrategy = require('passport-windowslive').Strategy
|
||||
passport.use('windowslive',
|
||||
new WindowsLiveStrategy({
|
||||
clientID: appconfig.auth.microsoft.clientId,
|
||||
clientSecret: appconfig.auth.microsoft.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/ms/callback'
|
||||
clientID: wiki.config.auth.microsoft.clientId,
|
||||
clientSecret: wiki.config.auth.microsoft.clientSecret,
|
||||
callbackURL: wiki.config.host + '/login/ms/callback'
|
||||
}, function (accessToken, refreshToken, profile, cb) {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
wiki.db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
@@ -90,16 +90,16 @@ module.exports = function (passport) {
|
||||
|
||||
// Facebook
|
||||
|
||||
if (appconfig.auth.facebook && appconfig.auth.facebook.enabled) {
|
||||
if (wiki.config.auth.facebook && wiki.config.auth.facebook.enabled) {
|
||||
const FacebookStrategy = require('passport-facebook').Strategy
|
||||
passport.use('facebook',
|
||||
new FacebookStrategy({
|
||||
clientID: appconfig.auth.facebook.clientId,
|
||||
clientSecret: appconfig.auth.facebook.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/facebook/callback',
|
||||
clientID: wiki.config.auth.facebook.clientId,
|
||||
clientSecret: wiki.config.auth.facebook.clientSecret,
|
||||
callbackURL: wiki.config.host + '/login/facebook/callback',
|
||||
profileFields: ['id', 'displayName', 'email']
|
||||
}, function (accessToken, refreshToken, profile, cb) {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
wiki.db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
@@ -110,16 +110,16 @@ module.exports = function (passport) {
|
||||
|
||||
// GitHub
|
||||
|
||||
if (appconfig.auth.github && appconfig.auth.github.enabled) {
|
||||
if (wiki.config.auth.github && wiki.config.auth.github.enabled) {
|
||||
const GitHubStrategy = require('passport-github2').Strategy
|
||||
passport.use('github',
|
||||
new GitHubStrategy({
|
||||
clientID: appconfig.auth.github.clientId,
|
||||
clientSecret: appconfig.auth.github.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/github/callback',
|
||||
clientID: wiki.config.auth.github.clientId,
|
||||
clientSecret: wiki.config.auth.github.clientSecret,
|
||||
callbackURL: wiki.config.host + '/login/github/callback',
|
||||
scope: ['user:email']
|
||||
}, (accessToken, refreshToken, profile, cb) => {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
wiki.db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
@@ -130,15 +130,15 @@ module.exports = function (passport) {
|
||||
|
||||
// Slack
|
||||
|
||||
if (appconfig.auth.slack && appconfig.auth.slack.enabled) {
|
||||
if (wiki.config.auth.slack && wiki.config.auth.slack.enabled) {
|
||||
const SlackStrategy = require('passport-slack').Strategy
|
||||
passport.use('slack',
|
||||
new SlackStrategy({
|
||||
clientID: appconfig.auth.slack.clientId,
|
||||
clientSecret: appconfig.auth.slack.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/slack/callback'
|
||||
clientID: wiki.config.auth.slack.clientId,
|
||||
clientSecret: wiki.config.auth.slack.clientSecret,
|
||||
callbackURL: wiki.config.host + '/login/slack/callback'
|
||||
}, (accessToken, refreshToken, profile, cb) => {
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
wiki.db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
@@ -149,20 +149,20 @@ module.exports = function (passport) {
|
||||
|
||||
// LDAP
|
||||
|
||||
if (appconfig.auth.ldap && appconfig.auth.ldap.enabled) {
|
||||
if (wiki.config.auth.ldap && wiki.config.auth.ldap.enabled) {
|
||||
const LdapStrategy = require('passport-ldapauth').Strategy
|
||||
passport.use('ldapauth',
|
||||
new LdapStrategy({
|
||||
server: {
|
||||
url: appconfig.auth.ldap.url,
|
||||
bindDn: appconfig.auth.ldap.bindDn,
|
||||
bindCredentials: appconfig.auth.ldap.bindCredentials,
|
||||
searchBase: appconfig.auth.ldap.searchBase,
|
||||
searchFilter: appconfig.auth.ldap.searchFilter,
|
||||
url: wiki.config.auth.ldap.url,
|
||||
bindDn: wiki.config.auth.ldap.bindDn,
|
||||
bindCredentials: wiki.config.auth.ldap.bindCredentials,
|
||||
searchBase: wiki.config.auth.ldap.searchBase,
|
||||
searchFilter: wiki.config.auth.ldap.searchFilter,
|
||||
searchAttributes: ['displayName', 'name', 'cn', 'mail'],
|
||||
tlsOptions: (appconfig.auth.ldap.tlsEnabled) ? {
|
||||
tlsOptions: (wiki.config.auth.ldap.tlsEnabled) ? {
|
||||
ca: [
|
||||
fs.readFileSync(appconfig.auth.ldap.tlsCertPath)
|
||||
fs.readFileSync(wiki.config.auth.ldap.tlsCertPath)
|
||||
]
|
||||
} : {}
|
||||
},
|
||||
@@ -171,7 +171,7 @@ module.exports = function (passport) {
|
||||
}, (profile, cb) => {
|
||||
profile.provider = 'ldap'
|
||||
profile.id = profile.dn
|
||||
db.User.processProfile(profile).then((user) => {
|
||||
wiki.db.User.processProfile(profile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
@@ -182,21 +182,21 @@ module.exports = function (passport) {
|
||||
|
||||
// AZURE AD
|
||||
|
||||
if (appconfig.auth.azure && appconfig.auth.azure.enabled) {
|
||||
if (wiki.config.auth.azure && wiki.config.auth.azure.enabled) {
|
||||
const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy
|
||||
const jwt = require('jsonwebtoken')
|
||||
passport.use('azure_ad_oauth2',
|
||||
new AzureAdOAuth2Strategy({
|
||||
clientID: appconfig.auth.azure.clientId,
|
||||
clientSecret: appconfig.auth.azure.clientSecret,
|
||||
callbackURL: appconfig.host + '/login/azure/callback',
|
||||
resource: appconfig.auth.azure.resource,
|
||||
tenant: appconfig.auth.azure.tenant
|
||||
clientID: wiki.config.auth.azure.clientId,
|
||||
clientSecret: wiki.config.auth.azure.clientSecret,
|
||||
callbackURL: wiki.config.host + '/login/azure/callback',
|
||||
resource: wiki.config.auth.azure.resource,
|
||||
tenant: wiki.config.auth.azure.tenant
|
||||
}, (accessToken, refreshToken, params, profile, cb) => {
|
||||
let waadProfile = jwt.decode(params.id_token)
|
||||
waadProfile.id = waadProfile.oid
|
||||
waadProfile.provider = 'azure'
|
||||
db.User.processProfile(waadProfile).then((user) => {
|
||||
wiki.db.User.processProfile(waadProfile).then((user) => {
|
||||
return cb(null, user) || true
|
||||
}).catch((err) => {
|
||||
return cb(err, null) || true
|
||||
@@ -207,12 +207,12 @@ module.exports = function (passport) {
|
||||
|
||||
// Create users for first-time
|
||||
|
||||
db.onReady.then(() => {
|
||||
return db.User.findOne({ provider: 'local', email: 'guest' }).then((c) => {
|
||||
wiki.db.onReady.then(() => {
|
||||
return wiki.db.User.findOne({ provider: 'local', email: 'guest' }).then((c) => {
|
||||
if (c < 1) {
|
||||
// Create guest account
|
||||
|
||||
return db.User.create({
|
||||
return wiki.db.User.create({
|
||||
provider: 'local',
|
||||
email: 'guest',
|
||||
name: 'Guest',
|
||||
@@ -221,22 +221,22 @@ module.exports = function (passport) {
|
||||
role: 'read',
|
||||
path: '/',
|
||||
exact: false,
|
||||
deny: !appconfig.public
|
||||
deny: !wiki.config.public
|
||||
}]
|
||||
}).then(() => {
|
||||
winston.info('[AUTH] Guest account created successfully!')
|
||||
wiki.logger.info('[AUTH] Guest account created successfully!')
|
||||
}).catch((err) => {
|
||||
winston.error('[AUTH] An error occured while creating guest account:')
|
||||
winston.error(err)
|
||||
wiki.logger.error('[AUTH] An error occured while creating guest account:')
|
||||
wiki.logger.error(err)
|
||||
})
|
||||
}
|
||||
}).then(() => {
|
||||
if (process.env.WIKI_JS_HEROKU) {
|
||||
return db.User.findOne({ provider: 'local', email: process.env.WIKI_ADMIN_EMAIL }).then((c) => {
|
||||
return wiki.db.User.findOne({ provider: 'local', email: process.env.WIKI_ADMIN_EMAIL }).then((c) => {
|
||||
if (c < 1) {
|
||||
// Create root admin account (HEROKU ONLY)
|
||||
|
||||
return db.User.create({
|
||||
return wiki.db.User.create({
|
||||
provider: 'local',
|
||||
email: process.env.WIKI_ADMIN_EMAIL,
|
||||
name: 'Administrator',
|
||||
@@ -248,10 +248,10 @@ module.exports = function (passport) {
|
||||
deny: false
|
||||
}]
|
||||
}).then(() => {
|
||||
winston.info('[AUTH] Root admin account created successfully!')
|
||||
wiki.logger.info('[AUTH] Root admin account created successfully!')
|
||||
}).catch((err) => {
|
||||
winston.error('[AUTH] An error occured while creating root admin account:')
|
||||
winston.error(err)
|
||||
wiki.logger.error('[AUTH] An error occured while creating root admin account:')
|
||||
wiki.logger.error(err)
|
||||
})
|
||||
} else { return true }
|
||||
})
|
||||
@@ -1,5 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
/* global wiki */
|
||||
|
||||
const fs = require('fs')
|
||||
const yaml = require('js-yaml')
|
||||
const _ = require('lodash')
|
||||
@@ -14,9 +16,9 @@ const cfgHelper = require('../helpers/config')
|
||||
*/
|
||||
module.exports = (confPaths) => {
|
||||
confPaths = _.defaults(confPaths, {
|
||||
config: path.join(ROOTPATH, 'config.yml'),
|
||||
data: path.join(SERVERPATH, 'app/data.yml'),
|
||||
dataRegex: path.join(SERVERPATH, 'app/regex.js')
|
||||
config: path.join(wiki.ROOTPATH, 'config.yml'),
|
||||
data: path.join(wiki.SERVERPATH, 'app/data.yml'),
|
||||
dataRegex: path.join(wiki.SERVERPATH, 'app/regex.js')
|
||||
})
|
||||
|
||||
let appconfig = {}
|
||||
@@ -0,0 +1,74 @@
|
||||
'use strict'
|
||||
|
||||
/* global wiki */
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* PostgreSQL DB module
|
||||
*/
|
||||
module.exports = {
|
||||
|
||||
Sequelize: require('sequelize'),
|
||||
|
||||
/**
|
||||
* Initialize DB
|
||||
*
|
||||
* @return {Object} DB instance
|
||||
*/
|
||||
init() {
|
||||
let self = this
|
||||
|
||||
let dbModelsPath = path.join(wiki.SERVERPATH, 'models')
|
||||
|
||||
// Define Sequelize instance
|
||||
|
||||
self.inst = new self.Sequelize(wiki.config.db.db, wiki.config.db.user, wiki.config.db.pass, {
|
||||
host: wiki.config.db.host,
|
||||
port: wiki.config.db.port,
|
||||
dialect: 'postgres',
|
||||
pool: {
|
||||
max: 10,
|
||||
min: 0,
|
||||
idle: 10000
|
||||
}
|
||||
})
|
||||
|
||||
// Attempt to connect and authenticate to DB
|
||||
|
||||
self.inst.authenticate().then(() => {
|
||||
wiki.logger.info('Connected to PostgreSQL database.')
|
||||
}).catch(err => {
|
||||
wiki.logger.error('Failed to connect to MongoDB instance.')
|
||||
return err
|
||||
})
|
||||
|
||||
// Load DB Models
|
||||
|
||||
fs
|
||||
.readdirSync(dbModelsPath)
|
||||
.filter(function (file) {
|
||||
return (file.indexOf('.') !== 0 && file.indexOf('_') !== 0)
|
||||
})
|
||||
.forEach(function (file) {
|
||||
let modelName = _.upperFirst(_.camelCase(_.split(file, '.')[0]))
|
||||
self[modelName] = self.inst.import(path.join(dbModelsPath, file))
|
||||
})
|
||||
|
||||
// Associate DB Models
|
||||
|
||||
require(path.join(dbModelsPath, '_relations.js'))(self)
|
||||
|
||||
// Sync DB
|
||||
|
||||
self.onReady = self.inst.sync({
|
||||
force: false,
|
||||
logging: wiki.logger.verbose
|
||||
})
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global lang, winston */
|
||||
/* global wiki */
|
||||
|
||||
const path = require('path')
|
||||
const Promise = require('bluebird')
|
||||
@@ -10,7 +10,7 @@ const os = require('os')
|
||||
const _ = require('lodash')
|
||||
|
||||
/**
|
||||
* Local Data Storage
|
||||
* Local Disk Storage
|
||||
*/
|
||||
module.exports = {
|
||||
|
||||
@@ -21,29 +21,24 @@ module.exports = {
|
||||
|
||||
/**
|
||||
* Initialize Local Data Storage model
|
||||
*
|
||||
* @return {Object} Local Data Storage model instance
|
||||
*/
|
||||
init () {
|
||||
this._uploadsPath = path.resolve(ROOTPATH, appconfig.paths.repo, 'uploads')
|
||||
this._uploadsThumbsPath = path.resolve(ROOTPATH, appconfig.paths.data, 'thumbs')
|
||||
this._uploadsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, 'uploads')
|
||||
this._uploadsThumbsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'thumbs')
|
||||
|
||||
this.createBaseDirectories(appconfig)
|
||||
this.initMulter(appconfig)
|
||||
this.createBaseDirectories()
|
||||
this.initMulter()
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
/**
|
||||
* Init Multer upload handlers
|
||||
*
|
||||
* @param {Object} appconfig The application config
|
||||
* @return {boolean} Void
|
||||
*/
|
||||
initMulter (appconfig) {
|
||||
initMulter () {
|
||||
let maxFileSizes = {
|
||||
img: appconfig.uploads.maxImageFileSize * 1024 * 1024,
|
||||
file: appconfig.uploads.maxOtherFileSize * 1024 * 1024
|
||||
img: wiki.config.uploads.maxImageFileSize * 1024 * 1024,
|
||||
file: wiki.config.uploads.maxOtherFileSize * 1024 * 1024
|
||||
}
|
||||
|
||||
// -> IMAGES
|
||||
@@ -51,7 +46,7 @@ module.exports = {
|
||||
this.uploadImgHandler = multer({
|
||||
storage: multer.diskStorage({
|
||||
destination: (req, f, cb) => {
|
||||
cb(null, path.resolve(ROOTPATH, appconfig.paths.data, 'temp-upload'))
|
||||
cb(null, path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'temp-upload'))
|
||||
}
|
||||
}),
|
||||
fileFilter: (req, f, cb) => {
|
||||
@@ -76,7 +71,7 @@ module.exports = {
|
||||
this.uploadFileHandler = multer({
|
||||
storage: multer.diskStorage({
|
||||
destination: (req, f, cb) => {
|
||||
cb(null, path.resolve(ROOTPATH, appconfig.paths.data, 'temp-upload'))
|
||||
cb(null, path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'temp-upload'))
|
||||
}
|
||||
}),
|
||||
fileFilter: (req, f, cb) => {
|
||||
@@ -95,35 +90,32 @@ module.exports = {
|
||||
|
||||
/**
|
||||
* Creates a base directories (Synchronous).
|
||||
*
|
||||
* @param {Object} appconfig The application config
|
||||
* @return {Void} Void
|
||||
*/
|
||||
createBaseDirectories (appconfig) {
|
||||
winston.info('Checking data directories...')
|
||||
createBaseDirectories () {
|
||||
wiki.logger.info('Checking data directories...')
|
||||
|
||||
try {
|
||||
fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data))
|
||||
fs.emptyDirSync(path.resolve(ROOTPATH, appconfig.paths.data))
|
||||
fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './cache'))
|
||||
fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './thumbs'))
|
||||
fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './temp-upload'))
|
||||
fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data))
|
||||
fs.emptyDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data))
|
||||
fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './cache'))
|
||||
fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './thumbs'))
|
||||
fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './temp-upload'))
|
||||
|
||||
if (os.type() !== 'Windows_NT') {
|
||||
fs.chmodSync(path.resolve(ROOTPATH, appconfig.paths.data, './temp-upload'), '755')
|
||||
fs.chmodSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './temp-upload'), '755')
|
||||
}
|
||||
|
||||
fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.repo))
|
||||
fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.repo, './uploads'))
|
||||
fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo))
|
||||
fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, './uploads'))
|
||||
|
||||
if (os.type() !== 'Windows_NT') {
|
||||
fs.chmodSync(path.resolve(ROOTPATH, appconfig.paths.repo, './uploads'), '755')
|
||||
fs.chmodSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, './uploads'), '755')
|
||||
}
|
||||
} catch (err) {
|
||||
winston.error(err)
|
||||
wiki.logger.error(err)
|
||||
}
|
||||
|
||||
winston.info('Data and Repository directories are OK.')
|
||||
wiki.logger.info('Data and Repository directories are OK.')
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -154,7 +146,7 @@ module.exports = {
|
||||
*/
|
||||
validateUploadsFilename (f, fld, isImage) {
|
||||
let fObj = path.parse(f)
|
||||
let fname = _.chain(fObj.name).trim().toLower().kebabCase().value().replace(new RegExp('[^a-z0-9-' + appdata.regex.cjk + appdata.regex.arabic + ']', 'g'), '')
|
||||
let fname = _.chain(fObj.name).trim().toLower().kebabCase().value().replace(new RegExp('[^a-z0-9-' + wiki.data.regex.cjk + wiki.data.regex.arabic + ']', 'g'), '')
|
||||
let fext = _.toLower(fObj.ext)
|
||||
|
||||
if (isImage && !_.includes(['.jpg', '.jpeg', '.png', '.gif', '.webp'], fext)) {
|
||||
@@ -165,7 +157,7 @@ module.exports = {
|
||||
let fpath = path.resolve(this._uploadsPath, fld, f)
|
||||
|
||||
return fs.statAsync(fpath).then((s) => {
|
||||
throw new Error(lang.t('errors:fileexists', { path: f }))
|
||||
throw new Error(wiki.lang.t('errors:fileexists', { path: f }))
|
||||
}).catch((err) => {
|
||||
if (err.code === 'ENOENT') {
|
||||
return f
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global db, git, lang, mark, rights, search, winston */
|
||||
/* global wiki */
|
||||
|
||||
const Promise = require('bluebird')
|
||||
const path = require('path')
|
||||
@@ -25,10 +25,10 @@ module.exports = {
|
||||
init() {
|
||||
let self = this
|
||||
|
||||
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
|
||||
self._repoPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo)
|
||||
self._cachePath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'cache')
|
||||
wiki.data.repoPath = self._repoPath
|
||||
wiki.data.cachePath = self._cachePath
|
||||
|
||||
return self
|
||||
},
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global lang, winston */
|
||||
/* global wiki */
|
||||
|
||||
const Git = require('git-wrapper2-promise')
|
||||
const Promise = require('bluebird')
|
||||
@@ -43,20 +43,20 @@ module.exports = {
|
||||
|
||||
// -> Build repository path
|
||||
|
||||
if (_.isEmpty(appconfig.paths.repo)) {
|
||||
self._repo.path = path.join(ROOTPATH, 'repo')
|
||||
if (_.isEmpty(wiki.config.paths.repo)) {
|
||||
self._repo.path = path.join(wiki.ROOTPATH, 'repo')
|
||||
} else {
|
||||
self._repo.path = appconfig.paths.repo
|
||||
self._repo.path = wiki.config.paths.repo
|
||||
}
|
||||
|
||||
// -> Initialize repository
|
||||
|
||||
self.onReady = self._initRepo(appconfig)
|
||||
self.onReady = self._initRepo()
|
||||
|
||||
// Define signature
|
||||
|
||||
if (appconfig.git) {
|
||||
self._signature.email = appconfig.git.serverEmail || 'wiki@example.com'
|
||||
if (wiki.config.git) {
|
||||
self._signature.email = wiki.config.git.serverEmail || 'wiki@example.com'
|
||||
}
|
||||
|
||||
return self
|
||||
@@ -65,19 +65,19 @@ module.exports = {
|
||||
/**
|
||||
* Initialize Git repository
|
||||
*
|
||||
* @param {Object} appconfig The application config
|
||||
* @param {Object} wiki.config The application config
|
||||
* @return {Object} Promise
|
||||
*/
|
||||
_initRepo(appconfig) {
|
||||
_initRepo() {
|
||||
let self = this
|
||||
|
||||
winston.info('Checking Git repository...')
|
||||
wiki.logger.info('Checking Git repository...')
|
||||
|
||||
// -> Check if path is accessible
|
||||
|
||||
return fs.mkdirAsync(self._repo.path).catch((err) => {
|
||||
if (err.code !== 'EEXIST') {
|
||||
winston.error('Invalid Git repository path or missing permissions.')
|
||||
wiki.logger.error('Invalid Git repository path or missing permissions.')
|
||||
}
|
||||
}).then(() => {
|
||||
self._git = new Git({ 'git-dir': self._repo.path })
|
||||
@@ -91,28 +91,28 @@ module.exports = {
|
||||
self._repo.exists = false
|
||||
})
|
||||
}).then(() => {
|
||||
if (appconfig.git === false) {
|
||||
winston.info('Remote Git syncing is disabled. Not recommended!')
|
||||
if (wiki.config.git === false) {
|
||||
wiki.logger.info('Remote Git syncing is disabled. Not recommended!')
|
||||
return Promise.resolve(true)
|
||||
}
|
||||
|
||||
// Initialize remote
|
||||
|
||||
let urlObj = URL.parse(appconfig.git.url)
|
||||
if (appconfig.git.auth.type !== 'ssh') {
|
||||
urlObj.auth = appconfig.git.auth.username + ':' + appconfig.git.auth.password
|
||||
let urlObj = URL.parse(wiki.config.git.url)
|
||||
if (wiki.config.git.auth.type !== 'ssh') {
|
||||
urlObj.auth = wiki.config.git.auth.username + ':' + wiki.config.git.auth.password
|
||||
}
|
||||
self._url = URL.format(urlObj)
|
||||
|
||||
let gitConfigs = [
|
||||
() => { return self._git.exec('config', ['--local', 'user.name', 'Wiki']) },
|
||||
() => { return self._git.exec('config', ['--local', 'user.email', self._signature.email]) },
|
||||
() => { return self._git.exec('config', ['--local', '--bool', 'http.sslVerify', _.toString(appconfig.git.auth.sslVerify)]) }
|
||||
() => { return self._git.exec('config', ['--local', '--bool', 'http.sslVerify', _.toString(wiki.config.git.auth.sslVerify)]) }
|
||||
]
|
||||
|
||||
if (appconfig.git.auth.type === 'ssh') {
|
||||
if (wiki.config.git.auth.type === 'ssh') {
|
||||
gitConfigs.push(() => {
|
||||
return self._git.exec('config', ['--local', 'core.sshCommand', 'ssh -i "' + appconfig.git.auth.privateKey + '" -o StrictHostKeyChecking=no'])
|
||||
return self._git.exec('config', ['--local', 'core.sshCommand', 'ssh -i "' + wiki.config.git.auth.privateKey + '" -o StrictHostKeyChecking=no'])
|
||||
})
|
||||
}
|
||||
|
||||
@@ -125,14 +125,14 @@ module.exports = {
|
||||
return self._git.exec('remote', ['set-url', 'origin', self._url])
|
||||
}
|
||||
}).catch(err => {
|
||||
winston.error(err)
|
||||
wiki.logger.error(err)
|
||||
})
|
||||
})
|
||||
}).catch((err) => {
|
||||
winston.error('Git remote error!')
|
||||
wiki.logger.error('Git remote error!')
|
||||
throw err
|
||||
}).then(() => {
|
||||
winston.info('Git repository is OK.')
|
||||
wiki.logger.info('Git repository is OK.')
|
||||
return true
|
||||
})
|
||||
},
|
||||
@@ -143,7 +143,7 @@ module.exports = {
|
||||
* @return {String} The repo path.
|
||||
*/
|
||||
getRepoPath() {
|
||||
return this._repo.path || path.join(ROOTPATH, 'repo')
|
||||
return this._repo.path || path.join(wiki.ROOTPATH, 'repo')
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -156,18 +156,18 @@ module.exports = {
|
||||
|
||||
// Is git remote disabled?
|
||||
|
||||
if (appconfig.git === false) {
|
||||
if (wiki.config.git === false) {
|
||||
return Promise.resolve(true)
|
||||
}
|
||||
|
||||
// Fetch
|
||||
|
||||
winston.info('Performing pull from remote Git repository...')
|
||||
wiki.logger.info('Performing pull from remote Git repository...')
|
||||
return self._git.pull('origin', self._repo.branch).then((cProc) => {
|
||||
winston.info('Git Pull completed.')
|
||||
wiki.logger.info('Git Pull completed.')
|
||||
})
|
||||
.catch((err) => {
|
||||
winston.error('Unable to fetch from git origin!')
|
||||
wiki.logger.error('Unable to fetch from git origin!')
|
||||
throw err
|
||||
})
|
||||
.then(() => {
|
||||
@@ -177,19 +177,19 @@ module.exports = {
|
||||
let out = cProc.stdout.toString()
|
||||
|
||||
if (_.includes(out, 'commit')) {
|
||||
winston.info('Performing push to remote Git repository...')
|
||||
wiki.logger.info('Performing push to remote Git repository...')
|
||||
return self._git.push('origin', self._repo.branch).then(() => {
|
||||
return winston.info('Git Push completed.')
|
||||
return wiki.logger.info('Git Push completed.')
|
||||
})
|
||||
} else {
|
||||
winston.info('Git Push skipped. Repository is already in sync.')
|
||||
wiki.logger.info('Git Push skipped. Repository is already in sync.')
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
})
|
||||
.catch((err) => {
|
||||
winston.error('Unable to push changes to remote Git repository!')
|
||||
wiki.logger.error('Unable to push changes to remote Git repository!')
|
||||
throw err
|
||||
})
|
||||
},
|
||||
@@ -209,7 +209,7 @@ module.exports = {
|
||||
let out = cProc.stdout.toString()
|
||||
return _.includes(out, gitFilePath)
|
||||
}).then((isTracked) => {
|
||||
commitMsg = (isTracked) ? lang.t('git:updated', { path: gitFilePath }) : lang.t('git:added', { path: gitFilePath })
|
||||
commitMsg = (isTracked) ? wiki.lang.t('git:updated', { path: gitFilePath }) : wiki.lang.t('git:added', { path: gitFilePath })
|
||||
return self._git.add(gitFilePath)
|
||||
}).then(() => {
|
||||
let commitUsr = securityHelper.sanitizeCommitUser(author)
|
||||
@@ -1,6 +1,8 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = (isDebug, processName) => {
|
||||
/* global wiki */
|
||||
|
||||
module.exports = (processName) => {
|
||||
let winston = require('winston')
|
||||
|
||||
if (typeof processName === 'undefined') {
|
||||
@@ -10,10 +12,10 @@ module.exports = (isDebug, processName) => {
|
||||
// Console
|
||||
|
||||
let logger = new (winston.Logger)({
|
||||
level: (isDebug) ? 'debug' : 'info',
|
||||
level: (wiki.IS_DEBUG) ? 'debug' : 'info',
|
||||
transports: [
|
||||
new (winston.transports.Console)({
|
||||
level: (isDebug) ? 'debug' : 'info',
|
||||
level: (wiki.IS_DEBUG) ? 'debug' : 'info',
|
||||
prettyPrint: true,
|
||||
colorize: true,
|
||||
silent: false,
|
||||
@@ -28,48 +30,48 @@ module.exports = (isDebug, processName) => {
|
||||
|
||||
// External services
|
||||
|
||||
if (appconfig.externalLogging.bugsnag) {
|
||||
if (wiki.config.externalLogging.bugsnag) {
|
||||
const bugsnagTransport = require('./winston-transports/bugsnag')
|
||||
logger.add(bugsnagTransport, {
|
||||
level: 'warn',
|
||||
key: appconfig.externalLogging.bugsnag
|
||||
key: wiki.config.externalLogging.bugsnag
|
||||
})
|
||||
}
|
||||
|
||||
if (appconfig.externalLogging.loggly) {
|
||||
if (wiki.config.externalLogging.loggly) {
|
||||
require('winston-loggly-bulk')
|
||||
logger.add(winston.transports.Loggly, {
|
||||
token: appconfig.externalLogging.loggly.token,
|
||||
subdomain: appconfig.externalLogging.loggly.subdomain,
|
||||
token: wiki.config.externalLogging.loggly.token,
|
||||
subdomain: wiki.config.externalLogging.loggly.subdomain,
|
||||
tags: ['wiki-js'],
|
||||
level: 'warn',
|
||||
json: true
|
||||
})
|
||||
}
|
||||
|
||||
if (appconfig.externalLogging.papertrail) {
|
||||
if (wiki.config.externalLogging.papertrail) {
|
||||
require('winston-papertrail').Papertrail // eslint-disable-line no-unused-expressions
|
||||
logger.add(winston.transports.Papertrail, {
|
||||
host: appconfig.externalLogging.papertrail.host,
|
||||
port: appconfig.externalLogging.papertrail.port,
|
||||
host: wiki.config.externalLogging.papertrail.host,
|
||||
port: wiki.config.externalLogging.papertrail.port,
|
||||
level: 'warn',
|
||||
program: 'wiki.js'
|
||||
})
|
||||
}
|
||||
|
||||
if (appconfig.externalLogging.rollbar) {
|
||||
if (wiki.config.externalLogging.rollbar) {
|
||||
const rollbarTransport = require('./winston-transports/rollbar')
|
||||
logger.add(rollbarTransport, {
|
||||
level: 'warn',
|
||||
key: appconfig.externalLogging.rollbar
|
||||
key: wiki.config.externalLogging.rollbar
|
||||
})
|
||||
}
|
||||
|
||||
if (appconfig.externalLogging.sentry) {
|
||||
if (wiki.config.externalLogging.sentry) {
|
||||
const sentryTransport = require('./winston-transports/sentry')
|
||||
logger.add(sentryTransport, {
|
||||
level: 'warn',
|
||||
key: appconfig.externalLogging.sentry
|
||||
key: wiki.config.externalLogging.sentry
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global winston */
|
||||
/* global wiki */
|
||||
|
||||
const Promise = require('bluebird')
|
||||
const md = require('markdown-it')
|
||||
@@ -23,11 +23,11 @@ const mdRemove = require('remove-markdown')
|
||||
|
||||
var mkdown = md({
|
||||
html: true,
|
||||
breaks: appconfig.features.linebreaks,
|
||||
breaks: wiki.config.features.linebreaks,
|
||||
linkify: true,
|
||||
typography: true,
|
||||
highlight(str, lang) {
|
||||
if (appconfig.theme.code.colorize && lang && hljs.getLanguage(lang)) {
|
||||
if (wiki.config.theme.code.colorize && lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return '<pre class="hljs"><code>' + hljs.highlight(lang, str, true).value + '</code></pre>'
|
||||
} catch (err) {
|
||||
@@ -57,7 +57,7 @@ var mkdown = md({
|
||||
})
|
||||
.use(mdAttrs)
|
||||
|
||||
if (appconfig.features.mathjax) {
|
||||
if (wiki.config.features.mathjax) {
|
||||
mkdown.use(mdMathjax)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ const videoRules = [
|
||||
|
||||
// Regex
|
||||
|
||||
const textRegex = new RegExp('\\b[a-z0-9-.,' + appdata.regex.cjk + appdata.regex.arabic + ']+\\b', 'g')
|
||||
const textRegex = new RegExp('\\b[a-z0-9-.,' + wiki.data.regex.cjk + wiki.data.regex.arabic + ']+\\b', 'g')
|
||||
const mathRegex = [
|
||||
{
|
||||
format: 'TeX',
|
||||
@@ -301,7 +301,7 @@ const parseContent = (content) => {
|
||||
|
||||
// Mathjax Post-processor
|
||||
|
||||
if (appconfig.features.mathjax) {
|
||||
if (wiki.config.features.mathjax) {
|
||||
return processMathjax(cr.html())
|
||||
} else {
|
||||
return Promise.resolve(cr.html())
|
||||
@@ -339,7 +339,7 @@ const processMathjax = (content) => {
|
||||
resolve(result.svg)
|
||||
} else {
|
||||
resolve(currentMatch[0])
|
||||
winston.warn(result.errors.join(', '))
|
||||
wiki.logger.warn(result.errors.join(', '))
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
'use strict'
|
||||
|
||||
/* global wiki */
|
||||
|
||||
const Redis = require('ioredis')
|
||||
const { isPlainObject } = require('lodash')
|
||||
|
||||
/**
|
||||
* Redis module
|
||||
*
|
||||
* @return {Object} Redis client wrapper instance
|
||||
*/
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Initialize Redis client
|
||||
*
|
||||
* @return {Object} Redis client instance
|
||||
*/
|
||||
init() {
|
||||
if (isPlainObject(wiki.config.redis)) {
|
||||
return new Redis(wiki.config.redis)
|
||||
} else {
|
||||
wiki.logger.error('Invalid Redis configuration!')
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global db */
|
||||
/* global wiki */
|
||||
|
||||
const _ = require('lodash')
|
||||
|
||||
@@ -32,8 +32,8 @@ module.exports = {
|
||||
init () {
|
||||
let self = this
|
||||
|
||||
db.onReady.then(() => {
|
||||
db.User.findOne({ provider: 'local', email: 'guest' }).then((u) => {
|
||||
wiki.db.onReady.then(() => {
|
||||
wiki.db.User.findOne({ provider: 'local', email: 'guest' }).then((u) => {
|
||||
if (u) {
|
||||
self.guest = u
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
'use strict'
|
||||
|
||||
/* global winston */
|
||||
/* global wiki */
|
||||
|
||||
const Promise = require('bluebird')
|
||||
const _ = require('lodash')
|
||||
const searchIndex = require('./search-index')
|
||||
const stopWord = require('stopword')
|
||||
const streamToPromise = require('stream-to-promise')
|
||||
const searchAllowedChars = new RegExp('[^a-z0-9' + appdata.regex.cjk + appdata.regex.arabic + ' ]', 'g')
|
||||
const searchAllowedChars = new RegExp('[^a-z0-9' + wiki.data.regex.cjk + wiki.data.regex.arabic + ' ]', 'g')
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -27,15 +27,15 @@ module.exports = {
|
||||
fieldedSearch: true,
|
||||
indexPath: 'wiki',
|
||||
logLevel: 'error',
|
||||
stopwords: _.get(stopWord, appconfig.lang, [])
|
||||
stopwords: _.get(stopWord, wiki.config.lang, [])
|
||||
}, (err, si) => {
|
||||
if (err) {
|
||||
winston.error('Failed to initialize search index.', err)
|
||||
wiki.logger.error('Failed to initialize search index.', err)
|
||||
reject(err)
|
||||
} else {
|
||||
self._si = Promise.promisifyAll(si)
|
||||
self._si.flushAsync().then(() => {
|
||||
winston.info('Search index flushed and ready.')
|
||||
wiki.logger.info('Search index flushed and ready.')
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
@@ -95,13 +95,13 @@ module.exports = {
|
||||
parent: content.parent || '',
|
||||
content: content.text || ''
|
||||
}]).then(() => {
|
||||
winston.log('verbose', 'Entry ' + content._id + ' added/updated to search index.')
|
||||
wiki.logger.log('verbose', 'Entry ' + content._id + ' added/updated to search index.')
|
||||
return true
|
||||
}).catch((err) => {
|
||||
winston.error(err)
|
||||
wiki.logger.error(err)
|
||||
})
|
||||
}).catch((err) => {
|
||||
winston.error(err)
|
||||
wiki.logger.error(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -131,7 +131,7 @@ module.exports = {
|
||||
if (err.type === 'NotFoundError') {
|
||||
return true
|
||||
} else {
|
||||
winston.error(err)
|
||||
wiki.logger.error(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -204,7 +204,7 @@ module.exports = {
|
||||
suggest: []
|
||||
}
|
||||
} else {
|
||||
winston.error(err)
|
||||
wiki.logger.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
/* global db, lang, lcdata, upl, winston */
|
||||
/* global wiki */
|
||||
|
||||
const path = require('path')
|
||||
const Promise = require('bluebird')
|
||||
@@ -27,8 +27,8 @@ module.exports = {
|
||||
* @return {Object} Uploads model instance
|
||||
*/
|
||||
init () {
|
||||
this._uploadsPath = path.resolve(ROOTPATH, appconfig.paths.repo, 'uploads')
|
||||
this._uploadsThumbsPath = path.resolve(ROOTPATH, appconfig.paths.data, 'thumbs')
|
||||
this._uploadsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, 'uploads')
|
||||
this._uploadsThumbsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'thumbs')
|
||||
|
||||
return this
|
||||
},
|
||||
@@ -48,7 +48,7 @@ module.exports = {
|
||||
* @return {Array<String>} The uploads folders.
|
||||
*/
|
||||
getUploadsFolders () {
|
||||
return db.UplFolder.find({}, 'name').sort('name').exec().then((results) => {
|
||||
return wiki.db.Folder.find({}, 'name').sort('name').exec().then((results) => {
|
||||
return (results) ? _.map(results, 'name') : [{ name: '' }]
|
||||
})
|
||||
},
|
||||
@@ -69,7 +69,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
return fs.ensureDirAsync(path.join(self._uploadsPath, folderName)).then(() => {
|
||||
return db.UplFolder.findOneAndUpdate({
|
||||
return wiki.db.UplFolder.findOneAndUpdate({
|
||||
_id: 'f:' + folderName
|
||||
}, {
|
||||
name: folderName
|
||||
@@ -88,7 +88,7 @@ module.exports = {
|
||||
* @return {Boolean} True if valid
|
||||
*/
|
||||
validateUploadsFolder (folderName) {
|
||||
return db.UplFolder.findOne({ name: folderName }).then((f) => {
|
||||
return wiki.db.UplFolder.findOne({ name: folderName }).then((f) => {
|
||||
return (f) ? path.resolve(this._uploadsPath, folderName) : false
|
||||
})
|
||||
},
|
||||
@@ -101,7 +101,7 @@ module.exports = {
|
||||
*/
|
||||
addUploadsFiles (arrFiles) {
|
||||
if (_.isArray(arrFiles) || _.isPlainObject(arrFiles)) {
|
||||
// this._uploadsDb.Files.insert(arrFiles);
|
||||
// this._uploadswiki.Db.Files.insert(arrFiles);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -113,7 +113,7 @@ module.exports = {
|
||||
* @return {Array<Object>} The files matching the query
|
||||
*/
|
||||
getUploadsFiles (cat, fld) {
|
||||
return db.UplFile.find({
|
||||
return wiki.db.UplFile.find({
|
||||
category: cat,
|
||||
folder: 'f:' + fld
|
||||
}).sort('filename').exec()
|
||||
@@ -128,7 +128,7 @@ module.exports = {
|
||||
deleteUploadsFile (uid) {
|
||||
let self = this
|
||||
|
||||
return db.UplFile.findOneAndRemove({ _id: uid }).then((f) => {
|
||||
return wiki.db.UplFile.findOneAndRemove({ _id: uid }).then((f) => {
|
||||
if (f) {
|
||||
return self.deleteUploadsFileTry(f, 0)
|
||||
}
|
||||
@@ -150,7 +150,7 @@ module.exports = {
|
||||
return self.deleteUploadsFileTry(f, attempt + 1)
|
||||
})
|
||||
} else {
|
||||
winston.warn('Unable to delete uploads file ' + f.filename + '. File is locked by another process and multiple attempts failed.')
|
||||
wiki.logger.warn('Unable to delete uploads file ' + f.filename + '. File is locked by another process and multiple attempts failed.')
|
||||
return true
|
||||
}
|
||||
})
|
||||
@@ -168,12 +168,12 @@ module.exports = {
|
||||
let fUrlFilename = _.last(_.split(fUrlObj.pathname, '/'))
|
||||
let destFolder = _.chain(fFolder).trim().toLower().value()
|
||||
|
||||
return upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
|
||||
return wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
|
||||
if (!destFolderPath) {
|
||||
return Promise.reject(new Error(lang.t('errors:invalidfolder')))
|
||||
return Promise.reject(new Error(wiki.lang.t('errors:invalidfolder')))
|
||||
}
|
||||
|
||||
return lcdata.validateUploadsFilename(fUrlFilename, destFolder).then((destFilename) => {
|
||||
return wiki.disk.validateUploadsFilename(fUrlFilename, destFolder).then((destFilename) => {
|
||||
let destFilePath = path.resolve(destFolderPath, destFilename)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -194,7 +194,7 @@ module.exports = {
|
||||
rq.abort()
|
||||
destFileStream.destroy()
|
||||
fs.remove(destFilePath)
|
||||
reject(new Error(lang.t('errors:remotetoolarge')))
|
||||
reject(new Error(wiki.lang.t('errors:remotetoolarge')))
|
||||
}
|
||||
}).on('error', (err) => {
|
||||
destFileStream.destroy()
|
||||
@@ -223,15 +223,15 @@ module.exports = {
|
||||
moveUploadsFile (uid, fld, nFilename) {
|
||||
let self = this
|
||||
|
||||
return db.UplFolder.findById('f:' + fld).then((folder) => {
|
||||
return wiki.db.UplFolder.finwiki.dById('f:' + fld).then((folder) => {
|
||||
if (folder) {
|
||||
return db.UplFile.findById(uid).then((originFile) => {
|
||||
return wiki.db.UplFile.finwiki.dById(uid).then((originFile) => {
|
||||
// -> Check if rename is valid
|
||||
|
||||
let nameCheck = null
|
||||
if (nFilename) {
|
||||
let originFileObj = path.parse(originFile.filename)
|
||||
nameCheck = lcdata.validateUploadsFilename(nFilename + originFileObj.ext, folder.name)
|
||||
nameCheck = wiki.disk.validateUploadsFilename(nFilename + originFileObj.ext, folder.name)
|
||||
} else {
|
||||
nameCheck = Promise.resolve(originFile.filename)
|
||||
}
|
||||
@@ -245,12 +245,12 @@ module.exports = {
|
||||
// -> Check for invalid operations
|
||||
|
||||
if (sourceFilePath === destFilePath) {
|
||||
return Promise.reject(new Error(lang.t('errors:invalidoperation')))
|
||||
return Promise.reject(new Error(wiki.lang.t('errors:invalidoperation')))
|
||||
}
|
||||
|
||||
// -> Delete DB entry
|
||||
// -> Delete wiki.DB entry
|
||||
|
||||
preMoveOps.push(db.UplFile.findByIdAndRemove(uid))
|
||||
preMoveOps.push(wiki.db.UplFile.finwiki.dByIdAndRemove(uid))
|
||||
|
||||
// -> Move thumbnail ahead to avoid re-generation
|
||||
|
||||
@@ -273,7 +273,7 @@ module.exports = {
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return Promise.reject(new Error(lang.t('errors:invaliddestfolder')))
|
||||
return Promise.reject(new Error(wiki.lang.t('errors:invaliddestfolder')))
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user