From d76f6182b2d175339cff5f2071ae94615190bcf1 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 22 Jul 2017 23:56:46 -0400 Subject: [PATCH 01/33] refactor: migrate to PostgreSQL + Sequelize --- package.json | 11 +- server/agent.js | 16 +- server/app/data.yml | 9 + server/controllers/auth.js | 18 +- server/controllers/uploads.js | 26 +- server/index.js | 128 +++-- server/libs/db.js | 63 --- server/models/_relations.js | 10 + server/models/bruteforce.js | 20 - server/models/document.js | 56 ++ server/models/entry.js | 42 -- server/models/file.js | 44 ++ server/models/folder.js | 24 + server/models/group.js | 18 + server/models/right.js | 38 ++ server/models/setting.js | 38 +- server/models/upl-file.js | 46 -- server/models/upl-folder.js | 21 - server/models/user.js | 186 +++---- server/{libs => modules}/auth.js | 116 ++-- server/{libs => modules}/config.js | 8 +- server/modules/db.js | 74 +++ server/{libs/local.js => modules/disk.js} | 60 +-- server/{libs => modules}/entries.js | 10 +- server/{libs => modules}/git.js | 64 +-- server/{libs => modules}/logger.js | 32 +- server/{libs => modules}/markdown.js | 14 +- server/modules/redis.js | 29 + server/{libs => modules}/rights.js | 6 +- .../{libs => modules}/search-index/index.js | 0 .../{libs => modules}/search-index/siUtil.js | 0 server/{libs => modules}/search.js | 20 +- server/{libs => modules}/system.js | 0 server/{libs => modules}/uploads-agent.js | 0 server/{libs => modules}/uploads.js | 42 +- .../winston-transports/bugsnag.js | 0 .../winston-transports/rollbar.js | 0 .../winston-transports/sentry.js | 0 wiki.js | 2 +- yarn.lock | 496 ++++++++++++------ 40 files changed, 1043 insertions(+), 744 deletions(-) delete mode 100644 server/libs/db.js create mode 100644 server/models/_relations.js delete mode 100644 server/models/bruteforce.js create mode 100644 server/models/document.js delete mode 100644 server/models/entry.js create mode 100644 server/models/file.js create mode 100644 server/models/folder.js create mode 100644 server/models/group.js create mode 100644 server/models/right.js delete mode 100644 server/models/upl-file.js delete mode 100644 server/models/upl-folder.js rename server/{libs => modules}/auth.js (58%) rename server/{libs => modules}/config.js (89%) create mode 100644 server/modules/db.js rename server/{libs/local.js => modules/disk.js} (59%) rename server/{libs => modules}/entries.js (97%) rename server/{libs => modules}/git.js (78%) rename server/{libs => modules}/logger.js (62%) rename server/{libs => modules}/markdown.js (96%) create mode 100644 server/modules/redis.js rename server/{libs => modules}/rights.js (94%) rename server/{libs => modules}/search-index/index.js (100%) rename server/{libs => modules}/search-index/siUtil.js (100%) rename server/{libs => modules}/search.js (88%) rename server/{libs => modules}/system.js (100%) rename server/{libs => modules}/uploads-agent.js (100%) rename server/{libs => modules}/uploads.js (81%) rename server/{libs => modules}/winston-transports/bugsnag.js (100%) rename server/{libs => modules}/winston-transports/rollbar.js (100%) rename server/{libs => modules}/winston-transports/sentry.js (100%) diff --git a/package.json b/package.json index a598f44e..d616a1e6 100644 --- a/package.json +++ b/package.json @@ -48,14 +48,14 @@ "chokidar": "~1.7.0", "compression": "~1.7.0", "connect-flash": "~0.1.1", - "connect-mongo": "~1.3.2", + "connect-redis": "~3.3.0", "cookie-parser": "~1.4.3", "cron": "~1.2.1", "diff2html": "~2.3.0", "execa": "~0.7.0", "express": "~4.15.3", "express-brute": "1.0.1", - "express-brute-mongoose": "~0.0.9", + "express-brute-redis": "~0.0.1", "express-session": "~1.15.3", "file-type": "~5.2.0", "filesize.js": "~1.0.2", @@ -67,6 +67,7 @@ "i18next-express-middleware": "~1.0.5", "i18next-node-fs-backend": "~1.0.0", "image-size": "~0.6.0", + "ioredis": "~3.1.1", "jimp": "~0.2.28", "js-yaml": "~3.9.0", "jsonwebtoken": "~7.4.1", @@ -88,8 +89,6 @@ "mime-types": "~2.1.15", "moment": "~2.18.1", "moment-timezone": "~0.5.13", - "mongodb": "~2.2.30", - "mongoose": "~4.11.1", "multer": "~1.3.0", "node-2fa": "~1.1.2", "node-graceful": "~0.2.3", @@ -104,6 +103,9 @@ "passport-slack": "0.0.7", "passport-windowslive": "~1.0.2", "passport.socketio": "~3.7.0", + "pg": "~7.0.2", + "pg-hstore": "~2.3.2", + "pg-promise": "~6.3.5", "pm2": "~2.6.1", "pug": "~2.0.0-rc.2", "read-chunk": "~2.0.0", @@ -112,6 +114,7 @@ "search-index-adder": "~0.3.9", "search-index-searcher": "~0.2.10", "semver": "~5.3.0", + "sequelize": "~4.4.2", "serve-favicon": "~2.4.3", "simplemde": "~1.11.2", "socket.io": "~2.0.2", diff --git a/server/agent.js b/server/agent.js index 38efd466..327496e8 100644 --- a/server/agent.js +++ b/server/agent.js @@ -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 diff --git a/server/app/data.yml b/server/app/data.yml index da16577b..cd8e839d 100644 --- a/server/app/data.yml +++ b/server/app/data.yml @@ -64,6 +64,15 @@ defaults: code: dark: true colorize: true +authProviders: + - local + - microsoft + - google + - facebook + - github + - slack + - ldap + - azure colors: - red - pink diff --git a/server/controllers/auth.js b/server/controllers/auth.js index b513470e..a29e2873 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -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') diff --git a/server/controllers/uploads.js b/server/controllers/uploads.js index a2a3f2f2..d7321c41 100644 --- a/server/controllers/uploads.js +++ b/server/controllers/uploads.js @@ -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) { diff --git a/server/index.js b/server/index.js index 07cc3df8..3f831aaa 100644 --- a/server/index.js +++ b/server/index.js @@ -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() }) }) diff --git a/server/libs/db.js b/server/libs/db.js deleted file mode 100644 index 733d28a2..00000000 --- a/server/libs/db.js +++ /dev/null @@ -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 - } - -} diff --git a/server/models/_relations.js b/server/models/_relations.js new file mode 100644 index 00000000..1f2f373f --- /dev/null +++ b/server/models/_relations.js @@ -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) +} diff --git a/server/models/bruteforce.js b/server/models/bruteforce.js deleted file mode 100644 index 76981fd7..00000000 --- a/server/models/bruteforce.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -const Mongoose = require('mongoose') - -/** - * BruteForce schema - * - * @type {} - */ -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) diff --git a/server/models/document.js b/server/models/document.js new file mode 100644 index 00000000..e742d492 --- /dev/null +++ b/server/models/document.js @@ -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 +} diff --git a/server/models/entry.js b/server/models/entry.js deleted file mode 100644 index 746d6d28..00000000 --- a/server/models/entry.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict' - -const Mongoose = require('mongoose') - -/** - * Entry schema - * - * @type {} - */ -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) diff --git a/server/models/file.js b/server/models/file.js new file mode 100644 index 00000000..9dea525b --- /dev/null +++ b/server/models/file.js @@ -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 +} diff --git a/server/models/folder.js b/server/models/folder.js new file mode 100644 index 00000000..ea873100 --- /dev/null +++ b/server/models/folder.js @@ -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 +} diff --git a/server/models/group.js b/server/models/group.js new file mode 100644 index 00000000..436d845b --- /dev/null +++ b/server/models/group.js @@ -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 +} diff --git a/server/models/right.js b/server/models/right.js new file mode 100644 index 00000000..22306370 --- /dev/null +++ b/server/models/right.js @@ -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 +} diff --git a/server/models/setting.js b/server/models/setting.js index 73686af2..28cef993 100644 --- a/server/models/setting.js +++ b/server/models/setting.js @@ -1,22 +1,28 @@ 'use strict' -const Mongoose = require('mongoose') - /** * Settings schema - * - * @type {} */ -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 +} diff --git a/server/models/upl-file.js b/server/models/upl-file.js deleted file mode 100644 index a48602bb..00000000 --- a/server/models/upl-file.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict' - -const Mongoose = require('mongoose') - -/** - * Upload File schema - * - * @type {} - */ -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) diff --git a/server/models/upl-folder.js b/server/models/upl-folder.js deleted file mode 100644 index 80028b6f..00000000 --- a/server/models/upl-folder.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -const Mongoose = require('mongoose') - -/** - * Upload Folder schema - * - * @type {} - */ -var uplFolderSchema = Mongoose.Schema({ - - _id: String, - - name: { - type: String, - index: true - } - -}, { timestamps: {} }) - -module.exports = Mongoose.model('UplFolder', uplFolderSchema) diff --git a/server/models/user.js b/server/models/user.js index be3ab360..1a9bc05e 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -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 {} */ -var userSchema = Mongoose.Schema({ - - 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: {} }) +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'] + } + ] + }) -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) + 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 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 - }] + profile.provider = _.lowerCase(profile.provider) + primaryEmail = _.toLower(primaryEmail) + + 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 db.User.create(nUsr) - } - return user || Promise.reject(new Error(lang.t('auth:errors:notyetauthorized'))) - }) -} + return user || Promise.reject(new Error(wiki.lang.t('auth:errors:notyetauthorized'))) + }) + } -userSchema.statics.hashPassword = (rawPwd) => { - return bcrypt.hash(rawPwd) -} + userSchema.hashPassword = (rawPwd) => { + return bcrypt.hash(rawPwd) + } -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 userSchema } - -module.exports = Mongoose.model('User', userSchema) diff --git a/server/libs/auth.js b/server/modules/auth.js similarity index 58% rename from server/libs/auth.js rename to server/modules/auth.js index 34271ccc..2b0a408d 100644 --- a/server/libs/auth.js +++ b/server/modules/auth.js @@ -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 } }) diff --git a/server/libs/config.js b/server/modules/config.js similarity index 89% rename from server/libs/config.js rename to server/modules/config.js index 92eac339..4c120338 100644 --- a/server/libs/config.js +++ b/server/modules/config.js @@ -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 = {} diff --git a/server/modules/db.js b/server/modules/db.js new file mode 100644 index 00000000..42e83eb3 --- /dev/null +++ b/server/modules/db.js @@ -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 + } + +} diff --git a/server/libs/local.js b/server/modules/disk.js similarity index 59% rename from server/libs/local.js rename to server/modules/disk.js index 3053e63b..9e919229 100644 --- a/server/libs/local.js +++ b/server/modules/disk.js @@ -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 diff --git a/server/libs/entries.js b/server/modules/entries.js similarity index 97% rename from server/libs/entries.js rename to server/modules/entries.js index a5e7b830..802d0d6d 100644 --- a/server/libs/entries.js +++ b/server/modules/entries.js @@ -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 }, diff --git a/server/libs/git.js b/server/modules/git.js similarity index 78% rename from server/libs/git.js rename to server/modules/git.js index 2f86fbb2..b0155ce9 100644 --- a/server/libs/git.js +++ b/server/modules/git.js @@ -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) diff --git a/server/libs/logger.js b/server/modules/logger.js similarity index 62% rename from server/libs/logger.js rename to server/modules/logger.js index 4a6f7884..d45a3ec4 100644 --- a/server/libs/logger.js +++ b/server/modules/logger.js @@ -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 }) } diff --git a/server/libs/markdown.js b/server/modules/markdown.js similarity index 96% rename from server/libs/markdown.js rename to server/modules/markdown.js index 14b0c887..c88266d7 100644 --- a/server/libs/markdown.js +++ b/server/modules/markdown.js @@ -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 '
' + hljs.highlight(lang, str, true).value + '
' } 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(', ')) } }) }) diff --git a/server/modules/redis.js b/server/modules/redis.js new file mode 100644 index 00000000..284c93d3 --- /dev/null +++ b/server/modules/redis.js @@ -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) + } + } + +} diff --git a/server/libs/rights.js b/server/modules/rights.js similarity index 94% rename from server/libs/rights.js rename to server/modules/rights.js index ce82882b..d06de758 100644 --- a/server/libs/rights.js +++ b/server/modules/rights.js @@ -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 } diff --git a/server/libs/search-index/index.js b/server/modules/search-index/index.js similarity index 100% rename from server/libs/search-index/index.js rename to server/modules/search-index/index.js diff --git a/server/libs/search-index/siUtil.js b/server/modules/search-index/siUtil.js similarity index 100% rename from server/libs/search-index/siUtil.js rename to server/modules/search-index/siUtil.js diff --git a/server/libs/search.js b/server/modules/search.js similarity index 88% rename from server/libs/search.js rename to server/modules/search.js index 7c446b17..d2978aa2 100644 --- a/server/libs/search.js +++ b/server/modules/search.js @@ -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) } }) } diff --git a/server/libs/system.js b/server/modules/system.js similarity index 100% rename from server/libs/system.js rename to server/modules/system.js diff --git a/server/libs/uploads-agent.js b/server/modules/uploads-agent.js similarity index 100% rename from server/libs/uploads-agent.js rename to server/modules/uploads-agent.js diff --git a/server/libs/uploads.js b/server/modules/uploads.js similarity index 81% rename from server/libs/uploads.js rename to server/modules/uploads.js index 2bee6322..f56ecab3 100644 --- a/server/libs/uploads.js +++ b/server/modules/uploads.js @@ -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} 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} 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'))) } }) } diff --git a/server/libs/winston-transports/bugsnag.js b/server/modules/winston-transports/bugsnag.js similarity index 100% rename from server/libs/winston-transports/bugsnag.js rename to server/modules/winston-transports/bugsnag.js diff --git a/server/libs/winston-transports/rollbar.js b/server/modules/winston-transports/rollbar.js similarity index 100% rename from server/libs/winston-transports/rollbar.js rename to server/modules/winston-transports/rollbar.js diff --git a/server/libs/winston-transports/sentry.js b/server/modules/winston-transports/sentry.js similarity index 100% rename from server/libs/winston-transports/sentry.js rename to server/modules/winston-transports/sentry.js diff --git a/wiki.js b/wiki.js index fcfb1358..faa38b0d 100644 --- a/wiki.js +++ b/wiki.js @@ -3,7 +3,7 @@ // =========================================== // Wiki.js -// 1.0.0 +// 1.0.1 // Licensed under AGPLv3 // =========================================== diff --git a/yarn.lock b/yarn.lock index 60ff1355..3094beea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -72,6 +72,10 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" +"@types/geojson@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.2.tgz#b02d10ab028e2928ac592a051aaa4981a1941d03" + "@types/ldapjs@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/ldapjs/-/ldapjs-1.0.0.tgz#d940cb412140caec14edaa9c76d5b92799dab495" @@ -86,7 +90,7 @@ version "8.0.14" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.14.tgz#4a19dc6bb61d16c01cbadc7b30ac23518fff176b" -"@types/node@^6.0.46": +"@types/node@^6.0.46", "@types/node@^6.0.48": version "6.0.84" resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.84.tgz#193ffe5a9f42864d425ffd9739d95b753c6a1eab" @@ -288,6 +292,10 @@ anymatch@^1.3.0: arrify "^1.0.0" micromatch "^2.1.5" +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + app-root-path@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-1.4.0.tgz#6335d865c9640d0fad99004e5a79232238e92dfa" @@ -412,12 +420,6 @@ async@1.5, async@^1.4.0, async@^1.5: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" - dependencies: - lodash "^4.14.0" - async@^2.1.4, async@^2.3.0, async@^2.5: version "2.5.0" resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d" @@ -986,6 +988,10 @@ bindings@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" +bisection@: + version "0.0.3" + resolved "https://registry.yarnpkg.com/bisection/-/bisection-0.0.3.tgz#9891d506d86ec7d50910c5157bb592dbb03f33db" + bl@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" @@ -1006,11 +1012,7 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@2.10.2: - version "2.10.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.10.2.tgz#024a5517295308857f14f91f1106fc3b555f446b" - -bluebird@^3.0, bluebird@^3.1.1, bluebird@^3.4.1, bluebird@~3.5.0: +bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" @@ -1082,10 +1084,6 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" -bson@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.4.tgz#93c10d39eaa5b58415cbc4052f3e53e562b0b72c" - buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -1094,9 +1092,9 @@ buffer-equal@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" -buffer-shims@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" +buffer-writer@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" @@ -1323,6 +1321,17 @@ closure-compiler@0.2.12: dependencies: google-closure-compiler "20150901.x" +cls-bluebird@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cls-bluebird/-/cls-bluebird-2.0.1.tgz#c259a480ae02c0e506134307bb13db30446ee2e7" + dependencies: + is-bluebird "^1.0.2" + shimmer "^1.1.0" + +cluster-key-slot@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz#7654556085a65330932a2e8b5976f8e2d0b3e414" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1453,12 +1462,12 @@ connect-flash@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/connect-flash/-/connect-flash-0.1.1.tgz#d8630f26d95a7f851f9956b1e8cc6732f3b6aa30" -connect-mongo@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/connect-mongo/-/connect-mongo-1.3.2.tgz#7cbf58dfff26760e5e00e017d0a85b4bc90b9d37" +connect-redis@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/connect-redis/-/connect-redis-3.3.0.tgz#c9510c1a567ff710eb2510e6a7509fa92b2232df" dependencies: - bluebird "^3.0" - mongodb ">= 1.2.0 <3.0.0" + debug "^2.2.0" + redis "^2.1.0" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" @@ -1563,6 +1572,13 @@ cron@1.2.1, cron@~1.2.1: dependencies: moment-timezone "^0.5.x" +cross-env@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-3.2.4.tgz#9e0585f277864ed421ce756f81a980ff0d698aba" + dependencies: + cross-spawn "^5.1.0" + is-windows "^1.0.0" + cross-spawn@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" @@ -1638,7 +1654,7 @@ de-indent@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" -debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6: +debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.3.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: @@ -1716,7 +1732,11 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -depd@1.1.0, depd@~1.1.0: +denque@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.1.1.tgz#10229c2b88eec1bd15ff82c5fde356e7beb6db9e" + +depd@1.1.0, depd@^1.1.0, depd@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" @@ -1814,6 +1834,14 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +dottie@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.0.tgz#da191981c8b8d713ca0115d5898cf397c2f0ddd0" + +double-ended-queue@^2.1.0-0: + version "2.1.0-0" + resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" + dtrace-provider@^0.7.0: version "0.7.1" resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.7.1.tgz#c06b308f2f10d5d5838aec9c571e5d588dc71d04" @@ -1949,6 +1977,12 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" +env-cmd@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/env-cmd/-/env-cmd-5.1.0.tgz#0236db393c3f033005204fcd0a92ee40723a9c9e" + dependencies: + cross-spawn "^5.0.1" + errno@^0.1.4, errno@~0.1.1: version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" @@ -1961,10 +1995,6 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -es6-promise@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4" - es6-promise@^3.0.2: version "3.3.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" @@ -2208,13 +2238,13 @@ expand-template@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a" -express-brute-mongoose@~0.0.9: - version "0.0.9" - resolved "https://registry.yarnpkg.com/express-brute-mongoose/-/express-brute-mongoose-0.0.9.tgz#7f8001c9548f78b705e6810be06f4c1e85745bd2" +express-brute-redis@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/express-brute-redis/-/express-brute-redis-0.0.1.tgz#0f4c833a5c3c2505c0c5c9ba55108e224a247ef8" dependencies: - express-brute "~0.5.0" - moment "^2.18.1" - mongoose "*" + express-brute "~0.4.2" + redis "~0.10.0" + underscore "~1.5.1" express-brute@1.0.1: version "1.0.1" @@ -2223,10 +2253,11 @@ express-brute@1.0.1: long-timeout "~0.1.1" underscore "~1.8.3" -express-brute@~0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/express-brute/-/express-brute-0.5.3.tgz#0c8aabafe09dd722666587916f471b976f0c2a48" +express-brute@~0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/express-brute/-/express-brute-0.4.2.tgz#3bc34fb01252b8f47e737bf72dd01ff4df1d9c07" dependencies: + memcached "~0.2.4" underscore "~1.5.1" express-session@~1.15.3: @@ -2486,6 +2517,10 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" +flexbuffer@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/flexbuffer/-/flexbuffer-0.0.6.tgz#039fdf23f8823e440c38f3277e6fef1174215b30" + fliplog@^0.3.13: version "0.3.13" resolved "https://registry.yarnpkg.com/fliplog/-/fliplog-0.3.13.tgz#dd0d786e821822aae272e0ddc84012596a96154c" @@ -2653,6 +2688,14 @@ gaze@^1.0.0: dependencies: globule "^1.0.0" +generic-pool@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" + +generic-pool@^3.1.6: + version "3.1.7" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.1.7.tgz#dac22b2c7a7a04e41732f7d8d2d25a303c88f662" + get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" @@ -2894,6 +2937,13 @@ has@^1.0.1: dependencies: function-bind "^1.0.2" +hashring@0.0.x: + version "0.0.8" + resolved "https://registry.yarnpkg.com/hashring/-/hashring-0.0.8.tgz#203ab13c364119f10106526d2eaf7bd42b484c31" + dependencies: + bisection "" + simple-lru-cache "0.0.x" + hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" @@ -2929,10 +2979,6 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" -hooks-fixed@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hooks-fixed/-/hooks-fixed-2.0.0.tgz#a01d894d52ac7f6599bbb1f63dfc9c411df70cba" - hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" @@ -3053,6 +3099,10 @@ infinity-agent@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/infinity-agent/-/infinity-agent-2.0.3.tgz#45e0e2ff7a9eb030b27d62b74b3744b7a7ac4216" +inflection@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.10.0.tgz#5bffcb1197ad3e81050f8e17e21668087ee9eb2f" + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3127,6 +3177,19 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +ioredis@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.1.tgz#cc2f1d3232b8c95cc153046bce168f2baa1186e8" + dependencies: + bluebird "^3.3.4" + cluster-key-slot "^1.0.6" + debug "^2.2.0" + denque "^1.1.0" + flexbuffer "0.0.6" + lodash "^4.8.2" + redis-commands "^1.2.0" + redis-parser "^2.4.0" + ip-regex@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" @@ -3149,6 +3212,10 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-bluebird@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-bluebird/-/is-bluebird-1.0.2.tgz#096439060f4aa411abee19143a84d6a55346d6e2" + is-buffer@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" @@ -3307,6 +3374,10 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +is-windows@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" + is@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" @@ -3411,6 +3482,12 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +jackpot@>=0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/jackpot/-/jackpot-0.0.6.tgz#3cff064285cbf66f4eab2593c90bce816a821849" + dependencies: + retry "0.6.0" + jest-changed-files@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8" @@ -3862,10 +3939,6 @@ jws@^3.1.4: jwa "^1.1.4" safe-buffer "^5.0.1" -kareem@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.4.2.tgz#3b4af5dbfaf3ac1c08b8e5518fdd81ba90c2ab72" - keygrip@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.1.tgz#b02fa4816eef21a8c4b35ca9e52921ffc89a30e9" @@ -4182,7 +4255,7 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.4: +lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.2, lodash@~4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4238,6 +4311,10 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" +manakin@0.4: + version "0.4.7" + resolved "https://registry.yarnpkg.com/manakin/-/manakin-0.4.7.tgz#41ca449b55bea9c4c4fecec393b9c4d63818fc3f" + map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -4325,6 +4402,13 @@ mem@^1.1.0: dependencies: mimic-fn "^1.0.0" +memcached@~0.2.4: + version "0.2.8" + resolved "https://registry.yarnpkg.com/memcached/-/memcached-0.2.8.tgz#ffbf9498cbc30779625b77e77770bd50dc525212" + dependencies: + hashring "0.0.x" + jackpot ">=0.0.6" + memdown@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.2.4.tgz#cd9a34aaf074d53445a271108eb4b8dd4ec0f27f" @@ -4456,80 +4540,16 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -moment-timezone@^0.5.x, moment-timezone@~0.5.13: +moment-timezone@^0.5.4, moment-timezone@^0.5.x, moment-timezone@~0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.13.tgz#99ce5c7d827262eb0f1f702044177f60745d7b90" dependencies: moment ">= 2.9.0" -moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.16.1, moment@^2.18, moment@^2.18.1, moment@~2.18.1: +moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.16.1, moment@^2.18, moment@~2.18.1: version "2.18.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" -mongodb-core@2.1.11: - version "2.1.11" - resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.11.tgz#1c38776ceb174997a99c28860eed9028da9b3e1a" - dependencies: - bson "~1.0.4" - require_optional "~1.0.0" - -mongodb-core@2.1.14: - version "2.1.14" - resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.14.tgz#13cba2764226b5be3d18992af0c963ce5ea0f0fd" - dependencies: - bson "~1.0.4" - require_optional "~1.0.0" - -mongodb@2.2.27: - version "2.2.27" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.27.tgz#34122034db66d983bcf6ab5adb26a24a70fef6e6" - dependencies: - es6-promise "3.2.1" - mongodb-core "2.1.11" - readable-stream "2.2.7" - -"mongodb@>= 1.2.0 <3.0.0", mongodb@~2.2.30: - version "2.2.30" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.30.tgz#8ccd801f676c8172040c2f2b47e9602a0d5634ab" - dependencies: - es6-promise "3.2.1" - mongodb-core "2.1.14" - readable-stream "2.2.7" - -mongoose@*, mongoose@~4.11.1: - version "4.11.3" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.11.3.tgz#f93d427b282c2e798b0fe1532fb41a7dde6e98d3" - dependencies: - async "2.1.4" - bson "~1.0.4" - hooks-fixed "2.0.0" - kareem "1.4.2" - mongodb "2.2.27" - mpath "0.3.0" - mpromise "0.5.5" - mquery "2.3.1" - ms "2.0.0" - muri "1.2.2" - regexp-clone "0.0.1" - sliced "1.0.1" - -mpath@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.3.0.tgz#7a58f789e9b5fd3c94520634157960f26bd5ef44" - -mpromise@0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mpromise/-/mpromise-0.5.5.tgz#f5b24259d763acc2257b0a0c8c6d866fd51732e6" - -mquery@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/mquery/-/mquery-2.3.1.tgz#9ab36749714800ff0bb53a681ce4bc4d5f07c87b" - dependencies: - bluebird "2.10.2" - debug "2.6.8" - regexp-clone "0.0.1" - sliced "0.0.5" - ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" @@ -4555,10 +4575,6 @@ multer@~1.3.0: type-is "^1.6.4" xtend "^4.0.0" -muri@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/muri/-/muri-1.2.2.tgz#63198132650db08a04cc79ccd00dd389afd2631c" - mustache@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0" @@ -4811,6 +4827,10 @@ oauth@0.9.x: version "0.9.15" resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" @@ -4979,6 +4999,10 @@ package-json@^1.0.0: got "^3.2.0" registry-url "^3.0.0" +packet-reader@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" + parse-bmfont-ascii@^1.0.3: version "1.0.6" resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285" @@ -5214,6 +5238,80 @@ performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + +pg-hstore@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/pg-hstore/-/pg-hstore-2.3.2.tgz#f7ef053e7b9b892ae986af2f7cbe86432dfcf24f" + dependencies: + underscore "^1.7.0" + +pg-minify@0.4: + version "0.4.2" + resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.4.2.tgz#c75b4b5878960fb09c3b9a4d4eb1036aea7ea0e3" + +pg-pool@1.*: + version "1.8.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.8.0.tgz#f7ec73824c37a03f076f51bfdf70e340147c4f37" + dependencies: + generic-pool "2.4.3" + object-assign "4.1.0" + +pg-pool@2.*: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.1.tgz#8b12541df271b57f7020c50a3f5566471f82c77e" + +pg-promise@~6.3.5: + version "6.3.5" + resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.3.5.tgz#61db54e4cd269d6c7c789ee8989ae5b0aa778caa" + dependencies: + manakin "0.4" + pg "^6.4.0" + pg-minify "0.4" + spex "1.2" + +pg-types@1.*: + version "1.12.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" + dependencies: + ap "~0.2.0" + postgres-array "~1.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.0" + postgres-interval "^1.1.0" + +pg@^6.4.0: + version "6.4.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.1.tgz#3eabd8ca056814437c769f17ff7a0c36ac7023c5" + dependencies: + buffer-writer "1.0.1" + packet-reader "0.3.1" + pg-connection-string "0.1.3" + pg-pool "1.*" + pg-types "1.*" + pgpass "1.*" + semver "4.3.2" + +pg@~7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.0.2.tgz#b9c2fe8168e7edfe9343aebe6fc48591e766ada7" + dependencies: + buffer-writer "1.0.1" + packet-reader "0.3.1" + pg-connection-string "0.1.3" + pg-pool "2.*" + pg-types "1.*" + pgpass "1.x" + semver "4.3.2" + +pgpass@1.*, pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + dependencies: + split "^1.0.0" + pidusage@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/pidusage/-/pidusage-1.1.5.tgz#b8c8d32bdfaf36212ca9e741028876ea33217e66" @@ -5335,6 +5433,24 @@ postcss@^6.0.1: source-map "^0.5.6" supports-color "^4.2.0" +postgres-array@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + +postgres-date@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" + +postgres-interval@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.1.tgz#acdb0f897b4b1c6e496d9d4e0a853e1c428f06f0" + dependencies: + xtend "^4.0.0" + prebuild-install@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.2.0.tgz#55934756a32bac8747390ca44ff663cee8b99b69" @@ -5704,18 +5820,6 @@ readable-stream@1.1.x, readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@2.2.7: - version "2.2.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1" - dependencies: - buffer-shims "~1.0.0" - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~1.0.0" - util-deprecate "~1.0.1" - readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" @@ -5757,6 +5861,26 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" +redis-commands@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.1.tgz#81d826f45fa9c8b2011f4cd7a0fe597d241d442b" + +redis-parser@^2.4.0, redis-parser@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b" + +redis@^2.1.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/redis/-/redis-2.7.1.tgz#7d56f7875b98b20410b71539f1d878ed58ebf46a" + dependencies: + double-ended-queue "^2.1.0-0" + redis-commands "^1.2.0" + redis-parser "^2.5.0" + +redis@~0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/redis/-/redis-0.10.3.tgz#8927fe2110ee39617bcf3fd37b89d8e123911bb6" + regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" @@ -5780,10 +5904,6 @@ regex-cache@^0.4.2: is-equal-shallow "^0.1.3" is-primitive "^2.0.0" -regexp-clone@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589" - regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -5878,21 +5998,10 @@ require-uncached@^1.0.3: caller-path "^0.1.0" resolve-from "^1.0.0" -require_optional@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" - dependencies: - resolve-from "^2.0.0" - semver "^5.1.0" - resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" -resolve-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -5910,6 +6019,18 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +retry-as-promised@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-2.2.0.tgz#b0463d7fd3cf5b2fed64500ab6e8b8a49c5b8e6c" + dependencies: + bluebird "^3.4.6" + cross-env "^3.1.2" + debug "^2.2.0" + +retry@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.6.0.tgz#1c010713279a6fd1e8def28af0c3ff1871caa537" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -6036,6 +6157,10 @@ semver-diff@^2.0.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + semver@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19" @@ -6092,6 +6217,29 @@ send@0.15.3: range-parser "~1.2.0" statuses "~1.3.1" +sequelize@~4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.4.2.tgz#95292e0a752e2586ec92a0e72362b76e4fcb8eae" + dependencies: + bluebird "^3.4.6" + cls-bluebird "^2.0.1" + debug "^2.3.0" + depd "^1.1.0" + dottie "^2.0.0" + env-cmd "^5.0.0" + generic-pool "^3.1.6" + inflection "1.10.0" + lodash "^4.17.1" + moment "^2.13.0" + moment-timezone "^0.5.4" + retry-as-promised "^2.0.0" + semver "^5.0.1" + terraformer-wkt-parser "^1.1.2" + toposort-class "^1.0.1" + uuid "^3.0.0" + validator "^6.3.0" + wkx "^0.4.1" + serve-favicon@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.4.3.tgz#5986b17b0502642b641c21f818b1acce32025d23" @@ -6177,6 +6325,10 @@ simple-get@^1.4.2: unzip-response "^1.0.0" xtend "^4.0.0" +simple-lru-cache@0.0.x: + version "0.0.2" + resolved "https://registry.yarnpkg.com/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz#d59cc3a193c1a5d0320f84ee732f6e4713e511dd" + simplemde@~1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/simplemde/-/simplemde-1.11.2.tgz#a23a35d978d2c40ef07dec008c92f070d8e080e3" @@ -6193,14 +6345,6 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" -sliced@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/sliced/-/sliced-0.0.5.tgz#5edc044ca4eb6f7816d50ba2fc63e25d8fe4707f" - -sliced@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" - slide@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -6291,12 +6435,22 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" +spex@1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/spex/-/spex-1.2.0.tgz#6264b3b8acbc444477f06dbb66d425c0ee1074c0" + split@0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" dependencies: through "2" +split@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae" + dependencies: + through "2" + sprintf-js@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" @@ -6408,7 +6562,7 @@ string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -string_decoder@~1.0.0, string_decoder@~1.0.3: +string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" dependencies: @@ -6543,6 +6697,18 @@ term-vector@^0.1.2: dependencies: lodash.isequal "^4.1.3" +terraformer-wkt-parser@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz#336a0c8fc82094a5aff83288f69aedecd369bf0c" + dependencies: + terraformer "~1.0.5" + +terraformer@~1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/terraformer/-/terraformer-1.0.8.tgz#51e0ad89746fcf2161dc6f65aa70e42377c8b593" + dependencies: + "@types/geojson" "^1.0.0" + test-exclude@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" @@ -6620,6 +6786,10 @@ topo@1.x.x: dependencies: hoek "2.x.x" +toposort-class@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" + touch@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de" @@ -6760,14 +6930,14 @@ undefsafe@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-0.0.3.tgz#ecca3a03e56b9af17385baac812ac83b994a962f" +underscore@^1.7.0, underscore@~1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + underscore@~1.5.1: version "1.5.2" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.5.2.tgz#1335c5e4f5e6d33bbb4b006ba8c86a00f556de08" -underscore@~1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - universalify@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" @@ -6874,6 +7044,10 @@ validator@^5.5.0: version "5.7.0" resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c" +validator@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-6.3.0.tgz#47ce23ed8d4eaddfa9d4b8ef0071b6cf1078d7c8" + validator@~8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/validator/-/validator-8.0.0.tgz#00d6ec230ab5d3353ab1174162a96462b947bdbd" @@ -7072,6 +7246,12 @@ with@^5.0.0: acorn "^3.1.0" acorn-globals "^3.0.0" +wkx@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.4.1.tgz#2fc171b5e9cb55c6256fef4bde1f21be413befee" + dependencies: + "@types/node" "^6.0.48" + wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" From 60750eeed8d1744f76eec8ba24ff9be73c347928 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Mon, 24 Jul 2017 22:37:13 -0400 Subject: [PATCH 02/33] feat: GraphQL base implementation --- package.json | 2 + server/index.js | 4 ++ server/middlewares/security.js | 4 +- server/models/user.js | 2 +- server/modules/auth.js | 20 ++++------ server/modules/db.js | 3 +- server/modules/graphql.js | 67 ++++++++++++++++++++++++++++++++++ yarn.lock | 36 +++++++++++++++++- 8 files changed, 118 insertions(+), 20 deletions(-) create mode 100644 server/modules/graphql.js diff --git a/package.json b/package.json index d616a1e6..862d8fff 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "node": ">=6.11.1" }, "dependencies": { + "apollo-server-express": "~1.0.4", "auto-load": "~3.0.0", "axios": "~0.16.2", "bcryptjs-then": "~1.0.1", @@ -62,6 +63,7 @@ "follow-redirects": "~1.2.4", "fs-extra": "~4.0.0", "git-wrapper2-promise": "~0.2.9", + "graphql": "~0.10.5", "highlight.js": "~9.12.0", "i18next": "~8.4.3", "i18next-express-middleware": "~1.0.5", diff --git a/server/index.js b/server/index.js index 3f831aaa..d53f3fba 100644 --- a/server/index.js +++ b/server/index.js @@ -65,6 +65,8 @@ const session = require('express-session') const SessionRedisStore = require('connect-redis')(session) const graceful = require('node-graceful') const socketio = require('socket.io') +const graphqlApollo = require('apollo-server-express') +const graphqlSchema = require('./modules/graphql') var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares')) var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers')) @@ -167,6 +169,8 @@ app.use(mw.flash) app.use('/', ctrl.auth) +app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema })) +app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' })) app.use('/uploads', mw.auth, ctrl.uploads) app.use('/admin', mw.auth, ctrl.admin) app.use('/', mw.auth, ctrl.pages) diff --git a/server/middlewares/security.js b/server/middlewares/security.js index 4a04056c..4b63612c 100644 --- a/server/middlewares/security.js +++ b/server/middlewares/security.js @@ -1,7 +1,5 @@ 'use strict' -/* global app */ - /** * Security Middleware * @@ -12,7 +10,7 @@ */ module.exports = function (req, res, next) { // -> Disable X-Powered-By - app.disable('x-powered-by') + req.app.disable('x-powered-by') // -> Disable Frame Embedding res.set('X-Frame-Options', 'deny') diff --git a/server/models/user.js b/server/models/user.js index 1a9bc05e..4d740b39 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -99,7 +99,7 @@ module.exports = (sequelize, DataTypes) => { deny: false }] } - return db.User.create(nUsr) + return wiki.db.User.create(nUsr) } return user || Promise.reject(new Error(wiki.lang.t('auth:errors:notyetauthorized'))) }) diff --git a/server/modules/auth.js b/server/modules/auth.js index 2b0a408d..60bc49d8 100644 --- a/server/modules/auth.js +++ b/server/modules/auth.js @@ -214,20 +214,17 @@ module.exports = function (passport) { return wiki.db.User.create({ provider: 'local', - email: 'guest', + email: 'guest@example.com', name: 'Guest', password: '', - rights: [{ - role: 'read', - path: '/', - exact: false, - deny: !wiki.config.public - }] + role: 'guest' }).then(() => { wiki.logger.info('[AUTH] Guest account created successfully!') + return true }).catch((err) => { wiki.logger.error('[AUTH] An error occured while creating guest account:') wiki.logger.error(err) + return err }) } }).then(() => { @@ -241,17 +238,14 @@ module.exports = function (passport) { email: process.env.WIKI_ADMIN_EMAIL, name: 'Administrator', password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default) - rights: [{ - role: 'admin', - path: '/', - exact: false, - deny: false - }] + role: 'admin' }).then(() => { wiki.logger.info('[AUTH] Root admin account created successfully!') + return true }).catch((err) => { wiki.logger.error('[AUTH] An error occured while creating root admin account:') wiki.logger.error(err) + return err }) } else { return true } }) diff --git a/server/modules/db.js b/server/modules/db.js index 42e83eb3..a849031d 100644 --- a/server/modules/db.js +++ b/server/modules/db.js @@ -64,8 +64,7 @@ module.exports = { // Sync DB self.onReady = self.inst.sync({ - force: false, - logging: wiki.logger.verbose + force: false }) return self diff --git a/server/modules/graphql.js b/server/modules/graphql.js new file mode 100644 index 00000000..4de7a8c7 --- /dev/null +++ b/server/modules/graphql.js @@ -0,0 +1,67 @@ +'use strict' + +/* global wiki */ + +const gql = require('graphql') + +const User = new gql.GraphQLObjectType({ + name: 'User', + description: 'A User', + fields() { + return { + id: { + type: gql.GraphQLInt, + resolve(usr) { + return usr.id + } + }, + email: { + type: gql.GraphQLString, + resolve(usr) { + return usr.email + } + }, + provider: { + type: gql.GraphQLString, + resolve(usr) { + return usr.provider + } + }, + providerId: { + type: gql.GraphQLString, + resolve(usr) { + return usr.providerId + } + } + } + } +}) + +const Query = new gql.GraphQLObjectType({ + name: 'Query', + description: 'Root Query', + fields() { + return { + users: { + type: new gql.GraphQLList(User), + args: { + id: { + type: gql.GraphQLInt + }, + email: { + type: gql.GraphQLString + } + }, + resolve(root, args) { + return wiki.db.User.findAll({ where: args }) + } + } + } + } +}) + +const Schema = new gql.GraphQLSchema({ + query: Query +}) + +module.exports = Schema diff --git a/yarn.lock b/yarn.lock index 3094beea..0bac2239 100644 --- a/yarn.lock +++ b/yarn.lock @@ -65,7 +65,7 @@ dependencies: "@types/node" "*" -"@types/express@*": +"@types/express@*", "@types/express@^4.0.35": version "4.0.36" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.0.36.tgz#14eb47de7ecb10319f0a2fb1cf971aa8680758c2" dependencies: @@ -76,6 +76,10 @@ version "1.0.2" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.2.tgz#b02d10ab028e2928ac592a051aaa4981a1941d03" +"@types/graphql@^0.9.0", "@types/graphql@^0.9.1": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.4.tgz#cdeb6bcbef9b6c584374b81aa7f48ecf3da404fa" + "@types/ldapjs@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/ldapjs/-/ldapjs-1.0.0.tgz#d940cb412140caec14edaa9c76d5b92799dab495" @@ -296,6 +300,26 @@ ap@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" +apollo-server-core@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.0.2.tgz#6860a6b5680c42c8727153c524eefc84fb91e500" + optionalDependencies: + "@types/graphql" "^0.9.0" + +apollo-server-express@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.0.4.tgz#fad6045493d818b09ad4610faa389768386a68b6" + dependencies: + apollo-server-core "^1.0.2" + apollo-server-module-graphiql "^1.0.4" + optionalDependencies: + "@types/express" "^4.0.35" + "@types/graphql" "^0.9.1" + +apollo-server-module-graphiql@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.0.4.tgz#d6db21a8c60f052649124da5cde1d88dab702319" + app-root-path@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-1.4.0.tgz#6335d865c9640d0fad99004e5a79232238e92dfa" @@ -2868,6 +2892,12 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +graphql@~0.10.5: + version "0.10.5" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" + dependencies: + iterall "^1.1.0" + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -3482,6 +3512,10 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +iterall@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.1.tgz#f7f0af11e9a04ec6426260f5019d9fcca4d50214" + jackpot@>=0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/jackpot/-/jackpot-0.0.6.tgz#3cff064285cbf66f4eab2593c90bce816a821849" From 9c112ab53555839424bcbf2dae48b2ae2314b60e Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 29 Jul 2017 00:11:22 -0400 Subject: [PATCH 03/33] feat: cluster implementation --- config.sample.yml | 153 ++-------------- package.json | 1 + server/index.js | 254 ++------------------------ server/master.js | 232 +++++++++++++++++++++++ server/models/_relations.js | 7 +- server/models/comment.js | 18 ++ server/models/document.js | 5 + server/models/tag.js | 24 +++ server/modules/db.js | 3 +- server/modules/logger.js | 9 +- server/modules/search-index/index.js | 81 -------- server/modules/search-index/siUtil.js | 36 ---- server/modules/search.js | 6 +- server/{agent.js => worker.js} | 86 ++++----- yarn.lock | 63 ++++++- 15 files changed, 414 insertions(+), 564 deletions(-) create mode 100644 server/master.js create mode 100644 server/models/comment.js create mode 100644 server/models/tag.js delete mode 100644 server/modules/search-index/index.js delete mode 100644 server/modules/search-index/siUtil.js rename server/{agent.js => worker.js} (69%) diff --git a/config.sample.yml b/config.sample.yml index 7f10129f..d3359c9c 100644 --- a/config.sample.yml +++ b/config.sample.yml @@ -4,23 +4,9 @@ # Full explanation + examples in the documentation: # https://docs.requarks.io/wiki/install -# --------------------------------------------------------------------- -# Title of this site -# --------------------------------------------------------------------- - -title: Wiki - -# --------------------------------------------------------------------- -# Full public path to the site, without the trailing slash -# --------------------------------------------------------------------- -# INCLUDE CLIENT PORT IF NOT 80/443! - -host: http://localhost - # --------------------------------------------------------------------- # Port the main server should listen to (80 by default) # --------------------------------------------------------------------- -# To use process.env.PORT, comment the line below: port: 80 @@ -33,136 +19,23 @@ paths: data: ./data # --------------------------------------------------------------------- -# Upload Limits -# --------------------------------------------------------------------- -# In megabytes (MB) - -uploads: - maxImageFileSize: 3 - maxOtherFileSize: 100 - -# --------------------------------------------------------------------- -# Site Language -# --------------------------------------------------------------------- -# Possible values: en, es, fr, ko, ru or zh - -lang: en - -# --------------------------------------------------------------------- -# Site Authentication -# --------------------------------------------------------------------- - -public: false - -auth: - defaultReadAccess: false - local: - enabled: true - google: - enabled: true - clientId: GOOGLE_CLIENT_ID - clientSecret: GOOGLE_CLIENT_SECRET - microsoft: - enabled: true - clientId: MS_APP_ID - clientSecret: MS_APP_SECRET - facebook: - enabled: false - clientId: FACEBOOK_APP_ID - clientSecret: FACEBOOK_APP_SECRET - github: - enabled: false - clientId: GITHUB_CLIENT_ID - clientSecret: GITHUB_CLIENT_SECRET - slack: - enabled: false - clientId: SLACK_CLIENT_ID - clientSecret: SLACK_CLIENT_SECRET - ldap: - enabled: false - url: ldap://serverhost:389 - bindDn: cn='root' - bindCredentials: BIND_PASSWORD - searchBase: o=users,o=example.com - searchFilter: (uid={{username}}) - tlsEnabled: false - tlsCertPath: C:\example\root_ca_cert.crt - azure: - enabled: false - clientID: APP_ID - clientSecret: APP_SECRET_KEY - resource: '00000002-0000-0000-c000-000000000000' - tenant: 'YOUR_TENANT.onmicrosoft.com' - -# --------------------------------------------------------------------- -# Secret key to use when encrypting sessions +# Database # --------------------------------------------------------------------- -# Use a long and unique random string (256-bit keys are perfect!) -sessionSecret: 1234567890abcdefghijklmnopqrstuvxyz +db: + host: localhost + port: 5432 + user: wikijs + pass: wikijsrocks + db: wiki # --------------------------------------------------------------------- -# Database Connection String +# Redis # --------------------------------------------------------------------- -# You can also use an ENV variable by using $ENV_VAR_NAME as the value -db: mongodb://localhost:27017/wiki - -# --------------------------------------------------------------------- -# Git Connection Info -# --------------------------------------------------------------------- - -git: - url: https://github.com/Organization/Repo - branch: master - auth: - - # Type: basic or ssh - type: ssh - - # Only for Basic authentication: - username: marty - password: MartyMcFly88 - - # Only for SSH authentication: - privateKey: /etc/wiki/keys/git.pem - - sslVerify: true - - # Default email to use as commit author - serverEmail: marty@example.com - - # Whether to use user email as author in commits - showUserEmail: true - -# --------------------------------------------------------------------- -# Features -# --------------------------------------------------------------------- -# You can enable / disable specific features below - -features: - linebreaks: true - mathjax: true - -# --------------------------------------------------------------------- -# External Logging -# --------------------------------------------------------------------- - -externalLogging: - bugsnag: false - loggly: false - papertrail: false - rollbar: false - sentry: false - -# --------------------------------------------------------------------- -# Color Theme -# --------------------------------------------------------------------- +redis: + host: localhost + port: 6379 + db: 0 + password: null -theme: - primary: indigo - alt: blue-grey - footer: blue-grey - code: - dark: true - colorize: true diff --git a/package.json b/package.json index 862d8fff..d20fd14e 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "bcryptjs-then": "~1.0.1", "bluebird": "~3.5.0", "body-parser": "~1.17.2", + "bull": "/home/nick3.0.0-rc.4", "bunyan": "~1.8.10", "cheerio": "~1.0.0-rc.2", "child-process-promise": "~2.2.1", diff --git a/server/index.js b/server/index.js index d53f3fba..aeb2f8a5 100644 --- a/server/index.js +++ b/server/index.js @@ -2,7 +2,6 @@ // =========================================== // Wiki.js -// 1.0.1 // Licensed under AGPLv3 // =========================================== @@ -28,251 +27,28 @@ wiki.data = appconf.data // Load Winston // ---------------------------------------- -wiki.logger = require('./modules/logger')(wiki.IS_DEBUG, 'SERVER') -wiki.logger.info('Wiki.js is initializing...') +wiki.logger = require('./modules/logger')() // ---------------------------------------- -// Load global modules +// Start Cluster // ---------------------------------------- -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() +const cluster = require('cluster') +const numCPUs = require('os').cpus().length -// ---------------------------------------- -// Load modules -// ---------------------------------------- - -const autoload = require('auto-load') -const bodyParser = require('body-parser') -const compression = require('compression') -const cookieParser = require('cookie-parser') -const express = require('express') -const favicon = require('serve-favicon') -const flash = require('connect-flash') -const fork = require('child_process').fork -const http = require('http') -const i18nBackend = require('i18next-node-fs-backend') -const passport = require('passport') -const passportSocketIo = require('passport.socketio') -const session = require('express-session') -const SessionRedisStore = require('connect-redis')(session) -const graceful = require('node-graceful') -const socketio = require('socket.io') -const graphqlApollo = require('apollo-server-express') -const graphqlSchema = require('./modules/graphql') - -var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares')) -var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers')) - -// ---------------------------------------- -// Define Express App -// ---------------------------------------- - -const app = express() -wiki.app = app -app.use(compression()) - -// ---------------------------------------- -// Security -// ---------------------------------------- - -app.use(mw.security) - -// ---------------------------------------- -// Public Assets -// ---------------------------------------- - -app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico'))) -app.use(express.static(path.join(wiki.ROOTPATH, 'assets'), { - index: false, - maxAge: '7d' -})) - -// ---------------------------------------- -// Passport Authentication -// ---------------------------------------- - -require('./modules/auth')(passport) -wiki.rights = require('./modules/rights') -wiki.rights.init() - -let sessionStore = new SessionRedisStore({ - client: wiki.redis -}) - -app.use(cookieParser()) -app.use(session({ - name: 'wikijs.sid', - store: sessionStore, - secret: wiki.config.sessionSecret, - resave: false, - saveUninitialized: false -})) -app.use(flash()) -app.use(passport.initialize()) -app.use(passport.session()) - -// ---------------------------------------- -// SEO -// ---------------------------------------- - -app.use(mw.seo) - -// ---------------------------------------- -// Localization Engine -// ---------------------------------------- - -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(wiki.SERVERPATH, 'views')) -app.set('view engine', 'pug') - -app.use(bodyParser.json({ limit: '1mb' })) -app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' })) - -// ---------------------------------------- -// View accessible data -// ---------------------------------------- - -app.locals._ = require('lodash') -app.locals.t = wiki.lang.t.bind(wiki.lang) -app.locals.moment = require('moment') -app.locals.moment.locale(wiki.config.lang) -app.locals.appconfig = wiki.config -app.use(mw.flash) - -// ---------------------------------------- -// Controllers -// ---------------------------------------- - -app.use('/', ctrl.auth) - -app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema })) -app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' })) -app.use('/uploads', mw.auth, ctrl.uploads) -app.use('/admin', mw.auth, ctrl.admin) -app.use('/', mw.auth, ctrl.pages) - -// ---------------------------------------- -// Error handling -// ---------------------------------------- - -app.use(function (req, res, next) { - var err = new Error('Not Found') - err.status = 404 - next(err) -}) - -app.use(function (err, req, res, next) { - res.status(err.status || 500) - res.render('error', { - message: err.message, - error: wiki.IS_DEBUG ? err : {} - }) -}) - -// ---------------------------------------- -// Start HTTP server -// ---------------------------------------- - -wiki.logger.info('Starting HTTP/WS server on port ' + wiki.config.port + '...') - -app.set('port', wiki.config.port) -var server = http.createServer(app) -var io = socketio(server) - -server.listen(wiki.config.port) -server.on('error', (error) => { - if (error.syscall !== 'listen') { - throw error - } - - // handle specific listen errors with friendly messages - switch (error.code) { - case 'EACCES': - wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!') - return process.exit(1) - case 'EADDRINUSE': - wiki.logger.error('Port ' + wiki.config.port + ' is already in use!') - return process.exit(1) - default: - throw error - } -}) +if (cluster.isMaster) { + wiki.logger.info('Wiki.js is initializing...') -server.on('listening', () => { - wiki.logger.info('HTTP/WS server started successfully! [RUNNING]') -}) - -// ---------------------------------------- -// WebSocket -// ---------------------------------------- + require('./master') -io.use(passportSocketIo.authorize({ - key: 'wikijs.sid', - store: sessionStore, - secret: wiki.config.sessionSecret, - cookieParser, - success: (data, accept) => { - accept() - }, - fail: (data, message, error, accept) => { - accept() + for (let i = 0; i < numCPUs; i++) { + cluster.fork() } -})) - -io.on('connection', ctrl.ws) - -// ---------------------------------------- -// Start child processes -// ---------------------------------------- -let bgAgent = fork(path.join(wiki.SERVERPATH, 'agent.js')) - -bgAgent.on('message', m => { - if (!m.action) { - return - } - - switch (m.action) { - case 'searchAdd': - wiki.search.add(m.content) - break - } -}) - -// ---------------------------------------- -// Graceful shutdown -// ---------------------------------------- - -graceful.on('exit', () => { - wiki.logger.info('- SHUTTING DOWN - Terminating Background Agent...') - bgAgent.kill() - wiki.logger.info('- SHUTTING DOWN - Performing git sync...') - return global.git.resync().then(() => { - wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.') - process.exit() + cluster.on('exit', (worker, code, signal) => { + wiki.logger.info(`Worker #${worker.id} died.`) }) -}) +} else { + wiki.logger.info(`Background Worker #${cluster.worker.id} is starting...`) + // require('./worker') +} diff --git a/server/master.js b/server/master.js new file mode 100644 index 00000000..75a609c8 --- /dev/null +++ b/server/master.js @@ -0,0 +1,232 @@ +'use strict' + +/* global wiki */ + +const path = require('path') + +// ---------------------------------------- +// Load global modules +// ---------------------------------------- + +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 +// ---------------------------------------- + +const autoload = require('auto-load') +const bodyParser = require('body-parser') +const compression = require('compression') +const cookieParser = require('cookie-parser') +const express = require('express') +const favicon = require('serve-favicon') +const flash = require('connect-flash') +const http = require('http') +const i18nBackend = require('i18next-node-fs-backend') +const passport = require('passport') +const passportSocketIo = require('passport.socketio') +const session = require('express-session') +const SessionRedisStore = require('connect-redis')(session) +const graceful = require('node-graceful') +const socketio = require('socket.io') +const graphqlApollo = require('apollo-server-express') +const graphqlSchema = require('./modules/graphql') + +var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares')) +var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers')) + +// ---------------------------------------- +// Define Express App +// ---------------------------------------- + +const app = express() +wiki.app = app +app.use(compression()) + +// ---------------------------------------- +// Security +// ---------------------------------------- + +app.use(mw.security) + +// ---------------------------------------- +// Public Assets +// ---------------------------------------- + +app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico'))) +app.use(express.static(path.join(wiki.ROOTPATH, 'assets'), { + index: false, + maxAge: '7d' +})) + +// ---------------------------------------- +// Passport Authentication +// ---------------------------------------- + +require('./modules/auth')(passport) +wiki.rights = require('./modules/rights') +wiki.rights.init() + +let sessionStore = new SessionRedisStore({ + client: wiki.redis +}) + +app.use(cookieParser()) +app.use(session({ + name: 'wikijs.sid', + store: sessionStore, + secret: wiki.config.sessionSecret, + resave: false, + saveUninitialized: false +})) +app.use(flash()) +app.use(passport.initialize()) +app.use(passport.session()) + +// ---------------------------------------- +// SEO +// ---------------------------------------- + +app.use(mw.seo) + +// ---------------------------------------- +// Localization Engine +// ---------------------------------------- + +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(wiki.SERVERPATH, 'views')) +app.set('view engine', 'pug') + +app.use(bodyParser.json({ limit: '1mb' })) +app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' })) + +// ---------------------------------------- +// View accessible data +// ---------------------------------------- + +app.locals._ = require('lodash') +app.locals.t = wiki.lang.t.bind(wiki.lang) +app.locals.moment = require('moment') +app.locals.moment.locale(wiki.config.lang) +app.locals.appconfig = wiki.config +app.use(mw.flash) + +// ---------------------------------------- +// Controllers +// ---------------------------------------- + +app.use('/', ctrl.auth) + +app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema })) +app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' })) +app.use('/uploads', mw.auth, ctrl.uploads) +app.use('/admin', mw.auth, ctrl.admin) +app.use('/', mw.auth, ctrl.pages) + +// ---------------------------------------- +// Error handling +// ---------------------------------------- + +app.use(function (req, res, next) { + var err = new Error('Not Found') + err.status = 404 + next(err) +}) + +app.use(function (err, req, res, next) { + res.status(err.status || 500) + res.render('error', { + message: err.message, + error: wiki.IS_DEBUG ? err : {} + }) +}) + +// ---------------------------------------- +// Start HTTP server +// ---------------------------------------- + +wiki.logger.info('Starting HTTP/WS server on port ' + wiki.config.port + '...') + +app.set('port', wiki.config.port) +var server = http.createServer(app) +var io = socketio(server) + +server.listen(wiki.config.port) +server.on('error', (error) => { + if (error.syscall !== 'listen') { + throw error + } + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!') + return process.exit(1) + case 'EADDRINUSE': + wiki.logger.error('Port ' + wiki.config.port + ' is already in use!') + return process.exit(1) + default: + throw error + } +}) + +server.on('listening', () => { + wiki.logger.info('HTTP/WS server started successfully! [RUNNING]') +}) + +// ---------------------------------------- +// WebSocket +// ---------------------------------------- + +io.use(passportSocketIo.authorize({ + key: 'wikijs.sid', + store: sessionStore, + secret: wiki.config.sessionSecret, + cookieParser, + success: (data, accept) => { + accept() + }, + fail: (data, message, error, accept) => { + accept() + } +})) + +io.on('connection', ctrl.ws) + +// ---------------------------------------- +// Graceful shutdown +// ---------------------------------------- + +graceful.on('exit', () => { + // wiki.logger.info('- SHUTTING DOWN - Terminating Background Agent...') + // bgAgent.kill() + wiki.logger.info('- SHUTTING DOWN - Performing git sync...') + return global.git.resync().then(() => { + wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.') + process.exit() + }) +}) diff --git a/server/models/_relations.js b/server/models/_relations.js index 1f2f373f..7a851396 100644 --- a/server/models/_relations.js +++ b/server/models/_relations.js @@ -4,7 +4,10 @@ * Associate DB Model relations */ module.exports = db => { - db.User.belongsToMany(db.Group, { through: 'UserGroups' }) - db.Group.hasMany(db.Right, { as: 'GroupRights' }) + db.User.belongsToMany(db.Group, { through: 'userGroups' }) + db.Group.hasMany(db.Right, { as: 'groupRights' }) + db.Document.hasMany(db.Tag, { as: 'documentTags' }) db.File.belongsTo(db.Folder) + db.Comment.belongsTo(db.Document) + db.Comment.belongsTo(db.User, { as: 'author' }) } diff --git a/server/models/comment.js b/server/models/comment.js new file mode 100644 index 00000000..ecdb5806 --- /dev/null +++ b/server/models/comment.js @@ -0,0 +1,18 @@ +'use strict' + +/** + * Comment schema + */ +module.exports = (sequelize, DataTypes) => { + let commentSchema = sequelize.define('comment', { + content: { + type: DataTypes.STRING, + allowNull: false + } + }, { + timestamps: true, + version: true + }) + + return commentSchema +} diff --git a/server/models/document.js b/server/models/document.js index e742d492..76c9e0c7 100644 --- a/server/models/document.js +++ b/server/models/document.js @@ -40,6 +40,11 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false + }, + searchContent: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: '' } }, { timestamps: true, diff --git a/server/models/tag.js b/server/models/tag.js new file mode 100644 index 00000000..ccd9363a --- /dev/null +++ b/server/models/tag.js @@ -0,0 +1,24 @@ +'use strict' + +/** + * Tags schema + */ +module.exports = (sequelize, DataTypes) => { + let tagSchema = sequelize.define('tag', { + key: { + type: DataTypes.STRING, + allowNull: false + } + }, { + timestamps: true, + version: true, + indexes: [ + { + unique: true, + fields: ['key'] + } + ] + }) + + return tagSchema +} diff --git a/server/modules/db.js b/server/modules/db.js index a849031d..89ca5ce1 100644 --- a/server/modules/db.js +++ b/server/modules/db.js @@ -64,7 +64,8 @@ module.exports = { // Sync DB self.onReady = self.inst.sync({ - force: false + force: false, + logging: false }) return self diff --git a/server/modules/logger.js b/server/modules/logger.js index d45a3ec4..08ecc175 100644 --- a/server/modules/logger.js +++ b/server/modules/logger.js @@ -2,12 +2,10 @@ /* global wiki */ -module.exports = (processName) => { - let winston = require('winston') +const cluster = require('cluster') - if (typeof processName === 'undefined') { - processName = 'SERVER' - } +module.exports = () => { + let winston = require('winston') // Console @@ -25,6 +23,7 @@ module.exports = (processName) => { }) logger.filters.push((level, msg) => { + let processName = (cluster.isMaster) ? 'MASTER' : `WORKER-${cluster.worker.id}` return '[' + processName + '] ' + msg }) diff --git a/server/modules/search-index/index.js b/server/modules/search-index/index.js deleted file mode 100644 index 807219d9..00000000 --- a/server/modules/search-index/index.js +++ /dev/null @@ -1,81 +0,0 @@ -const bunyan = require('bunyan') -const level = require('levelup') -const down = require('memdown') -const SearchIndexAdder = require('search-index-adder') -const SearchIndexSearcher = require('search-index-searcher') - -module.exports = function (givenOptions, moduleReady) { - const optionsLoaded = function (err, SearchIndex) { - const siUtil = require('./siUtil.js')(SearchIndex.options) - if (err) return moduleReady(err) - SearchIndex.close = siUtil.close - SearchIndex.countDocs = siUtil.countDocs - getAdder(SearchIndex, adderLoaded) - } - - const adderLoaded = function (err, SearchIndex) { - if (err) return moduleReady(err) - getSearcher(SearchIndex, searcherLoaded) - } - - const searcherLoaded = function (err, SearchIndex) { - if (err) return moduleReady(err) - return moduleReady(err, SearchIndex) - } - - getOptions(givenOptions, optionsLoaded) -} - -const getAdder = function (SearchIndex, done) { - SearchIndexAdder(SearchIndex.options, function (err, searchIndexAdder) { - SearchIndex.add = searchIndexAdder.add - SearchIndex.callbackyAdd = searchIndexAdder.concurrentAdd // deprecated - SearchIndex.concurrentAdd = searchIndexAdder.concurrentAdd - SearchIndex.createWriteStream = searchIndexAdder.createWriteStream - SearchIndex.dbWriteStream = searchIndexAdder.dbWriteStream - SearchIndex.defaultPipeline = searchIndexAdder.defaultPipeline - SearchIndex.del = searchIndexAdder.deleter - SearchIndex.deleteStream = searchIndexAdder.deleteStream - SearchIndex.flush = searchIndexAdder.flush - done(err, SearchIndex) - }) -} - -const getSearcher = function (SearchIndex, done) { - SearchIndexSearcher(SearchIndex.options, function (err, searchIndexSearcher) { - SearchIndex.availableFields = searchIndexSearcher.availableFields - SearchIndex.buckets = searchIndexSearcher.bucketStream - SearchIndex.categorize = searchIndexSearcher.categoryStream - SearchIndex.dbReadStream = searchIndexSearcher.dbReadStream - SearchIndex.get = searchIndexSearcher.get - SearchIndex.match = searchIndexSearcher.match - SearchIndex.scan = searchIndexSearcher.scan - SearchIndex.search = searchIndexSearcher.search - SearchIndex.totalHits = searchIndexSearcher.totalHits - done(err, SearchIndex) - }) -} - -const getOptions = function (options, done) { - var SearchIndex = {} - SearchIndex.options = Object.assign({}, { - indexPath: 'si', - keySeparator: '○', - logLevel: 'error' - }, options) - options.log = bunyan.createLogger({ - name: 'search-index', - level: options.logLevel - }) - if (!options.indexes) { - level(SearchIndex.options.indexPath || 'si', { - valueEncoding: 'json', - db: down - }, function (err, db) { - SearchIndex.options.indexes = db - return done(err, SearchIndex) - }) - } else { - return done(null, SearchIndex) - } -} diff --git a/server/modules/search-index/siUtil.js b/server/modules/search-index/siUtil.js deleted file mode 100644 index bad264a7..00000000 --- a/server/modules/search-index/siUtil.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict' - -module.exports = function (siOptions) { - var siUtil = {} - - siUtil.countDocs = function (callback) { - var count = 0 - const gte = 'DOCUMENT' + siOptions.keySeparator - const lte = 'DOCUMENT' + siOptions.keySeparator + siOptions.keySeparator - siOptions.indexes.createReadStream({gte: gte, lte: lte}) - .on('data', function (data) { - count++ - }) - .on('error', function (err) { - return callback(err, null) - }) - .on('end', function () { - return callback(null, count) - }) - } - - siUtil.close = function (callback) { - siOptions.indexes.close(function (err) { - while (!siOptions.indexes.isClosed()) { - // log not always working here- investigate - if (siOptions.log) siOptions.log.info('closing...') - } - if (siOptions.indexes.isClosed()) { - if (siOptions.log) siOptions.log.info('closed...') - callback(err) - } - }) - } - - return siUtil -} diff --git a/server/modules/search.js b/server/modules/search.js index d2978aa2..7801a739 100644 --- a/server/modules/search.js +++ b/server/modules/search.js @@ -4,7 +4,7 @@ const Promise = require('bluebird') const _ = require('lodash') -const searchIndex = require('./search-index') +// const searchIndex = require('./search-index') const stopWord = require('stopword') const streamToPromise = require('stream-to-promise') const searchAllowedChars = new RegExp('[^a-z0-9' + wiki.data.regex.cjk + wiki.data.regex.arabic + ' ]', 'g') @@ -22,7 +22,7 @@ module.exports = { init () { let self = this self._isReady = new Promise((resolve, reject) => { - searchIndex({ + /*searchIndex({ deletable: true, fieldedSearch: true, indexPath: 'wiki', @@ -39,7 +39,7 @@ module.exports = { resolve(true) }) } - }) + }) */ }) return self diff --git a/server/agent.js b/server/worker.js similarity index 69% rename from server/agent.js rename to server/worker.js index 327496e8..7ad76277 100644 --- a/server/agent.js +++ b/server/worker.js @@ -1,39 +1,19 @@ -// =========================================== -// Wiki.js - Background Agent -// 1.0.1 -// Licensed under AGPLv3 -// =========================================== +'use strict' -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 appconf = require('./modules/config')() -global.appconfig = appconf.config -global.appdata = appconf.data - -// ---------------------------------------- -// Load Winston -// ---------------------------------------- +/* global wiki */ -global.winston = require('./modules/logger')(IS_DEBUG, 'AGENT') +const path = require('path') // ---------------------------------------- // Load global modules // ---------------------------------------- -global.winston.info('Background Agent is initializing...') - -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('./modules/markdown') +wiki.db = require('./modules/db').init() +wiki.upl = require('./modules/uploads-agent').init() +wiki.git = require('./modules/git').init() +wiki.entries = require('./modules/entries').init() +wiki.lang = require('i18next') +wiki.mark = require('./modules/markdown') // ---------------------------------------- // Load modules @@ -52,20 +32,18 @@ const entryHelper = require('./helpers/entry') // 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') + } +}) // ---------------------------------------- // Start Cron @@ -75,8 +53,8 @@ let job let jobIsBusy = false let jobUplWatchStarted = false -global.db.onReady.then(() => { - return global.db.Entry.remove({}) +wiki.db.onReady.then(() => { + return wiki.db.Entry.remove({}) }).then(() => { job = new Cron({ cronTime: '0 */5 * * * *', @@ -84,17 +62,17 @@ global.db.onReady.then(() => { // Make sure we don't start two concurrent jobs if (jobIsBusy) { - global.winston.warn('Previous job has not completed gracefully or is still running! Skipping for now. (This is not normal, you should investigate)') + wiki.logger.warn('Previous job has not completed gracefully or is still running! Skipping for now. (This is not normal, you should investigate)') return } - global.winston.info('Running all jobs...') + wiki.logger.info('Running all jobs...') jobIsBusy = true // Prepare async job collector let jobs = [] - let repoPath = path.resolve(ROOTPATH, appconfig.paths.repo) - let dataPath = path.resolve(ROOTPATH, appconfig.paths.data) + let repoPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo) + let dataPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data) let uploadsTempPath = path.join(dataPath, 'temp-upload') // ---------------------------------------- @@ -105,7 +83,7 @@ global.db.onReady.then(() => { // -> Sync with Git remote //* **************************************** - jobs.push(global.git.resync().then(() => { + jobs.push(wiki.git.resync().then(() => { // -> Stream all documents let cacheJobs = [] @@ -185,18 +163,18 @@ global.db.onReady.then(() => { // ---------------------------------------- Promise.all(jobs).then(() => { - global.winston.info('All jobs completed successfully! Going to sleep for now.') + wiki.logger.info('All jobs completed successfully! Going to sleep for now.') if (!jobUplWatchStarted) { jobUplWatchStarted = true - global.upl.initialScan().then(() => { + wiki.upl.initialScan().then(() => { job.start() }) } return true }).catch((err) => { - global.winston.error('One or more jobs have failed: ', err) + wiki.logger.error('One or more jobs have failed: ', err) }).finally(() => { jobIsBusy = false }) @@ -212,7 +190,7 @@ global.db.onReady.then(() => { // ---------------------------------------- process.on('disconnect', () => { - global.winston.warn('Lost connection to main server. Exiting...') + wiki.logger.warn('Lost connection to main server. Exiting...') job.stop() process.exit() }) diff --git a/yarn.lock b/yarn.lock index 0bac2239..e52fcd68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1036,7 +1036,7 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@~3.5.0: +bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@^3.5.0, bluebird@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" @@ -1124,6 +1124,18 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +bull@/home/nick3.0.0-rc.4: + version "3.0.0-rc.4" + resolved "https://registry.yarnpkg.com/bull/-/bull-3.0.0-rc.4.tgz#dea18e870787037183849fc0198982ed756589b7" + dependencies: + bluebird "^3.5.0" + cron-parser "^2.4.1" + debuglog "^1.0.0" + ioredis "^3.1.1" + lodash "^4.17.4" + semver "^5.3.0" + uuid "^3.1.0" + bunyan@^1.8.1, bunyan@^1.8.10, bunyan@^1.8.3, bunyan@~1.8.10: version "1.8.10" resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.10.tgz#201fedd26c7080b632f416072f53a90b9a52981c" @@ -1590,6 +1602,13 @@ crc@3.4.4, crc@^3.4.0: version "3.4.4" resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b" +cron-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.4.1.tgz#022befce1af293e4d3144ff04c2cbd2edb491271" + dependencies: + is-nan "^1.2.1" + moment-timezone "^0.5.0" + cron@1.2.1, cron@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/cron/-/cron-1.2.1.tgz#3a86c09b41b8f261ac863a7cc85ea4735857eab2" @@ -1702,6 +1721,10 @@ debug@~2.2.0: dependencies: ms "0.7.1" +debuglog@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1732,6 +1755,13 @@ deferred-leveldown@~1.2.1: dependencies: abstract-leveldown "~2.4.0" +define-properties@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -2573,6 +2603,10 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -3207,6 +3241,19 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +ioredis@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.2.tgz#2579e3eba6dc490f68f14c7b51346281332b467b" + dependencies: + bluebird "^3.3.4" + cluster-key-slot "^1.0.6" + debug "^2.2.0" + denque "^1.1.0" + flexbuffer "0.0.6" + lodash "^4.8.2" + redis-commands "^1.2.0" + redis-parser "^2.4.0" + ioredis@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.1.tgz#cc2f1d3232b8c95cc153046bce168f2baa1186e8" @@ -3320,6 +3367,12 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" +is-nan@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" + dependencies: + define-properties "^1.1.1" + is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" @@ -4574,7 +4627,7 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -moment-timezone@^0.5.4, moment-timezone@^0.5.x, moment-timezone@~0.5.13: +moment-timezone@^0.5.0, moment-timezone@^0.5.4, moment-timezone@^0.5.x, moment-timezone@~0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.13.tgz#99ce5c7d827262eb0f1f702044177f60745d7b90" dependencies: @@ -4877,6 +4930,10 @@ object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" +object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -7045,7 +7102,7 @@ uuid@^2.0.1, uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" -uuid@^3.0.0, uuid@^3.0.1: +uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" From f32429325cc39edb8243052a266e750fde346f6c Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 29 Jul 2017 17:33:08 -0400 Subject: [PATCH 04/33] feat: modular auth + queue tasks --- config.sample.yml | 8 +- package.json | 1 - server/app/data.yml | 70 +---- server/authentication/azure.js | 33 +++ server/authentication/facebook.js | 28 ++ server/authentication/github.js | 28 ++ server/authentication/google.js | 27 ++ server/authentication/ldap.js | 41 +++ server/authentication/local.js | 34 +++ server/authentication/microsoft.js | 27 ++ server/authentication/slack.js | 27 ++ server/index.js | 29 +- server/master.js | 428 +++++++++++++++-------------- server/modules/auth.js | 269 +++--------------- server/modules/config.js | 121 +++++--- server/modules/db.js | 8 +- server/modules/disk.js | 8 +- server/modules/git.js | 2 +- server/modules/logger.js | 124 +++++---- server/modules/markdown.js | 6 +- server/modules/uploads-agent.js | 24 +- server/queues/git-sync.js | 65 +++++ server/queues/upl-clear-temp.js | 26 ++ server/worker.js | 170 ++---------- yarn.lock | 2 +- 25 files changed, 829 insertions(+), 777 deletions(-) create mode 100644 server/authentication/azure.js create mode 100644 server/authentication/facebook.js create mode 100644 server/authentication/github.js create mode 100644 server/authentication/google.js create mode 100644 server/authentication/ldap.js create mode 100644 server/authentication/local.js create mode 100644 server/authentication/microsoft.js create mode 100644 server/authentication/slack.js create mode 100644 server/queues/git-sync.js create mode 100644 server/queues/upl-clear-temp.js diff --git a/config.sample.yml b/config.sample.yml index d3359c9c..a42a67ba 100644 --- a/config.sample.yml +++ b/config.sample.yml @@ -5,7 +5,7 @@ # https://docs.requarks.io/wiki/install # --------------------------------------------------------------------- -# Port the main server should listen to (80 by default) +# Port the main server should listen to # --------------------------------------------------------------------- port: 80 @@ -39,3 +39,9 @@ redis: db: 0 password: null +# --------------------------------------------------------------------- +# Background Workers +# --------------------------------------------------------------------- + +# Leave 0 for auto based on CPU cores +workers: 0 diff --git a/package.json b/package.json index d20fd14e..06f4fbec 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,6 @@ "connect-flash": "~0.1.1", "connect-redis": "~3.3.0", "cookie-parser": "~1.4.3", - "cron": "~1.2.1", "diff2html": "~2.3.0", "execa": "~0.7.0", "express": "~4.15.3", diff --git a/server/app/data.yml b/server/app/data.yml index cd8e839d..8ab67828 100644 --- a/server/app/data.yml +++ b/server/app/data.yml @@ -5,65 +5,22 @@ name: Wiki.js defaults: config: - title: Wiki - host: http://localhost port: 80 paths: repo: ./repo data: ./data - uploads: - maxImageFileSize: 3, - maxOtherFileSize: 100 - lang: en - public: false - auth: - defaultReadAccess: false - local: - enabled: true - microsoft: - enabled: false - google: - enabled: false - facebook: - enabled: false - github: - enabled: false - slack: - enabled: false - ldap: - enabled: false - azure: - enabled: false - db: mongodb://localhost/wiki - sessionSecret: null - admin: null - git: - url: null - branch: master - auth: - type: basic - username: null - password: null - privateKey: null - sslVerify: true - serverEmail: wiki@example.com - showUserEmail: true - features: - linebreaks: true - mathjax: true - externalLogging: - bugsnap: false - loggly: false - papertrail: false - rollbar: false - sentry: false - theme: - primary: indigo - alt: blue-grey - footer: blue-grey - code: - dark: true - colorize: true + db: + host: localhost + port: 5432 + user: wikijs + pass: wikijsrocks + db: wiki + redis: + host: localhost + port: 6379 + db: 0 + password: null + workers: 0 authProviders: - local - microsoft @@ -112,6 +69,9 @@ langs: - id: ko name: Korean - 한국어 + - + id: pt + name: Portuguese - Português - id: ru name: Russian - Русский diff --git a/server/authentication/azure.js b/server/authentication/azure.js new file mode 100644 index 00000000..1759aa9f --- /dev/null +++ b/server/authentication/azure.js @@ -0,0 +1,33 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// Azure AD Account +// ------------------------------------ + +const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.azure && wiki.config.auth.azure.enabled) { + const jwt = require('jsonwebtoken') + passport.use('azure_ad_oauth2', + new AzureAdOAuth2Strategy({ + 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' + wiki.db.User.processProfile(waadProfile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } +} diff --git a/server/authentication/facebook.js b/server/authentication/facebook.js new file mode 100644 index 00000000..db1c4ef9 --- /dev/null +++ b/server/authentication/facebook.js @@ -0,0 +1,28 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// Facebook Account +// ------------------------------------ + +const FacebookStrategy = require('passport-facebook').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.facebook && wiki.config.auth.facebook.enabled) { + passport.use('facebook', + new FacebookStrategy({ + 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) { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } +} diff --git a/server/authentication/github.js b/server/authentication/github.js new file mode 100644 index 00000000..c26df1b3 --- /dev/null +++ b/server/authentication/github.js @@ -0,0 +1,28 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// GitHub Account +// ------------------------------------ + +const GitHubStrategy = require('passport-github2').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.github && wiki.config.auth.github.enabled) { + passport.use('github', + new GitHubStrategy({ + 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) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } +} diff --git a/server/authentication/google.js b/server/authentication/google.js new file mode 100644 index 00000000..12d51f2e --- /dev/null +++ b/server/authentication/google.js @@ -0,0 +1,27 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// Google ID Account +// ------------------------------------ + +const GoogleStrategy = require('passport-google-oauth20').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.google && wiki.config.auth.google.enabled) { + passport.use('google', + new GoogleStrategy({ + clientID: wiki.config.auth.google.clientId, + clientSecret: wiki.config.auth.google.clientSecret, + callbackURL: wiki.config.host + '/login/google/callback' + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } +} diff --git a/server/authentication/ldap.js b/server/authentication/ldap.js new file mode 100644 index 00000000..cc3ebf7c --- /dev/null +++ b/server/authentication/ldap.js @@ -0,0 +1,41 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// LDAP Account +// ------------------------------------ + +const LdapStrategy = require('passport-ldapauth').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.ldap && wiki.config.auth.ldap.enabled) { + passport.use('ldapauth', + new LdapStrategy({ + server: { + 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: (wiki.config.auth.ldap.tlsEnabled) ? { + ca: [ + fs.readFileSync(wiki.config.auth.ldap.tlsCertPath) + ] + } : {} + }, + usernameField: 'email', + passReqToCallback: false + }, (profile, cb) => { + profile.provider = 'ldap' + profile.id = profile.dn + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } +} diff --git a/server/authentication/local.js b/server/authentication/local.js new file mode 100644 index 00000000..3af57126 --- /dev/null +++ b/server/authentication/local.js @@ -0,0 +1,34 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// Local Account +// ------------------------------------ + +const LocalStrategy = require('passport-local').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.local && wiki.config.auth.local.enabled) { + passport.use('local', + new LocalStrategy({ + usernameField: 'email', + passwordField: 'password' + }, (uEmail, uPassword, done) => { + wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => { + if (user) { + return user.validatePassword(uPassword).then(() => { + return done(null, user) || true + }).catch((err) => { + return done(err, null) + }) + } else { + return done(new Error('INVALID_LOGIN'), null) + } + }).catch((err) => { + done(err, null) + }) + } + )) + } +} diff --git a/server/authentication/microsoft.js b/server/authentication/microsoft.js new file mode 100644 index 00000000..1d39eb47 --- /dev/null +++ b/server/authentication/microsoft.js @@ -0,0 +1,27 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// Microsoft Account +// ------------------------------------ + +const WindowsLiveStrategy = require('passport-windowslive').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.microsoft && wiki.config.auth.microsoft.enabled) { + passport.use('windowslive', + new WindowsLiveStrategy({ + clientID: wiki.config.auth.microsoft.clientId, + clientSecret: wiki.config.auth.microsoft.clientSecret, + callbackURL: wiki.config.host + '/login/ms/callback' + }, function (accessToken, refreshToken, profile, cb) { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } +} diff --git a/server/authentication/slack.js b/server/authentication/slack.js new file mode 100644 index 00000000..dcc8a7f2 --- /dev/null +++ b/server/authentication/slack.js @@ -0,0 +1,27 @@ +'use strict' + +/* global wiki */ + +// ------------------------------------ +// Slack Account +// ------------------------------------ + +const SlackStrategy = require('passport-slack').Strategy + +module.exports = (passport) => { + if (wiki.config.auth.slack && wiki.config.auth.slack.enabled) { + passport.use('slack', + new SlackStrategy({ + clientID: wiki.config.auth.slack.clientId, + clientSecret: wiki.config.auth.slack.clientSecret, + callbackURL: wiki.config.host + '/login/slack/callback' + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } +} diff --git a/server/index.js b/server/index.js index aeb2f8a5..24f65480 100644 --- a/server/index.js +++ b/server/index.js @@ -6,10 +6,14 @@ // =========================================== const path = require('path') +const cluster = require('cluster') + let wiki = { IS_DEBUG: process.env.NODE_ENV === 'development', + IS_MASTER: cluster.isMaster, ROOTPATH: process.cwd(), - SERVERPATH: path.join(process.cwd(), 'server') + SERVERPATH: path.join(process.cwd(), 'server'), + configSvc: require('./modules/config') } global.wiki = wiki @@ -19,29 +23,36 @@ process.env.VIPS_WARNING = false // require('@glimpse/glimpse').init() // } -let appconf = require('./modules/config')() -wiki.config = appconf.config -wiki.data = appconf.data +wiki.configSvc.init() + +// ---------------------------------------- +// Init Logger +// ---------------------------------------- + +wiki.logger = require('./modules/logger').init() // ---------------------------------------- -// Load Winston +// Init DB // ---------------------------------------- -wiki.logger = require('./modules/logger')() +wiki.db = require('./modules/db').init() // ---------------------------------------- // Start Cluster // ---------------------------------------- -const cluster = require('cluster') const numCPUs = require('os').cpus().length +let numWorkers = (wiki.config.workers > 0) ? wiki.config.workers : numCPUs +if (numWorkers > numCPUs) { + numWorkers = numCPUs +} if (cluster.isMaster) { wiki.logger.info('Wiki.js is initializing...') require('./master') - for (let i = 0; i < numCPUs; i++) { + for (let i = 0; i < numWorkers; i++) { cluster.fork() } @@ -50,5 +61,5 @@ if (cluster.isMaster) { }) } else { wiki.logger.info(`Background Worker #${cluster.worker.id} is starting...`) - // require('./worker') + require('./worker') } diff --git a/server/master.js b/server/master.js index 75a609c8..12248ba4 100644 --- a/server/master.js +++ b/server/master.js @@ -2,231 +2,241 @@ /* global wiki */ -const path = require('path') - -// ---------------------------------------- -// Load global modules -// ---------------------------------------- - -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 -// ---------------------------------------- - -const autoload = require('auto-load') -const bodyParser = require('body-parser') -const compression = require('compression') -const cookieParser = require('cookie-parser') -const express = require('express') -const favicon = require('serve-favicon') -const flash = require('connect-flash') -const http = require('http') -const i18nBackend = require('i18next-node-fs-backend') -const passport = require('passport') -const passportSocketIo = require('passport.socketio') -const session = require('express-session') -const SessionRedisStore = require('connect-redis')(session) -const graceful = require('node-graceful') -const socketio = require('socket.io') -const graphqlApollo = require('apollo-server-express') -const graphqlSchema = require('./modules/graphql') - -var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares')) -var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers')) - -// ---------------------------------------- -// Define Express App -// ---------------------------------------- - -const app = express() -wiki.app = app -app.use(compression()) - -// ---------------------------------------- -// Security -// ---------------------------------------- - -app.use(mw.security) - -// ---------------------------------------- -// Public Assets -// ---------------------------------------- - -app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico'))) -app.use(express.static(path.join(wiki.ROOTPATH, 'assets'), { - index: false, - maxAge: '7d' -})) - -// ---------------------------------------- -// Passport Authentication -// ---------------------------------------- - -require('./modules/auth')(passport) -wiki.rights = require('./modules/rights') -wiki.rights.init() - -let sessionStore = new SessionRedisStore({ - client: wiki.redis -}) +const Promise = require('bluebird') + +module.exports = Promise.join( + wiki.db.onReady, + wiki.configSvc.loadFromDb() +).then(() => { + // ---------------------------------------- + // Load global modules + // ---------------------------------------- + + wiki.disk = require('./modules/disk').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 + // ---------------------------------------- + + const autoload = require('auto-load') + const bodyParser = require('body-parser') + const compression = require('compression') + const cookieParser = require('cookie-parser') + const express = require('express') + const favicon = require('serve-favicon') + const flash = require('connect-flash') + const http = require('http') + const i18nBackend = require('i18next-node-fs-backend') + const path = require('path') + const passport = require('passport') + const passportSocketIo = require('passport.socketio') + const session = require('express-session') + const SessionRedisStore = require('connect-redis')(session) + const graceful = require('node-graceful') + const socketio = require('socket.io') + const graphqlApollo = require('apollo-server-express') + const graphqlSchema = require('./modules/graphql') + + var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares')) + var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers')) + + // ---------------------------------------- + // Define Express App + // ---------------------------------------- + + const app = express() + wiki.app = app + app.use(compression()) + + // ---------------------------------------- + // Security + // ---------------------------------------- + + app.use(mw.security) + + // ---------------------------------------- + // Public Assets + // ---------------------------------------- + + app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico'))) + app.use(express.static(path.join(wiki.ROOTPATH, 'assets'), { + index: false, + maxAge: '7d' + })) + + // ---------------------------------------- + // Passport Authentication + // ---------------------------------------- + + require('./modules/auth')(passport) + wiki.rights = require('./modules/rights') + // wiki.rights.init() + + let sessionStore = new SessionRedisStore({ + client: wiki.redis + }) -app.use(cookieParser()) -app.use(session({ - name: 'wikijs.sid', - store: sessionStore, - secret: wiki.config.sessionSecret, - resave: false, - saveUninitialized: false -})) -app.use(flash()) -app.use(passport.initialize()) -app.use(passport.session()) - -// ---------------------------------------- -// SEO -// ---------------------------------------- - -app.use(mw.seo) - -// ---------------------------------------- -// Localization Engine -// ---------------------------------------- - -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') - } -}) + app.use(cookieParser()) + app.use(session({ + name: 'wikijs.sid', + store: sessionStore, + secret: wiki.config.site.sessionSecret, + resave: false, + saveUninitialized: false + })) + app.use(flash()) + app.use(passport.initialize()) + app.use(passport.session()) + + // ---------------------------------------- + // SEO + // ---------------------------------------- + + app.use(mw.seo) + + // ---------------------------------------- + // Localization Engine + // ---------------------------------------- + + wiki.lang.use(i18nBackend).init({ + load: 'languageOnly', + ns: ['common', 'admin', 'auth', 'errors', 'git'], + defaultNS: 'common', + saveMissing: false, + preload: [wiki.config.site.lang], + lng: wiki.config.site.lang, + fallbackLng: 'en', + backend: { + loadPath: path.join(wiki.SERVERPATH, 'locales/{{lng}}/{{ns}}.json') + } + }) -// ---------------------------------------- -// View Engine Setup -// ---------------------------------------- + // ---------------------------------------- + // View Engine Setup + // ---------------------------------------- -app.set('views', path.join(wiki.SERVERPATH, 'views')) -app.set('view engine', 'pug') + app.set('views', path.join(wiki.SERVERPATH, 'views')) + app.set('view engine', 'pug') -app.use(bodyParser.json({ limit: '1mb' })) -app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' })) + app.use(bodyParser.json({ limit: '1mb' })) + app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' })) -// ---------------------------------------- -// View accessible data -// ---------------------------------------- + // ---------------------------------------- + // View accessible data + // ---------------------------------------- -app.locals._ = require('lodash') -app.locals.t = wiki.lang.t.bind(wiki.lang) -app.locals.moment = require('moment') -app.locals.moment.locale(wiki.config.lang) -app.locals.appconfig = wiki.config -app.use(mw.flash) + app.locals._ = require('lodash') + app.locals.t = wiki.lang.t.bind(wiki.config.site.lang) + app.locals.moment = require('moment') + app.locals.moment.locale(wiki.config.site.lang) + app.locals.appconfig = wiki.config + app.use(mw.flash) -// ---------------------------------------- -// Controllers -// ---------------------------------------- + // ---------------------------------------- + // Controllers + // ---------------------------------------- -app.use('/', ctrl.auth) + app.use('/', ctrl.auth) -app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema })) -app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' })) -app.use('/uploads', mw.auth, ctrl.uploads) -app.use('/admin', mw.auth, ctrl.admin) -app.use('/', mw.auth, ctrl.pages) + app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema })) + app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' })) + app.use('/uploads', mw.auth, ctrl.uploads) + app.use('/admin', mw.auth, ctrl.admin) + app.use('/', mw.auth, ctrl.pages) -// ---------------------------------------- -// Error handling -// ---------------------------------------- + // ---------------------------------------- + // Error handling + // ---------------------------------------- -app.use(function (req, res, next) { - var err = new Error('Not Found') - err.status = 404 - next(err) -}) + app.use(function (req, res, next) { + var err = new Error('Not Found') + err.status = 404 + next(err) + }) -app.use(function (err, req, res, next) { - res.status(err.status || 500) - res.render('error', { - message: err.message, - error: wiki.IS_DEBUG ? err : {} + app.use(function (err, req, res, next) { + res.status(err.status || 500) + res.render('error', { + message: err.message, + error: wiki.IS_DEBUG ? err : {} + }) }) -}) -// ---------------------------------------- -// Start HTTP server -// ---------------------------------------- - -wiki.logger.info('Starting HTTP/WS server on port ' + wiki.config.port + '...') - -app.set('port', wiki.config.port) -var server = http.createServer(app) -var io = socketio(server) - -server.listen(wiki.config.port) -server.on('error', (error) => { - if (error.syscall !== 'listen') { - throw error - } - - // handle specific listen errors with friendly messages - switch (error.code) { - case 'EACCES': - wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!') - return process.exit(1) - case 'EADDRINUSE': - wiki.logger.error('Port ' + wiki.config.port + ' is already in use!') - return process.exit(1) - default: + // ---------------------------------------- + // Start HTTP server + // ---------------------------------------- + + wiki.logger.info('Starting HTTP/WS server on port ' + wiki.config.port + '...') + + app.set('port', wiki.config.port) + var server = http.createServer(app) + var io = socketio(server) + + server.listen(wiki.config.port) + server.on('error', (error) => { + if (error.syscall !== 'listen') { throw error - } -}) + } + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!') + return process.exit(1) + case 'EADDRINUSE': + wiki.logger.error('Port ' + wiki.config.port + ' is already in use!') + return process.exit(1) + default: + throw error + } + }) -server.on('listening', () => { - wiki.logger.info('HTTP/WS server started successfully! [RUNNING]') -}) + server.on('listening', () => { + wiki.logger.info('HTTP/WS server started successfully! [RUNNING]') + }) -// ---------------------------------------- -// WebSocket -// ---------------------------------------- - -io.use(passportSocketIo.authorize({ - key: 'wikijs.sid', - store: sessionStore, - secret: wiki.config.sessionSecret, - cookieParser, - success: (data, accept) => { - accept() - }, - fail: (data, message, error, accept) => { - accept() - } -})) - -io.on('connection', ctrl.ws) - -// ---------------------------------------- -// Graceful shutdown -// ---------------------------------------- - -graceful.on('exit', () => { - // wiki.logger.info('- SHUTTING DOWN - Terminating Background Agent...') - // bgAgent.kill() - wiki.logger.info('- SHUTTING DOWN - Performing git sync...') - return global.git.resync().then(() => { - wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.') - process.exit() + // ---------------------------------------- + // WebSocket + // ---------------------------------------- + + io.use(passportSocketIo.authorize({ + key: 'wikijs.sid', + store: sessionStore, + secret: wiki.config.site.sessionSecret, + cookieParser, + success: (data, accept) => { + accept() + }, + fail: (data, message, error, accept) => { + accept() + } + })) + + io.on('connection', ctrl.ws) + + // ---------------------------------------- + // Graceful shutdown + // ---------------------------------------- + + graceful.on('exit', () => { + // wiki.logger.info('- SHUTTING DOWN - Terminating Background Agent...') + // bgAgent.kill() + wiki.logger.info('- SHUTTING DOWN - Performing git sync...') + return global.git.resync().then(() => { + wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.') + process.exit() + }) }) + + return true +}).catch(err => { + wiki.logger.error(err) + process.exit(1) }) diff --git a/server/modules/auth.js b/server/modules/auth.js index 60bc49d8..3e96e730 100644 --- a/server/modules/auth.js +++ b/server/modules/auth.js @@ -24,232 +24,51 @@ module.exports = function (passport) { }) }) - // Local Account - - 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) => { - wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => { - if (user) { - return user.validatePassword(uPassword).then(() => { - return done(null, user) || true - }).catch((err) => { - return done(err, null) - }) - } else { - return done(new Error('INVALID_LOGIN'), null) - } - }).catch((err) => { - done(err, null) - }) - } - )) - } - - // Google ID - - if (wiki.config.auth.google && wiki.config.auth.google.enabled) { - const GoogleStrategy = require('passport-google-oauth20').Strategy - passport.use('google', - new GoogleStrategy({ - clientID: wiki.config.auth.google.clientId, - clientSecret: wiki.config.auth.google.clientSecret, - callbackURL: wiki.config.host + '/login/google/callback' - }, (accessToken, refreshToken, profile, cb) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } - - // Microsoft Accounts - - if (wiki.config.auth.microsoft && wiki.config.auth.microsoft.enabled) { - const WindowsLiveStrategy = require('passport-windowslive').Strategy - passport.use('windowslive', - new WindowsLiveStrategy({ - clientID: wiki.config.auth.microsoft.clientId, - clientSecret: wiki.config.auth.microsoft.clientSecret, - callbackURL: wiki.config.host + '/login/ms/callback' - }, function (accessToken, refreshToken, profile, cb) { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } - - // Facebook - - if (wiki.config.auth.facebook && wiki.config.auth.facebook.enabled) { - const FacebookStrategy = require('passport-facebook').Strategy - passport.use('facebook', - new FacebookStrategy({ - 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) { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } - - // GitHub - - if (wiki.config.auth.github && wiki.config.auth.github.enabled) { - const GitHubStrategy = require('passport-github2').Strategy - passport.use('github', - new GitHubStrategy({ - 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) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } - - // Slack - - if (wiki.config.auth.slack && wiki.config.auth.slack.enabled) { - const SlackStrategy = require('passport-slack').Strategy - passport.use('slack', - new SlackStrategy({ - clientID: wiki.config.auth.slack.clientId, - clientSecret: wiki.config.auth.slack.clientSecret, - callbackURL: wiki.config.host + '/login/slack/callback' - }, (accessToken, refreshToken, profile, cb) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } - - // LDAP - - if (wiki.config.auth.ldap && wiki.config.auth.ldap.enabled) { - const LdapStrategy = require('passport-ldapauth').Strategy - passport.use('ldapauth', - new LdapStrategy({ - server: { - 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: (wiki.config.auth.ldap.tlsEnabled) ? { - ca: [ - fs.readFileSync(wiki.config.auth.ldap.tlsCertPath) - ] - } : {} - }, - usernameField: 'email', - passReqToCallback: false - }, (profile, cb) => { - profile.provider = 'ldap' - profile.id = profile.dn - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } - - // AZURE AD - - 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: 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' - wiki.db.User.processProfile(waadProfile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } - // Create users for first-time - wiki.db.onReady.then(() => { - return wiki.db.User.findOne({ provider: 'local', email: 'guest' }).then((c) => { - if (c < 1) { - // Create guest account - - return wiki.db.User.create({ - provider: 'local', - email: 'guest@example.com', - name: 'Guest', - password: '', - role: 'guest' - }).then(() => { - wiki.logger.info('[AUTH] Guest account created successfully!') - return true - }).catch((err) => { - wiki.logger.error('[AUTH] An error occured while creating guest account:') - wiki.logger.error(err) - return err - }) - } - }).then(() => { - if (process.env.WIKI_JS_HEROKU) { - 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 wiki.db.User.create({ - provider: 'local', - email: process.env.WIKI_ADMIN_EMAIL, - name: 'Administrator', - password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default) - role: 'admin' - }).then(() => { - wiki.logger.info('[AUTH] Root admin account created successfully!') - return true - }).catch((err) => { - wiki.logger.error('[AUTH] An error occured while creating root admin account:') - wiki.logger.error(err) - return err - }) - } else { return true } - }) - } else { return true } - }) + return wiki.db.User.findOne({ provider: 'local', email: 'guest@example.com' }).then((c) => { + if (c < 1) { + // Create guest account + + return wiki.db.User.create({ + provider: 'local', + email: 'guest@example.com', + name: 'Guest', + password: '', + role: 'guest' + }).then(() => { + wiki.logger.info('[AUTH] Guest account created successfully!') + return true + }).catch((err) => { + wiki.logger.error('[AUTH] An error occured while creating guest account:') + wiki.logger.error(err) + return err + }) + } }) + + // .then(() => { + // if (process.env.WIKI_JS_HEROKU) { + // 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 wiki.db.User.create({ + // provider: 'local', + // email: process.env.WIKI_ADMIN_EMAIL, + // name: 'Administrator', + // password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default) + // role: 'admin' + // }).then(() => { + // wiki.logger.info('[AUTH] Root admin account created successfully!') + // return true + // }).catch((err) => { + // wiki.logger.error('[AUTH] An error occured while creating root admin account:') + // wiki.logger.error(err) + // return err + // }) + // } else { return true } + // }) + // } else { return true } + // }) } diff --git a/server/modules/config.js b/server/modules/config.js index 4c120338..bb07c02f 100644 --- a/server/modules/config.js +++ b/server/modules/config.js @@ -8,62 +8,95 @@ const _ = require('lodash') const path = require('path') const cfgHelper = require('../helpers/config') -/** - * Load Application Configuration - * - * @param {Object} confPaths Path to the configuration files - * @return {Object} Application Configuration - */ -module.exports = (confPaths) => { - confPaths = _.defaults(confPaths, { - 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 = {} - let appdata = {} - - try { - appconfig = yaml.safeLoad( - cfgHelper.parseConfigValue( - fs.readFileSync(confPaths.config, 'utf8') +module.exports = { + SUBSETS: ['auth', 'features', 'git', 'logging', 'site', 'theme', 'uploads'], + + /** + * Load root config from disk + * + * @param {any} confPaths + * @returns + */ + init() { + let confPaths = { + 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 = {} + let appdata = {} + + try { + appconfig = yaml.safeLoad( + cfgHelper.parseConfigValue( + fs.readFileSync(confPaths.config, 'utf8') + ) ) - ) - appdata = yaml.safeLoad(fs.readFileSync(confPaths.data, 'utf8')) - appdata.regex = require(confPaths.dataRegex) - } catch (ex) { - console.error(ex) - process.exit(1) - } + appdata = yaml.safeLoad(fs.readFileSync(confPaths.data, 'utf8')) + appdata.regex = require(confPaths.dataRegex) + } catch (ex) { + console.error(ex) + process.exit(1) + } - // Merge with defaults + // Merge with defaults - appconfig = _.defaultsDeep(appconfig, appdata.defaults.config) + appconfig = _.defaultsDeep(appconfig, appdata.defaults.config) - // Check port + // Check port - if (appconfig.port < 1) { - appconfig.port = process.env.PORT || 80 - } + if (appconfig.port < 1) { + appconfig.port = process.env.PORT || 80 + } // Convert booleans appconfig.public = (appconfig.public === true || _.toLower(appconfig.public) === 'true') // List authentication strategies + wiki.config = appconfig + wiki.data = appdata - appconfig.authStrategies = { - list: _.filter(appconfig.auth, ['enabled', true]), - socialEnabled: (_.chain(appconfig.auth).omit(['local', 'ldap']).filter(['enabled', true]).value().length > 0) - } - if (appconfig.authStrategies.list.length < 1) { - console.error(new Error('You must enable at least 1 authentication strategy!')) - process.exit(1) - } + // List authentication strategies + + // appconfig.authStrategies = { + // list: _.filter(appconfig.auth, ['enabled', true]), + // socialEnabled: (_.chain(appconfig.auth).omit('local').filter(['enabled', true]).value().length > 0) + // } + // if (appconfig.authStrategies.list.length < 1) { + // console.error(new Error('You must enable at least 1 authentication strategy!')) + // process.exit(1) + // } + }, + + /** + * Load config from DB + * + * @param {Array} subsets Array of subsets to load + * @returns Promise + */ + loadFromDb(subsets) { + if (!_.isArray(subsets) || subsets.length === 0) { + subsets = this.SUBSETS + } - return { - config: appconfig, - data: appdata + return wiki.db.Setting.findAll({ + attributes: ['key', 'config'], + where: { + key: { + $in: subsets + } + } + }).then(results => { + if (_.isArray(results) && results.length > 0) { + results.forEach(result => { + wiki.config[result.key] = result.config + }) + return true + } else { + return Promise.reject(new Error('Invalid DB Configuration result set')) + } + }) } } diff --git a/server/modules/db.js b/server/modules/db.js index 89ca5ce1..36bbfadc 100644 --- a/server/modules/db.js +++ b/server/modules/db.js @@ -5,6 +5,7 @@ const fs = require('fs') const path = require('path') const _ = require('lodash') +const Promise = require('bluebird') /** * PostgreSQL DB module @@ -33,7 +34,8 @@ module.exports = { max: 10, min: 0, idle: 10000 - } + }, + logging: false }) // Attempt to connect and authenticate to DB @@ -63,10 +65,10 @@ module.exports = { // Sync DB - self.onReady = self.inst.sync({ + self.onReady = (wiki.IS_MASTER) ? self.inst.sync({ force: false, logging: false - }) + }) : Promise.resolve() return self } diff --git a/server/modules/disk.js b/server/modules/disk.js index 9e919229..88c54279 100644 --- a/server/modules/disk.js +++ b/server/modules/disk.js @@ -27,7 +27,7 @@ module.exports = { this._uploadsThumbsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'thumbs') this.createBaseDirectories() - this.initMulter() + // this.initMulter() return this }, @@ -37,8 +37,10 @@ module.exports = { */ initMulter () { let maxFileSizes = { - img: wiki.config.uploads.maxImageFileSize * 1024 * 1024, - file: wiki.config.uploads.maxOtherFileSize * 1024 * 1024 + // img: wiki.config.uploads.maxImageFileSize * 1024 * 1024, + // file: wiki.config.uploads.maxOtherFileSize * 1024 * 1024 + img: 3 * 1024 * 1024, + file: 10 * 1024 * 1024 } // -> IMAGES diff --git a/server/modules/git.js b/server/modules/git.js index b0155ce9..4c58a48f 100644 --- a/server/modules/git.js +++ b/server/modules/git.js @@ -51,7 +51,7 @@ module.exports = { // -> Initialize repository - self.onReady = self._initRepo() + self.onReady = (wiki.IS_MASTER) ? self._initRepo() : Promise.resolve() // Define signature diff --git a/server/modules/logger.js b/server/modules/logger.js index 08ecc175..8b134d05 100644 --- a/server/modules/logger.js +++ b/server/modules/logger.js @@ -4,75 +4,77 @@ const cluster = require('cluster') -module.exports = () => { - let winston = require('winston') +module.exports = { + init() { + let winston = require('winston') - // Console + // Console - let logger = new (winston.Logger)({ - level: (wiki.IS_DEBUG) ? 'debug' : 'info', - transports: [ - new (winston.transports.Console)({ - level: (wiki.IS_DEBUG) ? 'debug' : 'info', - prettyPrint: true, - colorize: true, - silent: false, - timestamp: true - }) - ] - }) + let logger = new (winston.Logger)({ + level: (wiki.IS_DEBUG) ? 'debug' : 'info', + transports: [ + new (winston.transports.Console)({ + level: (wiki.IS_DEBUG) ? 'debug' : 'info', + prettyPrint: true, + colorize: true, + silent: false, + timestamp: true + }) + ] + }) - logger.filters.push((level, msg) => { - let processName = (cluster.isMaster) ? 'MASTER' : `WORKER-${cluster.worker.id}` - return '[' + processName + '] ' + msg - }) + logger.filters.push((level, msg) => { + let processName = (cluster.isMaster) ? 'MASTER' : `WORKER-${cluster.worker.id}` + return '[' + processName + '] ' + msg + }) - // External services + // External services - if (wiki.config.externalLogging.bugsnag) { - const bugsnagTransport = require('./winston-transports/bugsnag') - logger.add(bugsnagTransport, { - level: 'warn', - key: wiki.config.externalLogging.bugsnag - }) - } + // if (wiki.config.externalLogging.bugsnag) { + // const bugsnagTransport = require('./winston-transports/bugsnag') + // logger.add(bugsnagTransport, { + // level: 'warn', + // key: wiki.config.externalLogging.bugsnag + // }) + // } - if (wiki.config.externalLogging.loggly) { - require('winston-loggly-bulk') - logger.add(winston.transports.Loggly, { - token: wiki.config.externalLogging.loggly.token, - subdomain: wiki.config.externalLogging.loggly.subdomain, - tags: ['wiki-js'], - level: 'warn', - json: true - }) - } + // if (wiki.config.externalLogging.loggly) { + // require('winston-loggly-bulk') + // logger.add(winston.transports.Loggly, { + // token: wiki.config.externalLogging.loggly.token, + // subdomain: wiki.config.externalLogging.loggly.subdomain, + // tags: ['wiki-js'], + // level: 'warn', + // json: true + // }) + // } - if (wiki.config.externalLogging.papertrail) { - require('winston-papertrail').Papertrail // eslint-disable-line no-unused-expressions - logger.add(winston.transports.Papertrail, { - host: wiki.config.externalLogging.papertrail.host, - port: wiki.config.externalLogging.papertrail.port, - level: 'warn', - program: 'wiki.js' - }) - } + // if (wiki.config.externalLogging.papertrail) { + // require('winston-papertrail').Papertrail // eslint-disable-line no-unused-expressions + // logger.add(winston.transports.Papertrail, { + // host: wiki.config.externalLogging.papertrail.host, + // port: wiki.config.externalLogging.papertrail.port, + // level: 'warn', + // program: 'wiki.js' + // }) + // } - if (wiki.config.externalLogging.rollbar) { - const rollbarTransport = require('./winston-transports/rollbar') - logger.add(rollbarTransport, { - level: 'warn', - key: wiki.config.externalLogging.rollbar - }) - } + // if (wiki.config.externalLogging.rollbar) { + // const rollbarTransport = require('./winston-transports/rollbar') + // logger.add(rollbarTransport, { + // level: 'warn', + // key: wiki.config.externalLogging.rollbar + // }) + // } - if (wiki.config.externalLogging.sentry) { - const sentryTransport = require('./winston-transports/sentry') - logger.add(sentryTransport, { - level: 'warn', - key: wiki.config.externalLogging.sentry - }) - } + // if (wiki.config.externalLogging.sentry) { + // const sentryTransport = require('./winston-transports/sentry') + // logger.add(sentryTransport, { + // level: 'warn', + // key: wiki.config.externalLogging.sentry + // }) + // } - return logger + return logger + } } diff --git a/server/modules/markdown.js b/server/modules/markdown.js index c88266d7..71e0ea54 100644 --- a/server/modules/markdown.js +++ b/server/modules/markdown.js @@ -23,7 +23,8 @@ const mdRemove = require('remove-markdown') var mkdown = md({ html: true, - breaks: wiki.config.features.linebreaks, + // breaks: wiki.config.features.linebreaks, + breaks: true, linkify: true, typography: true, highlight(str, lang) { @@ -57,7 +58,8 @@ var mkdown = md({ }) .use(mdAttrs) -if (wiki.config.features.mathjax) { +// if (wiki.config.features.mathjax) { +if (true) { mkdown.use(mdMathjax) } diff --git a/server/modules/uploads-agent.js b/server/modules/uploads-agent.js index a8ae79ec..6b861733 100644 --- a/server/modules/uploads-agent.js +++ b/server/modules/uploads-agent.js @@ -1,6 +1,6 @@ 'use strict' -/* global db, git, lang, upl */ +/* global wiki */ const path = require('path') const Promise = require('bluebird') @@ -32,8 +32,8 @@ module.exports = { init () { let self = this - self._uploadsPath = path.resolve(ROOTPATH, appconfig.paths.repo, 'uploads') - self._uploadsThumbsPath = path.resolve(ROOTPATH, appconfig.paths.data, 'thumbs') + self._uploadsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, 'uploads') + self._uploadsThumbsPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data, 'thumbs') return self }, @@ -59,16 +59,16 @@ module.exports = { self._watcher.on('add', (p) => { let pInfo = self.parseUploadsRelPath(p) return self.processFile(pInfo.folder, pInfo.filename).then((mData) => { - return db.UplFile.findByIdAndUpdate(mData._id, mData, { upsert: true }) + return wiki.db.UplFile.findByIdAndUpdate(mData._id, mData, { upsert: true }) }).then(() => { - return git.commitUploads(lang.t('git:uploaded', { path: p })) + return wiki.git.commitUploads(wiki.lang.t('git:uploaded', { path: p })) }) }) // -> Remove upload file self._watcher.on('unlink', (p) => { - return git.commitUploads(lang.t('git:deleted', { path: p })) + return wiki.git.commitUploads(wiki.lang.t('git:deleted', { path: p })) }) }, @@ -91,8 +91,8 @@ module.exports = { // Add folders to DB - return db.UplFolder.remove({}).then(() => { - return db.UplFolder.insertMany(_.map(folderNames, (f) => { + return wiki.db.UplFolder.remove({}).then(() => { + return wiki.db.UplFolder.insertMany(_.map(folderNames, (f) => { return { _id: 'f:' + f, name: f @@ -107,7 +107,7 @@ module.exports = { let fldPath = path.join(self._uploadsPath, fldName) return fs.readdirAsync(fldPath).then((fList) => { return Promise.map(fList, (f) => { - return upl.processFile(fldName, f).then((mData) => { + return wiki.upl.processFile(fldName, f).then((mData) => { if (mData) { allFiles.push(mData) } @@ -118,9 +118,9 @@ module.exports = { }, {concurrency: 1}).finally(() => { // Add files to DB - return db.UplFile.remove({}).then(() => { + return wiki.db.UplFile.remove({}).then(() => { if (_.isArray(allFiles) && allFiles.length > 0) { - return db.UplFile.insertMany(allFiles) + return wiki.db.UplFile.insertMany(allFiles) } else { return true } @@ -131,7 +131,7 @@ module.exports = { }).then(() => { // Watch for new changes - return upl.watch() + return wiki.upl.watch() }) }, diff --git a/server/queues/git-sync.js b/server/queues/git-sync.js new file mode 100644 index 00000000..9f9b1f57 --- /dev/null +++ b/server/queues/git-sync.js @@ -0,0 +1,65 @@ +'use strict' + +/* global wiki */ + +const Promise = require('bluebird') +const fs = Promise.promisifyAll(require('fs-extra')) +const klaw = require('klaw') +const moment = require('moment') +const path = require('path') +const entryHelper = require('../helpers/entry') + +module.exports = (job, done) => { + return wiki.git.resync().then(() => { + // -> Stream all documents + + let cacheJobs = [] + let jobCbStreamDocsResolve = null + let jobCbStreamDocs = new Promise((resolve, reject) => { + jobCbStreamDocsResolve = resolve + }) + + klaw(wiki.REPOPATH).on('data', function (item) { + if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') { + let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path)) + let cachePath = entryHelper.getCachePath(entryPath) + + // -> Purge outdated cache + + cacheJobs.push( + fs.statAsync(cachePath).then((st) => { + return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active' + }).catch((err) => { + return (err.code !== 'EEXIST') ? err : 'new' + }).then((fileStatus) => { + // -> Delete expired cache file + + if (fileStatus === 'expired') { + return fs.unlinkAsync(cachePath).return(fileStatus) + } + + return fileStatus + }).then((fileStatus) => { + // -> Update cache and search index + + if (fileStatus !== 'active') { + return global.entries.updateCache(entryPath).then(entry => { + process.send({ + action: 'searchAdd', + content: entry + }) + return true + }) + } + + return true + }) + ) + } + }).on('end', () => { + jobCbStreamDocsResolve(Promise.all(cacheJobs)) + }) + + return jobCbStreamDocs + }) +} diff --git a/server/queues/upl-clear-temp.js b/server/queues/upl-clear-temp.js new file mode 100644 index 00000000..2162aae4 --- /dev/null +++ b/server/queues/upl-clear-temp.js @@ -0,0 +1,26 @@ +'use strict' + +/* global wiki */ + +const Promise = require('bluebird') +const fs = Promise.promisifyAll(require('fs-extra')) +const moment = require('moment') +const path = require('path') + +module.exports = (job, done) => { + return fs.readdirAsync(wiki.UPLTEMPPATH).then((ls) => { + let fifteenAgo = moment().subtract(15, 'minutes') + + return Promise.map(ls, (f) => { + return fs.statAsync(path.join(wiki.UPLTEMPPATH, f)).then((s) => { return { filename: f, stat: s } }) + }).filter((s) => { return s.stat.isFile() }).then((arrFiles) => { + return Promise.map(arrFiles, (f) => { + if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) { + return fs.unlinkAsync(path.join(wiki.UPLTEMPPATH, f.filename)) + } else { + return true + } + }) + }) + }) +} diff --git a/server/worker.js b/server/worker.js index 7ad76277..f64deca5 100644 --- a/server/worker.js +++ b/server/worker.js @@ -4,30 +4,27 @@ const path = require('path') +wiki.REPOPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo) +wiki.DATAPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.data) +wiki.UPLTEMPPATH = path.join(wiki.DATAPATH, 'temp-upload') + // ---------------------------------------- // Load global modules // ---------------------------------------- -wiki.db = require('./modules/db').init() -wiki.upl = require('./modules/uploads-agent').init() -wiki.git = require('./modules/git').init() -wiki.entries = require('./modules/entries').init() +// wiki.upl = require('./modules/uploads-agent').init() +// wiki.git = require('./modules/git').init() +// wiki.entries = require('./modules/entries').init() wiki.lang = require('i18next') wiki.mark = require('./modules/markdown') // ---------------------------------------- -// Load modules +// Load local modules // ---------------------------------------- -const moment = require('moment') const Promise = require('bluebird') -const fs = Promise.promisifyAll(require('fs-extra')) -const klaw = require('klaw') -const Cron = require('cron').CronJob const i18nBackend = require('i18next-node-fs-backend') -const entryHelper = require('./helpers/entry') - // ---------------------------------------- // Localization Engine // ---------------------------------------- @@ -46,143 +43,21 @@ wiki.lang.use(i18nBackend).init({ }) // ---------------------------------------- -// Start Cron +// Start Queues // ---------------------------------------- -let job -let jobIsBusy = false -let jobUplWatchStarted = false - -wiki.db.onReady.then(() => { - return wiki.db.Entry.remove({}) -}).then(() => { - job = new Cron({ - cronTime: '0 */5 * * * *', - onTick: () => { - // Make sure we don't start two concurrent jobs - - if (jobIsBusy) { - wiki.logger.warn('Previous job has not completed gracefully or is still running! Skipping for now. (This is not normal, you should investigate)') - return - } - wiki.logger.info('Running all jobs...') - jobIsBusy = true - - // Prepare async job collector - - let jobs = [] - let repoPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo) - let dataPath = path.resolve(wiki.ROOTPATH, wiki.config.paths.data) - let uploadsTempPath = path.join(dataPath, 'temp-upload') - - // ---------------------------------------- - // REGULAR JOBS - // ---------------------------------------- - - //* **************************************** - // -> Sync with Git remote - //* **************************************** - - jobs.push(wiki.git.resync().then(() => { - // -> Stream all documents - - let cacheJobs = [] - let jobCbStreamDocsResolve = null - let jobCbStreamDocs = new Promise((resolve, reject) => { - jobCbStreamDocsResolve = resolve - }) - - klaw(repoPath).on('data', function (item) { - if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') { - let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path)) - let cachePath = entryHelper.getCachePath(entryPath) - - // -> Purge outdated cache - - cacheJobs.push( - fs.statAsync(cachePath).then((st) => { - return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active' - }).catch((err) => { - return (err.code !== 'EEXIST') ? err : 'new' - }).then((fileStatus) => { - // -> Delete expired cache file +const Bull = require('bull') +const autoload = require('auto-load') - if (fileStatus === 'expired') { - return fs.unlinkAsync(cachePath).return(fileStatus) - } +let queues = autoload(path.join(wiki.SERVERPATH, 'queues')) - return fileStatus - }).then((fileStatus) => { - // -> Update cache and search index - - if (fileStatus !== 'active') { - return global.entries.updateCache(entryPath).then(entry => { - process.send({ - action: 'searchAdd', - content: entry - }) - return true - }) - } - - return true - }) - ) - } - }).on('end', () => { - jobCbStreamDocsResolve(Promise.all(cacheJobs)) - }) - - return jobCbStreamDocs - })) - - //* **************************************** - // -> Clear failed temporary upload files - //* **************************************** - - jobs.push( - fs.readdirAsync(uploadsTempPath).then((ls) => { - let fifteenAgo = moment().subtract(15, 'minutes') - - return Promise.map(ls, (f) => { - return fs.statAsync(path.join(uploadsTempPath, f)).then((s) => { return { filename: f, stat: s } }) - }).filter((s) => { return s.stat.isFile() }).then((arrFiles) => { - return Promise.map(arrFiles, (f) => { - if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) { - return fs.unlinkAsync(path.join(uploadsTempPath, f.filename)) - } else { - return true - } - }) - }) - }) - ) - - // ---------------------------------------- - // Run - // ---------------------------------------- - - Promise.all(jobs).then(() => { - wiki.logger.info('All jobs completed successfully! Going to sleep for now.') - - if (!jobUplWatchStarted) { - jobUplWatchStarted = true - wiki.upl.initialScan().then(() => { - job.start() - }) - } - - return true - }).catch((err) => { - wiki.logger.error('One or more jobs have failed: ', err) - }).finally(() => { - jobIsBusy = false - }) - }, - start: false, - timeZone: 'UTC', - runOnInit: true - }) +Promise.join( + wiki.db.onReady + // wiki.upl.initialScan() +).then(() => { + for (let queueName in queues) { + new Bull(queueName, { redis: wiki.config.redis }).process(queues[queueName]) + } }) // ---------------------------------------- @@ -190,11 +65,6 @@ wiki.db.onReady.then(() => { // ---------------------------------------- process.on('disconnect', () => { - wiki.logger.warn('Lost connection to main server. Exiting...') - job.stop() + wiki.logger.warn('Lost connection to Master. Exiting...') process.exit() }) - -process.on('exit', () => { - job.stop() -}) diff --git a/yarn.lock b/yarn.lock index e52fcd68..534390bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1609,7 +1609,7 @@ cron-parser@^2.4.1: is-nan "^1.2.1" moment-timezone "^0.5.0" -cron@1.2.1, cron@~1.2.1: +cron@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/cron/-/cron-1.2.1.tgz#3a86c09b41b8f261ac863a7cc85ea4735857eab2" dependencies: From 2020e457cf5e7d14926f4f4d882c7505d352eb9f Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 30 Jul 2017 00:04:57 -0400 Subject: [PATCH 05/33] feat: modular auth + logging changes --- server/authentication/azure.js | 42 ++++++++++----------- server/authentication/facebook.js | 32 ++++++++-------- server/authentication/github.js | 32 ++++++++-------- server/authentication/google.js | 30 +++++++-------- server/authentication/ldap.js | 59 +++++++++++++++--------------- server/authentication/local.js | 44 +++++++++++----------- server/authentication/microsoft.js | 30 +++++++-------- server/authentication/slack.js | 30 +++++++-------- server/controllers/uploads.js | 3 ++ server/master.js | 6 +-- server/modules/auth.js | 28 +++++++++++--- server/modules/config.js | 11 ------ server/modules/db.js | 2 +- server/modules/disk.js | 4 +- server/modules/git.js | 6 +-- 15 files changed, 174 insertions(+), 185 deletions(-) diff --git a/server/authentication/azure.js b/server/authentication/azure.js index 1759aa9f..c54830ef 100644 --- a/server/authentication/azure.js +++ b/server/authentication/azure.js @@ -8,26 +8,24 @@ const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy -module.exports = (passport) => { - if (wiki.config.auth.azure && wiki.config.auth.azure.enabled) { - const jwt = require('jsonwebtoken') - passport.use('azure_ad_oauth2', - new AzureAdOAuth2Strategy({ - 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' - wiki.db.User.processProfile(waadProfile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } +module.exports = (passport, conf) => { + const jwt = require('jsonwebtoken') + passport.use('azure_ad_oauth2', + new AzureAdOAuth2Strategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL, + resource: conf.resource, + tenant: conf.tenant + }, (accessToken, refreshToken, params, profile, cb) => { + let waadProfile = jwt.decode(params.id_token) + waadProfile.id = waadProfile.oid + waadProfile.provider = 'azure' + wiki.db.User.processProfile(waadProfile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) } diff --git a/server/authentication/facebook.js b/server/authentication/facebook.js index db1c4ef9..1a1d3822 100644 --- a/server/authentication/facebook.js +++ b/server/authentication/facebook.js @@ -8,21 +8,19 @@ const FacebookStrategy = require('passport-facebook').Strategy -module.exports = (passport) => { - if (wiki.config.auth.facebook && wiki.config.auth.facebook.enabled) { - passport.use('facebook', - new FacebookStrategy({ - 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) { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } +module.exports = (passport, conf) => { + passport.use('facebook', + new FacebookStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL, + profileFields: ['id', 'displayName', 'email'] + }, function (accessToken, refreshToken, profile, cb) { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) } diff --git a/server/authentication/github.js b/server/authentication/github.js index c26df1b3..7c225e6a 100644 --- a/server/authentication/github.js +++ b/server/authentication/github.js @@ -8,21 +8,19 @@ const GitHubStrategy = require('passport-github2').Strategy -module.exports = (passport) => { - if (wiki.config.auth.github && wiki.config.auth.github.enabled) { - passport.use('github', - new GitHubStrategy({ - 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) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } +module.exports = (passport, conf) => { + passport.use('github', + new GitHubStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL, + scope: ['user:email'] + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) } diff --git a/server/authentication/google.js b/server/authentication/google.js index 12d51f2e..9531f4a8 100644 --- a/server/authentication/google.js +++ b/server/authentication/google.js @@ -8,20 +8,18 @@ const GoogleStrategy = require('passport-google-oauth20').Strategy -module.exports = (passport) => { - if (wiki.config.auth.google && wiki.config.auth.google.enabled) { - passport.use('google', - new GoogleStrategy({ - clientID: wiki.config.auth.google.clientId, - clientSecret: wiki.config.auth.google.clientSecret, - callbackURL: wiki.config.host + '/login/google/callback' - }, (accessToken, refreshToken, profile, cb) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } +module.exports = (passport, conf) => { + passport.use('google', + new GoogleStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) } diff --git a/server/authentication/ldap.js b/server/authentication/ldap.js index cc3ebf7c..0eb4ccbe 100644 --- a/server/authentication/ldap.js +++ b/server/authentication/ldap.js @@ -7,35 +7,34 @@ // ------------------------------------ const LdapStrategy = require('passport-ldapauth').Strategy +const fs = require('fs') -module.exports = (passport) => { - if (wiki.config.auth.ldap && wiki.config.auth.ldap.enabled) { - passport.use('ldapauth', - new LdapStrategy({ - server: { - 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: (wiki.config.auth.ldap.tlsEnabled) ? { - ca: [ - fs.readFileSync(wiki.config.auth.ldap.tlsCertPath) - ] - } : {} - }, - usernameField: 'email', - passReqToCallback: false - }, (profile, cb) => { - profile.provider = 'ldap' - profile.id = profile.dn - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } +module.exports = (passport, conf) => { + passport.use('ldapauth', + new LdapStrategy({ + server: { + url: conf.url, + bindDn: conf.bindDn, + bindCredentials: conf.bindCredentials, + searchBase: conf.searchBase, + searchFilter: conf.searchFilter, + searchAttributes: ['displayName', 'name', 'cn', 'mail'], + tlsOptions: (conf.tlsEnabled) ? { + ca: [ + fs.readFileSync(conf.tlsCertPath) + ] + } : {} + }, + usernameField: 'email', + passReqToCallback: false + }, (profile, cb) => { + profile.provider = 'ldap' + profile.id = profile.dn + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) } diff --git a/server/authentication/local.js b/server/authentication/local.js index 3af57126..ae00171b 100644 --- a/server/authentication/local.js +++ b/server/authentication/local.js @@ -8,27 +8,25 @@ const LocalStrategy = require('passport-local').Strategy -module.exports = (passport) => { - if (wiki.config.auth.local && wiki.config.auth.local.enabled) { - passport.use('local', - new LocalStrategy({ - usernameField: 'email', - passwordField: 'password' - }, (uEmail, uPassword, done) => { - wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => { - if (user) { - return user.validatePassword(uPassword).then(() => { - return done(null, user) || true - }).catch((err) => { - return done(err, null) - }) - } else { - return done(new Error('INVALID_LOGIN'), null) - } - }).catch((err) => { - done(err, null) - }) - } - )) - } +module.exports = (passport, conf) => { + passport.use('local', + new LocalStrategy({ + usernameField: 'email', + passwordField: 'password' + }, (uEmail, uPassword, done) => { + wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => { + if (user) { + return user.validatePassword(uPassword).then(() => { + return done(null, user) || true + }).catch((err) => { + return done(err, null) + }) + } else { + return done(new Error('INVALID_LOGIN'), null) + } + }).catch((err) => { + done(err, null) + }) + } + )) } diff --git a/server/authentication/microsoft.js b/server/authentication/microsoft.js index 1d39eb47..6ccd1b88 100644 --- a/server/authentication/microsoft.js +++ b/server/authentication/microsoft.js @@ -8,20 +8,18 @@ const WindowsLiveStrategy = require('passport-windowslive').Strategy -module.exports = (passport) => { - if (wiki.config.auth.microsoft && wiki.config.auth.microsoft.enabled) { - passport.use('windowslive', - new WindowsLiveStrategy({ - clientID: wiki.config.auth.microsoft.clientId, - clientSecret: wiki.config.auth.microsoft.clientSecret, - callbackURL: wiki.config.host + '/login/ms/callback' - }, function (accessToken, refreshToken, profile, cb) { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } +module.exports = (passport, conf) => { + passport.use('windowslive', + new WindowsLiveStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL + }, function (accessToken, refreshToken, profile, cb) { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) } diff --git a/server/authentication/slack.js b/server/authentication/slack.js index dcc8a7f2..778d6abf 100644 --- a/server/authentication/slack.js +++ b/server/authentication/slack.js @@ -8,20 +8,18 @@ const SlackStrategy = require('passport-slack').Strategy -module.exports = (passport) => { - if (wiki.config.auth.slack && wiki.config.auth.slack.enabled) { - passport.use('slack', - new SlackStrategy({ - clientID: wiki.config.auth.slack.clientId, - clientSecret: wiki.config.auth.slack.clientSecret, - callbackURL: wiki.config.host + '/login/slack/callback' - }, (accessToken, refreshToken, profile, cb) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) - } +module.exports = (passport, conf) => { + passport.use('slack', + new SlackStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) } diff --git a/server/controllers/uploads.js b/server/controllers/uploads.js index d7321c41..40b19e68 100644 --- a/server/controllers/uploads.js +++ b/server/controllers/uploads.js @@ -2,6 +2,9 @@ /* global wiki */ +module.exports = false +return + const express = require('express') const router = express.Router() diff --git a/server/master.js b/server/master.js index 12248ba4..0ce0bf19 100644 --- a/server/master.js +++ b/server/master.js @@ -147,7 +147,7 @@ module.exports = Promise.join( app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema })) app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' })) - app.use('/uploads', mw.auth, ctrl.uploads) + // app.use('/uploads', mw.auth, ctrl.uploads) app.use('/admin', mw.auth, ctrl.admin) app.use('/', mw.auth, ctrl.pages) @@ -173,7 +173,7 @@ module.exports = Promise.join( // Start HTTP server // ---------------------------------------- - wiki.logger.info('Starting HTTP/WS server on port ' + wiki.config.port + '...') + wiki.logger.info(`HTTP/WS Server on port: ${wiki.config.port}`) app.set('port', wiki.config.port) var server = http.createServer(app) @@ -199,7 +199,7 @@ module.exports = Promise.join( }) server.on('listening', () => { - wiki.logger.info('HTTP/WS server started successfully! [RUNNING]') + wiki.logger.info('HTTP/WS Server: RUNNING') }) // ---------------------------------------- diff --git a/server/modules/auth.js b/server/modules/auth.js index 3e96e730..45ee1b9e 100644 --- a/server/modules/auth.js +++ b/server/modules/auth.js @@ -2,9 +2,9 @@ /* global wiki */ -const fs = require('fs') +const _ = require('lodash') -module.exports = function (passport) { +module.exports = (passport) => { // Serialization user methods passport.serializeUser(function (user, done) { @@ -24,12 +24,28 @@ module.exports = function (passport) { }) }) - // Create users for first-time + // Load authentication strategies - return wiki.db.User.findOne({ provider: 'local', email: 'guest@example.com' }).then((c) => { - if (c < 1) { - // Create guest account + wiki.config.authStrategies = { + list: _.pickBy(wiki.config.auth, strategy => strategy.enabled), + socialEnabled: (_.chain(wiki.config.auth).omit('local').filter(['enabled', true]).value().length > 0) + } + + _.forOwn(wiki.config.authStrategies.list, (strategyConfig, strategyName) => { + strategyConfig.callbackURL = `${wiki.config.site.host}/login/${strategyName}/callback` + require(`../authentication/${strategyName}`)(passport, strategyConfig) + wiki.logger.info(`Authentication Provider ${_.upperFirst(strategyName)}: OK`) + }) + // Create Guest account for first-time + + return wiki.db.User.findOne({ + where: { + provider: 'local', + email: 'guest@example.com' + } + }).then((c) => { + if (c < 1) { return wiki.db.User.create({ provider: 'local', email: 'guest@example.com', diff --git a/server/modules/config.js b/server/modules/config.js index bb07c02f..da67d29f 100644 --- a/server/modules/config.js +++ b/server/modules/config.js @@ -57,17 +57,6 @@ module.exports = { // List authentication strategies wiki.config = appconfig wiki.data = appdata - - // List authentication strategies - - // appconfig.authStrategies = { - // list: _.filter(appconfig.auth, ['enabled', true]), - // socialEnabled: (_.chain(appconfig.auth).omit('local').filter(['enabled', true]).value().length > 0) - // } - // if (appconfig.authStrategies.list.length < 1) { - // console.error(new Error('You must enable at least 1 authentication strategy!')) - // process.exit(1) - // } }, /** diff --git a/server/modules/db.js b/server/modules/db.js index 36bbfadc..3654afd2 100644 --- a/server/modules/db.js +++ b/server/modules/db.js @@ -41,7 +41,7 @@ module.exports = { // Attempt to connect and authenticate to DB self.inst.authenticate().then(() => { - wiki.logger.info('Connected to PostgreSQL database.') + wiki.logger.info('Database (PostgreSQL) connection: OK') }).catch(err => { wiki.logger.error('Failed to connect to MongoDB instance.') return err diff --git a/server/modules/disk.js b/server/modules/disk.js index 88c54279..0fafcd68 100644 --- a/server/modules/disk.js +++ b/server/modules/disk.js @@ -94,8 +94,6 @@ module.exports = { * Creates a base directories (Synchronous). */ createBaseDirectories () { - wiki.logger.info('Checking data directories...') - try { fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data)) fs.emptyDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data)) @@ -117,7 +115,7 @@ module.exports = { wiki.logger.error(err) } - wiki.logger.info('Data and Repository directories are OK.') + wiki.logger.info('Disk Data Paths: OK') }, /** diff --git a/server/modules/git.js b/server/modules/git.js index 4c58a48f..dedd9b6b 100644 --- a/server/modules/git.js +++ b/server/modules/git.js @@ -71,8 +71,6 @@ module.exports = { _initRepo() { let self = this - wiki.logger.info('Checking Git repository...') - // -> Check if path is accessible return fs.mkdirAsync(self._repo.path).catch((err) => { @@ -92,7 +90,7 @@ module.exports = { }) }).then(() => { if (wiki.config.git === false) { - wiki.logger.info('Remote Git syncing is disabled. Not recommended!') + wiki.logger.warn('Remote Git syncing is disabled. Not recommended!') return Promise.resolve(true) } @@ -132,7 +130,7 @@ module.exports = { wiki.logger.error('Git remote error!') throw err }).then(() => { - wiki.logger.info('Git repository is OK.') + wiki.logger.info('Git Repository: OK') return true }) }, From 749766e9bd6c5375926cb3f319c93797592aa04b Mon Sep 17 00:00:00 2001 From: NGPixel Date: Wed, 2 Aug 2017 23:47:11 -0400 Subject: [PATCH 06/33] feat: queue handling --- config.sample.yml | 11 +- server/app/data.yml | 6 + server/index.js | 21 ++- server/master.js | 11 +- server/modules/auth.js | 144 ++++++++++---------- server/modules/config.js | 3 - server/modules/db.js | 32 ++++- server/modules/{entries.js => documents.js} | 2 +- server/modules/queue.js | 37 +++++ server/modules/redis.js | 6 +- server/queues/git-sync.js | 3 + server/queues/upl-clear-temp.js | 3 + server/worker.js | 101 +++++++------- 13 files changed, 236 insertions(+), 144 deletions(-) rename server/modules/{entries.js => documents.js} (99%) create mode 100644 server/modules/queue.js diff --git a/config.sample.yml b/config.sample.yml index a42a67ba..5421d5a8 100644 --- a/config.sample.yml +++ b/config.sample.yml @@ -42,6 +42,15 @@ redis: # --------------------------------------------------------------------- # Background Workers # --------------------------------------------------------------------- - # Leave 0 for auto based on CPU cores + workers: 0 + +# --------------------------------------------------------------------- +# High Availability +# --------------------------------------------------------------------- +# Read the docs BEFORE changing these settings! + +ha: + nodeuid: primary + readonly: false diff --git a/server/app/data.yml b/server/app/data.yml index 8ab67828..ded7b58a 100644 --- a/server/app/data.yml +++ b/server/app/data.yml @@ -21,6 +21,12 @@ defaults: db: 0 password: null workers: 0 + ha: + nodeuid: primary + readonly: false +queues: + - gitSync + - uplClearTemp authProviders: - local - microsoft diff --git a/server/index.js b/server/index.js index 24f65480..3f0007af 100644 --- a/server/index.js +++ b/server/index.js @@ -48,18 +48,27 @@ if (numWorkers > numCPUs) { } if (cluster.isMaster) { + wiki.logger.info('--------------------------') wiki.logger.info('Wiki.js is initializing...') + wiki.logger.info('--------------------------') - require('./master') + require('./master').then(() => { + // -> Create background workers + for (let i = 0; i < numWorkers; i++) { + cluster.fork() + } - for (let i = 0; i < numWorkers; i++) { - cluster.fork() - } + // -> Queue post-init tasks + + wiki.queue.uplClearTemp.add({}, { + repeat: { cron: '*/15 * * * *' } + }) + }) cluster.on('exit', (worker, code, signal) => { - wiki.logger.info(`Worker #${worker.id} died.`) + wiki.logger.info(`Background Worker #${worker.id} was terminated.`) }) } else { - wiki.logger.info(`Background Worker #${cluster.worker.id} is starting...`) + wiki.logger.info(`Background Worker #${cluster.worker.id} is initializing...`) require('./worker') } diff --git a/server/master.js b/server/master.js index 0ce0bf19..85754011 100644 --- a/server/master.js +++ b/server/master.js @@ -4,20 +4,23 @@ const Promise = require('bluebird') +wiki.redis = require('./modules/redis').init() +wiki.queue = require('./modules/queue').init() + module.exports = Promise.join( wiki.db.onReady, - wiki.configSvc.loadFromDb() + wiki.configSvc.loadFromDb(), + wiki.queue.clean() ).then(() => { // ---------------------------------------- // Load global modules // ---------------------------------------- wiki.disk = require('./modules/disk').init() - wiki.entries = require('./modules/entries').init() + wiki.docs = require('./modules/documents').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() @@ -75,7 +78,7 @@ module.exports = Promise.join( // Passport Authentication // ---------------------------------------- - require('./modules/auth')(passport) + require('./modules/auth').init(passport) wiki.rights = require('./modules/rights') // wiki.rights.init() diff --git a/server/modules/auth.js b/server/modules/auth.js index 45ee1b9e..2fd96206 100644 --- a/server/modules/auth.js +++ b/server/modules/auth.js @@ -4,87 +4,89 @@ const _ = require('lodash') -module.exports = (passport) => { +module.exports = { + init(passport) { // Serialization user methods - passport.serializeUser(function (user, done) { - done(null, user._id) - }) + passport.serializeUser(function (user, done) { + done(null, user._id) + }) - passport.deserializeUser(function (id, done) { - wiki.db.User.findById(id).then((user) => { - if (user) { - done(null, user) - } else { - done(new Error(wiki.lang.t('auth:errors:usernotfound')), null) - } - return true - }).catch((err) => { - done(err, null) + passport.deserializeUser(function (id, done) { + wiki.db.User.findById(id).then((user) => { + if (user) { + done(null, user) + } else { + done(new Error(wiki.lang.t('auth:errors:usernotfound')), null) + } + return true + }).catch((err) => { + done(err, null) + }) }) - }) - // Load authentication strategies + // Load authentication strategies - wiki.config.authStrategies = { - list: _.pickBy(wiki.config.auth, strategy => strategy.enabled), - socialEnabled: (_.chain(wiki.config.auth).omit('local').filter(['enabled', true]).value().length > 0) - } + wiki.config.authStrategies = { + list: _.pickBy(wiki.config.auth, strategy => strategy.enabled), + socialEnabled: (_.chain(wiki.config.auth).omit('local').filter(['enabled', true]).value().length > 0) + } - _.forOwn(wiki.config.authStrategies.list, (strategyConfig, strategyName) => { - strategyConfig.callbackURL = `${wiki.config.site.host}/login/${strategyName}/callback` - require(`../authentication/${strategyName}`)(passport, strategyConfig) - wiki.logger.info(`Authentication Provider ${_.upperFirst(strategyName)}: OK`) - }) + _.forOwn(wiki.config.authStrategies.list, (strategyConfig, strategyName) => { + strategyConfig.callbackURL = `${wiki.config.site.host}/login/${strategyName}/callback` + require(`../authentication/${strategyName}`)(passport, strategyConfig) + wiki.logger.info(`Authentication Provider ${_.upperFirst(strategyName)}: OK`) + }) - // Create Guest account for first-time + // Create Guest account for first-time - return wiki.db.User.findOne({ - where: { - provider: 'local', - email: 'guest@example.com' - } - }).then((c) => { - if (c < 1) { - return wiki.db.User.create({ + return wiki.db.User.findOne({ + where: { provider: 'local', - email: 'guest@example.com', - name: 'Guest', - password: '', - role: 'guest' - }).then(() => { - wiki.logger.info('[AUTH] Guest account created successfully!') - return true - }).catch((err) => { - wiki.logger.error('[AUTH] An error occured while creating guest account:') - wiki.logger.error(err) - return err - }) - } - }) + email: 'guest@example.com' + } + }).then((c) => { + if (c < 1) { + return wiki.db.User.create({ + provider: 'local', + email: 'guest@example.com', + name: 'Guest', + password: '', + role: 'guest' + }).then(() => { + wiki.logger.info('[AUTH] Guest account created successfully!') + return true + }).catch((err) => { + wiki.logger.error('[AUTH] An error occured while creating guest account:') + wiki.logger.error(err) + return err + }) + } + }) - // .then(() => { - // if (process.env.WIKI_JS_HEROKU) { - // return wiki.db.User.findOne({ provider: 'local', email: process.env.WIKI_ADMIN_EMAIL }).then((c) => { - // if (c < 1) { - // // Create root admin account (HEROKU ONLY) + // .then(() => { + // if (process.env.WIKI_JS_HEROKU) { + // 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 wiki.db.User.create({ - // provider: 'local', - // email: process.env.WIKI_ADMIN_EMAIL, - // name: 'Administrator', - // password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default) - // role: 'admin' - // }).then(() => { - // wiki.logger.info('[AUTH] Root admin account created successfully!') - // return true - // }).catch((err) => { - // wiki.logger.error('[AUTH] An error occured while creating root admin account:') - // wiki.logger.error(err) - // return err - // }) - // } else { return true } - // }) - // } else { return true } - // }) + // return wiki.db.User.create({ + // provider: 'local', + // email: process.env.WIKI_ADMIN_EMAIL, + // name: 'Administrator', + // password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default) + // role: 'admin' + // }).then(() => { + // wiki.logger.info('[AUTH] Root admin account created successfully!') + // return true + // }).catch((err) => { + // wiki.logger.error('[AUTH] An error occured while creating root admin account:') + // wiki.logger.error(err) + // return err + // }) + // } else { return true } + // }) + // } else { return true } + // }) + } } diff --git a/server/modules/config.js b/server/modules/config.js index da67d29f..334fba3c 100644 --- a/server/modules/config.js +++ b/server/modules/config.js @@ -13,9 +13,6 @@ module.exports = { /** * Load root config from disk - * - * @param {any} confPaths - * @returns */ init() { let confPaths = { diff --git a/server/modules/db.js b/server/modules/db.js index 3654afd2..f459039e 100644 --- a/server/modules/db.js +++ b/server/modules/db.js @@ -63,12 +63,32 @@ module.exports = { require(path.join(dbModelsPath, '_relations.js'))(self) - // Sync DB - - self.onReady = (wiki.IS_MASTER) ? self.inst.sync({ - force: false, - logging: false - }) : Promise.resolve() + // Set init tasks + + let initTasks = { + // -> Sync DB Schemas + syncSchemas() { + return self.inst.sync({ + force: false, + logging: false + }) + }, + // -> Set Connection App Name + setAppName() { + return self.inst.query(`set application_name = 'Wiki.js'`, { raw: true }) + } + } + + let initTasksQueue = (wiki.IS_MASTER) ? [ + initTasks.syncSchemas, + initTasks.setAppName + ] : [ + initTasks.setAppName + ] + + // Perform init tasks + + self.onReady = Promise.each(initTasksQueue, t => t()) return self } diff --git a/server/modules/entries.js b/server/modules/documents.js similarity index 99% rename from server/modules/entries.js rename to server/modules/documents.js index 802d0d6d..f89d6fab 100644 --- a/server/modules/entries.js +++ b/server/modules/documents.js @@ -10,7 +10,7 @@ const _ = require('lodash') const entryHelper = require('../helpers/entry') /** - * Entries Model + * Documents Model */ module.exports = { diff --git a/server/modules/queue.js b/server/modules/queue.js new file mode 100644 index 00000000..e7612ee3 --- /dev/null +++ b/server/modules/queue.js @@ -0,0 +1,37 @@ +'use strict' + +/* global wiki */ + +const Bull = require('bull') +const Promise = require('bluebird') + +module.exports = { + init() { + wiki.data.queues.forEach(queueName => { + this[queueName] = new Bull(queueName, { + prefix: `q-${wiki.config.ha.nodeuid}`, + redis: wiki.config.redis + }) + }) + return this + }, + clean() { + return Promise.each(wiki.data.queues, queueName => { + return new Promise((resolve, reject) => { + let keyStream = wiki.redis.scanStream({ + match: `q-${wiki.config.ha.nodeuid}:${queueName}:*` + }) + keyStream.on('data', resultKeys => { + if (resultKeys.length > 0) { + wiki.redis.del(resultKeys) + } + }) + keyStream.on('end', resolve) + }) + }).then(() => { + wiki.logger.info('Purging old queue jobs: OK') + }).catch(err => { + wiki.logger.error(err) + }) + } +} diff --git a/server/modules/redis.js b/server/modules/redis.js index 284c93d3..6eb7999b 100644 --- a/server/modules/redis.js +++ b/server/modules/redis.js @@ -19,7 +19,11 @@ module.exports = { */ init() { if (isPlainObject(wiki.config.redis)) { - return new Redis(wiki.config.redis) + let red = new Redis(wiki.config.redis) + red.on('ready', () => { + wiki.logger.info('Redis connection: OK') + }) + return red } else { wiki.logger.error('Invalid Redis configuration!') process.exit(1) diff --git a/server/queues/git-sync.js b/server/queues/git-sync.js index 9f9b1f57..ab4fefae 100644 --- a/server/queues/git-sync.js +++ b/server/queues/git-sync.js @@ -61,5 +61,8 @@ module.exports = (job, done) => { }) return jobCbStreamDocs + }).then(() => { + wiki.logger.info('Git remote repository sync: DONE') + return true }) } diff --git a/server/queues/upl-clear-temp.js b/server/queues/upl-clear-temp.js index 2162aae4..00e2bf1e 100644 --- a/server/queues/upl-clear-temp.js +++ b/server/queues/upl-clear-temp.js @@ -22,5 +22,8 @@ module.exports = (job, done) => { } }) }) + }).then(() => { + wiki.logger.info('Purging temporary upload files: DONE') + return true }) } diff --git a/server/worker.js b/server/worker.js index f64deca5..0028f755 100644 --- a/server/worker.js +++ b/server/worker.js @@ -2,69 +2,68 @@ /* global wiki */ -const path = require('path') - -wiki.REPOPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo) -wiki.DATAPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.data) -wiki.UPLTEMPPATH = path.join(wiki.DATAPATH, 'temp-upload') +const Promise = require('bluebird') -// ---------------------------------------- -// Load global modules -// ---------------------------------------- +module.exports = Promise.join( + wiki.db.onReady, + wiki.configSvc.loadFromDb(['features', 'git', 'logging', 'site', 'uploads']) +).then(() => { + const path = require('path') -// wiki.upl = require('./modules/uploads-agent').init() -// wiki.git = require('./modules/git').init() -// wiki.entries = require('./modules/entries').init() -wiki.lang = require('i18next') -wiki.mark = require('./modules/markdown') + wiki.REPOPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.repo) + wiki.DATAPATH = path.resolve(wiki.ROOTPATH, wiki.config.paths.data) + wiki.UPLTEMPPATH = path.join(wiki.DATAPATH, 'temp-upload') -// ---------------------------------------- -// Load local modules -// ---------------------------------------- + // ---------------------------------------- + // Load global modules + // ---------------------------------------- -const Promise = require('bluebird') -const i18nBackend = require('i18next-node-fs-backend') + // wiki.upl = require('./modules/uploads-agent').init() + // wiki.git = require('./modules/git').init() + // wiki.entries = require('./modules/entries').init() + wiki.lang = require('i18next') + wiki.mark = require('./modules/markdown') -// ---------------------------------------- -// Localization Engine -// ---------------------------------------- + // ---------------------------------------- + // Localization Engine + // ---------------------------------------- -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') - } -}) + const i18nBackend = require('i18next-node-fs-backend') + 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') + } + }) -// ---------------------------------------- -// Start Queues -// ---------------------------------------- + // ---------------------------------------- + // Start Queues + // ---------------------------------------- -const Bull = require('bull') -const autoload = require('auto-load') + const Bull = require('bull') + const autoload = require('auto-load') -let queues = autoload(path.join(wiki.SERVERPATH, 'queues')) + let queues = autoload(path.join(wiki.SERVERPATH, 'queues')) -Promise.join( - wiki.db.onReady - // wiki.upl.initialScan() -).then(() => { for (let queueName in queues) { - new Bull(queueName, { redis: wiki.config.redis }).process(queues[queueName]) + new Bull(queueName, { + prefix: `q-${wiki.config.ha.nodeuid}`, + redis: wiki.config.redis + }).process(queues[queueName]) } -}) -// ---------------------------------------- -// Shutdown gracefully -// ---------------------------------------- + // ---------------------------------------- + // Shutdown gracefully + // ---------------------------------------- -process.on('disconnect', () => { - wiki.logger.warn('Lost connection to Master. Exiting...') - process.exit() + process.on('disconnect', () => { + wiki.logger.warn('Lost connection to Master. Exiting...') + process.exit() + }) }) From 62067caa6295b6ccbe8417e0037da47cc72da248 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 6 Aug 2017 11:09:39 -0400 Subject: [PATCH 07/33] refactor: remove npm install method --- npm/README.md | 14 -------------- npm/install.js | 25 ------------------------- npm/package.json | 32 -------------------------------- 3 files changed, 71 deletions(-) delete mode 100644 npm/README.md delete mode 100644 npm/install.js delete mode 100644 npm/package.json diff --git a/npm/README.md b/npm/README.md deleted file mode 100644 index d482407e..00000000 --- a/npm/README.md +++ /dev/null @@ -1,14 +0,0 @@ -![Wiki.js](https://raw.githubusercontent.com/Requarks/wiki-site/1.0/assets/images/logo.png) - -# Wiki.js - -[![npm](https://img.shields.io/npm/v/wiki.js.svg?style=flat-square)](https://github.com/Requarks) -[![Release](https://img.shields.io/github/release/Requarks/wiki.svg?style=flat-square&maxAge=3600)](https://github.com/Requarks/wiki/releases) -[![License](https://img.shields.io/badge/license-AGPLv3-blue.svg?style=flat-square)](https://github.com/requarks/wiki/blob/master/LICENSE) - -This npm package is an installer for Wiki.js. -For information about Wiki.js, including detailed installation steps, read the following links: - -- [Official Website](https://wiki.js.org/) -- [Installation Guide](https://wiki.js.org/get-started.html) -- [GitHub Repository](https://github.com/Requarks/wiki) diff --git a/npm/install.js b/npm/install.js deleted file mode 100644 index cd0a0511..00000000 --- a/npm/install.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -// ===================================================== -// Wiki.js -// Installation Script -// ===================================================== - -const path = require('path') -const spawn = require('child_process').spawn -const installDir = path.resolve(__dirname, '../..') -const cmd = (process.platform !== 'win32') - ? 'curl -s -S -o- https://wiki.js.org/install.sh | bash' - : `PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://wiki.js.org/install.ps1'))"` - -console.info(`Executing installation script for ${process.platform} platform...`) - -let inst = spawn(cmd, [], { - cwd: installDir, - env: process.env, - shell: true, - stdio: 'inherit', - detached: true -}) - -inst.unref() diff --git a/npm/package.json b/npm/package.json deleted file mode 100644 index 2098e56c..00000000 --- a/npm/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "wiki.js", - "version": "1.0.5-rev.1", - "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown", - "main": "install.js", - "scripts": { - "test": "exit 1", - "postinstall": "node install.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Requarks/wiki.git" - }, - "keywords": [ - "wiki", - "wikis", - "wikijs", - "wiki.js", - "wiki-js", - "docs", - "documentation", - "markdown", - "guides" - ], - "author": "Nicolas Giard", - "license": "AGPL-3.0", - "bugs": { - "url": "https://github.com/Requarks/wiki/issues" - }, - "homepage": "https://github.com/Requarks/wiki#readme", - "dependencies": {} -} From 437b88bf5817a6fdcb2cc64014e908e1687403bc Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 6 Aug 2017 21:05:10 -0400 Subject: [PATCH 08/33] feat: GraphQL schema --- package.json | 1 + server/index.js | 6 +- server/models/_relations.js | 1 + server/modules/graphql.js | 75 ++++------------ server/schemas/resolvers-group.js | 14 +++ server/schemas/resolvers-user.js | 14 +++ server/schemas/types.graphql | 136 ++++++++++++++++++++++++++++++ yarn.lock | 14 +++ 8 files changed, 201 insertions(+), 60 deletions(-) create mode 100644 server/schemas/resolvers-group.js create mode 100644 server/schemas/resolvers-user.js create mode 100644 server/schemas/types.graphql diff --git a/package.json b/package.json index 06f4fbec..63607b2d 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "fs-extra": "~4.0.0", "git-wrapper2-promise": "~0.2.9", "graphql": "~0.10.5", + "graphql-tools": "/home/nick1.1.0", "highlight.js": "~9.12.0", "i18next": "~8.4.3", "i18next-express-middleware": "~1.0.5", diff --git a/server/index.js b/server/index.js index 3f0007af..30ea6e2c 100644 --- a/server/index.js +++ b/server/index.js @@ -48,9 +48,9 @@ if (numWorkers > numCPUs) { } if (cluster.isMaster) { - wiki.logger.info('--------------------------') - wiki.logger.info('Wiki.js is initializing...') - wiki.logger.info('--------------------------') + wiki.logger.info('=======================================') + wiki.logger.info('= Wiki.js =============================') + wiki.logger.info('=======================================') require('./master').then(() => { // -> Create background workers diff --git a/server/models/_relations.js b/server/models/_relations.js index 7a851396..73436762 100644 --- a/server/models/_relations.js +++ b/server/models/_relations.js @@ -5,6 +5,7 @@ */ module.exports = db => { db.User.belongsToMany(db.Group, { through: 'userGroups' }) + db.Group.belongsToMany(db.User, { through: 'userGroups' }) db.Group.hasMany(db.Right, { as: 'groupRights' }) db.Document.hasMany(db.Tag, { as: 'documentTags' }) db.File.belongsTo(db.Folder) diff --git a/server/modules/graphql.js b/server/modules/graphql.js index 4de7a8c7..d40b6d04 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -2,66 +2,27 @@ /* global wiki */ -const gql = require('graphql') +const gqlTools = require('graphql-tools') +const fs = require('fs') +const path = require('path') -const User = new gql.GraphQLObjectType({ - name: 'User', - description: 'A User', - fields() { - return { - id: { - type: gql.GraphQLInt, - resolve(usr) { - return usr.id - } - }, - email: { - type: gql.GraphQLString, - resolve(usr) { - return usr.email - } - }, - provider: { - type: gql.GraphQLString, - resolve(usr) { - return usr.provider - } - }, - providerId: { - type: gql.GraphQLString, - resolve(usr) { - return usr.providerId - } - } - } - } -}) +const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8') -const Query = new gql.GraphQLObjectType({ - name: 'Query', - description: 'Root Query', - fields() { - return { - users: { - type: new gql.GraphQLList(User), - args: { - id: { - type: gql.GraphQLInt - }, - email: { - type: gql.GraphQLString - } - }, - resolve(root, args) { - return wiki.db.User.findAll({ where: args }) - } - } - } - } -}) +const GroupResolvers = require('../schemas/resolvers-group') +const UserResolvers = require('../schemas/resolvers-user') + +const resolvers = { + Query: { + groups: GroupResolvers.Query, + users: UserResolvers.Query + }, + Group: GroupResolvers.Type, + User: UserResolvers.Type +} -const Schema = new gql.GraphQLSchema({ - query: Query +const Schema = gqlTools.makeExecutableSchema({ + typeDefs, + resolvers }) module.exports = Schema diff --git a/server/schemas/resolvers-group.js b/server/schemas/resolvers-group.js new file mode 100644 index 00000000..bde68195 --- /dev/null +++ b/server/schemas/resolvers-group.js @@ -0,0 +1,14 @@ +'use strict' + +/* global wiki */ + +module.exports = { + Query(obj, args, context, info) { + return wiki.db.Group.findAll({ where: args }) + }, + Type: { + users(grp) { + return grp.getUsers() + } + } +} diff --git a/server/schemas/resolvers-user.js b/server/schemas/resolvers-user.js new file mode 100644 index 00000000..d7a876fd --- /dev/null +++ b/server/schemas/resolvers-user.js @@ -0,0 +1,14 @@ +'use strict' + +/* global wiki */ + +module.exports = { + Query(obj, args, context, info) { + return wiki.db.User.findAll({ where: args }) + }, + Type: { + groups(usr) { + return usr.getGroups() + } + } +} diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql new file mode 100644 index 00000000..90722ddc --- /dev/null +++ b/server/schemas/types.graphql @@ -0,0 +1,136 @@ +# SCALARS + +scalar Date + +# ENUMS + +enum UserRole { + guest + user + admin +} + +enum FileType { + binary + image +} + +enum RightRole { + read + write + manage +} + +# INTERFACES + +interface Base { + id: Int! + createdOn: Date + updatedOn: Date +} + +# TYPES + +type Comment implements Base { + id: Int! + createdOn: Date + updatedOn: Date + content: String + document: Document! + author: User! +} + +type Document implements Base { + id: Int! + createdOn: Date + updatedOn: Date + path: String! + title: String! + subtitle: String + parentPath: String + parentTitle: String + isDirectory: Boolean! + isEntry: Boolean! + searchContent: String + tags: [Tag] +} + +type File implements Base { + id: Int! + createdOn: Date + updatedOn: Date + category: FileType! + mime: String! + extra: String + filename: String! + basename: String! + filesize: Int! + folder: Folder +} + +type Folder implements Base { + id: Int! + createdOn: Date + updatedOn: Date + name: String! +} + +type Group implements Base { + id: Int! + createdOn: Date + updatedOn: Date + name: String! + users: [User] + rights: [Right] +} + +type Right implements Base { + id: Int! + createdOn: Date + updatedOn: Date + path: String! + role: RightRole! + exact: Boolean! + allow: Boolean! +} + +type Setting implements Base { + id: Int! + createdOn: Date + updatedOn: Date + key: String! + config: String! +} + +type Tag implements Base { + id: Int! + createdOn: Date + updatedOn: Date + key: String! +} + +type User implements Base { + id: Int! + createdOn: Date + updatedOn: Date + email: String! + provider: String + providerId: String + name: String + role: UserRole! + groups: [Group] +} + +# QUERY + +type Query { + comments(id: Int): [Comment] + documents(id: Int, path: String): [Document] + files(id: Int): [File] + folders(id: Int, name: String): [Folder] + groups(id: Int, name: String): [Group] + rights(id: Int): [Right] + settings(key: String): [Setting] + tags(key: String): [Tag] + users(id: Int, email: String, provider: String, providerId: String, role: UserRole): [User] +} diff --git a/yarn.lock b/yarn.lock index 534390bc..d6f8684e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1794,6 +1794,10 @@ depd@1.1.0, depd@^1.1.0, depd@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" +deprecated-decorator@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37" + destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" @@ -2926,6 +2930,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +graphql-tools@/home/nick1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.1.0.tgz#8d86ea6997b0dea3089b62dc655e47146a663ebb" + dependencies: + deprecated-decorator "^0.1.6" + lodash "^4.3.0" + uuid "^3.0.1" + optionalDependencies: + "@types/graphql" "^0.9.0" + graphql@~0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" From 7f955707b7c0b32b63b668983667ba77d850e8f5 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 6 Aug 2017 21:14:20 -0400 Subject: [PATCH 09/33] chore: updated dependencies --- .npmrc | 3 +- .yarnrc | 3 +- package.json | 254 +++++++++--------- yarn.lock | 711 ++++++++++++++++++++++++++++++--------------------- 4 files changed, 544 insertions(+), 427 deletions(-) diff --git a/.npmrc b/.npmrc index 22b81d18..6d1bedf0 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ -save-prefix = "~" +save-exact = true +save-prefix = "" diff --git a/.yarnrc b/.yarnrc index 95888f66..d60dfee7 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1 +1,2 @@ -save-prefix "~" +save-exact true +save-prefix "" diff --git a/package.json b/package.json index 63607b2d..0d54a593 100644 --- a/package.json +++ b/package.json @@ -37,139 +37,139 @@ "node": ">=6.11.1" }, "dependencies": { - "apollo-server-express": "~1.0.4", - "auto-load": "~3.0.0", - "axios": "~0.16.2", - "bcryptjs-then": "~1.0.1", - "bluebird": "~3.5.0", - "body-parser": "~1.17.2", - "bull": "/home/nick3.0.0-rc.4", - "bunyan": "~1.8.10", - "cheerio": "~1.0.0-rc.2", - "child-process-promise": "~2.2.1", - "chokidar": "~1.7.0", - "compression": "~1.7.0", - "connect-flash": "~0.1.1", - "connect-redis": "~3.3.0", - "cookie-parser": "~1.4.3", - "diff2html": "~2.3.0", - "execa": "~0.7.0", - "express": "~4.15.3", + "apollo-server-express": "1.0.5", + "auto-load": "3.0.0", + "axios": "0.16.2", + "bcryptjs-then": "1.0.1", + "bluebird": "3.5.0", + "body-parser": "1.17.2", + "bull": "3.0.0-rc.4", + "bunyan": "1.8.12", + "cheerio": "1.0.0-rc.2", + "child-process-promise": "2.2.1", + "chokidar": "1.7.0", + "compression": "1.7.0", + "connect-flash": "0.1.1", + "connect-redis": "3.3.0", + "cookie-parser": "1.4.3", + "diff2html": "2.3.0", + "execa": "0.8.0", + "express": "4.15.3", "express-brute": "1.0.1", - "express-brute-redis": "~0.0.1", - "express-session": "~1.15.3", - "file-type": "~5.2.0", - "filesize.js": "~1.0.2", - "follow-redirects": "~1.2.4", - "fs-extra": "~4.0.0", - "git-wrapper2-promise": "~0.2.9", - "graphql": "~0.10.5", - "graphql-tools": "/home/nick1.1.0", - "highlight.js": "~9.12.0", - "i18next": "~8.4.3", - "i18next-express-middleware": "~1.0.5", - "i18next-node-fs-backend": "~1.0.0", - "image-size": "~0.6.0", - "ioredis": "~3.1.1", - "jimp": "~0.2.28", - "js-yaml": "~3.9.0", - "jsonwebtoken": "~7.4.1", - "klaw": "~2.0.0", - "levelup": "~1.3.8", - "lodash": "~4.17.4", - "markdown-it": "~8.3.1", - "markdown-it-abbr": "~1.0.4", - "markdown-it-anchor": "~4.0.0", - "markdown-it-attrs": "~0.9.0", - "markdown-it-emoji": "~1.4.0", - "markdown-it-expand-tabs": "~1.0.12", + "express-brute-redis": "0.0.1", + "express-session": "1.15.5", + "file-type": "5.2.0", + "filesize.js": "1.0.2", + "follow-redirects": "1.2.4", + "fs-extra": "4.0.1", + "git-wrapper2-promise": "0.2.9", + "graphql": "0.10.5", + "graphql-tools": "1.1.0", + "highlight.js": "9.12.0", + "i18next": "8.4.3", + "i18next-express-middleware": "1.0.5", + "i18next-node-fs-backend": "1.0.0", + "image-size": "0.6.1", + "ioredis": "3.1.2", + "jimp": "0.2.28", + "js-yaml": "3.9.1", + "jsonwebtoken": "7.4.2", + "klaw": "2.0.0", + "levelup": "1.3.9", + "lodash": "4.17.4", + "markdown-it": "8.3.2", + "markdown-it-abbr": "1.0.4", + "markdown-it-anchor": "4.0.0", + "markdown-it-attrs": "0.9.0", + "markdown-it-emoji": "1.4.0", + "markdown-it-expand-tabs": "1.0.12", "markdown-it-external-links": "0.0.6", - "markdown-it-footnote": "~3.0.1", - "markdown-it-mathjax": "~2.0.0", - "markdown-it-task-lists": "~2.0.1", - "mathjax-node": "~1.1.0", - "memdown": "~1.2.4", - "mime-types": "~2.1.15", - "moment": "~2.18.1", - "moment-timezone": "~0.5.13", - "multer": "~1.3.0", - "node-2fa": "~1.1.2", - "node-graceful": "~0.2.3", - "ora": "~1.3.0", - "passport": "~0.3.2", + "markdown-it-footnote": "3.0.1", + "markdown-it-mathjax": "2.0.0", + "markdown-it-task-lists": "2.0.1", + "mathjax-node": "1.1.0", + "memdown": "1.2.4", + "mime-types": "2.1.16", + "moment": "2.18.1", + "moment-timezone": "0.5.13", + "multer": "1.3.0", + "node-2fa": "1.1.2", + "node-graceful": "0.2.3", + "ora": "1.3.0", + "passport": "0.3.2", "passport-azure-ad-oauth2": "0.0.4", - "passport-facebook": "~2.1.1", - "passport-github2": "~0.1.10", - "passport-google-oauth20": "~1.0.0", - "passport-ldapauth": "~2.0.0", - "passport-local": "~1.0.0", + "passport-facebook": "2.1.1", + "passport-github2": "0.1.10", + "passport-google-oauth20": "1.0.0", + "passport-ldapauth": "2.0.0", + "passport-local": "1.0.0", "passport-slack": "0.0.7", - "passport-windowslive": "~1.0.2", - "passport.socketio": "~3.7.0", - "pg": "~7.0.2", - "pg-hstore": "~2.3.2", - "pg-promise": "~6.3.5", - "pm2": "~2.6.1", - "pug": "~2.0.0-rc.2", - "read-chunk": "~2.0.0", - "remove-markdown": "~0.2.0", - "request": "~2.81.0", - "search-index-adder": "~0.3.9", - "search-index-searcher": "~0.2.10", - "semver": "~5.3.0", - "sequelize": "~4.4.2", - "serve-favicon": "~2.4.3", - "simplemde": "~1.11.2", - "socket.io": "~2.0.2", - "stopword": "~0.1.6", - "stream-to-promise": "~2.2.0", - "tar": "~3.1.5", - "through2": "~2.0.3", - "validator": "~8.0.0", - "validator-as-promised": "~1.0.2", - "winston": "~2.3.1", - "yargs": "~8.0.1" + "passport-windowslive": "1.0.2", + "passport.socketio": "3.7.0", + "pg": "7.1.0", + "pg-hstore": "2.3.2", + "pg-promise": "6.3.7", + "pm2": "2.6.1", + "pug": "2.0.0-rc.3", + "read-chunk": "2.1.0", + "remove-markdown": "0.2.1", + "request": "2.81.0", + "search-index-adder": "0.3.9", + "search-index-searcher": "0.2.10", + "semver": "5.4.1", + "sequelize": "4.4.2", + "serve-favicon": "2.4.3", + "simplemde": "1.11.2", + "socket.io": "2.0.3", + "stopword": "0.1.6", + "stream-to-promise": "2.2.0", + "tar": "3.1.9", + "through2": "2.0.3", + "validator": "8.0.0", + "validator-as-promised": "1.0.2", + "winston": "2.3.1", + "yargs": "8.0.2" }, "devDependencies": { - "@glimpse/glimpse": "~0.22.13", - "@panter/vue-i18next": "~0.5.0", - "babel-cli": "~6.24.1", - "babel-jest": "~20.0.3", - "babel-plugin-transform-object-assign": "~6.22.0", - "babel-preset-es2015": "~6.24.1", - "brace": "~0.10.0", - "colors": "~1.1.2", - "consolidate": "~0.14.5", - "eslint": "~4.3.0", - "eslint-config-standard": "~10.2.1", - "eslint-plugin-import": "~2.7.0", - "eslint-plugin-node": "~5.1.0", - "eslint-plugin-promise": "~3.5.0", - "eslint-plugin-standard": "~3.0.1", - "fuse-box": "~2.2.1", - "i18next-xhr-backend": "~1.4.2", - "jest": "~20.0.4", - "jquery": "~3.2.1", - "jquery-contextmenu": "~2.5.0", - "jquery-simple-upload": "~1.0.0", - "jquery-smooth-scroll": "~2.2.0", - "jquery-sticky": "~1.0.4", - "lodash-cli": "~4.17.4", - "lodash-es": "~4.17.4", - "node-sass": "~4.5.3", - "nodemon": "~1.11.0", - "pug-lint": "~2.4.0", - "twemoji-awesome": "~1.0.6", - "typescript": "~2.4.1", - "uglify-es": "~3.0.24", - "vee-validate": "~2.0.0-rc.6", - "vue": "~2.4.2", - "vue-clipboards": "~1.0.2", - "vue-lodash": "~1.0.3", - "vue-resource": "~1.3.4", - "vue-template-compiler": "~2.4.2", - "vue-template-es2015-compiler": "~1.5.3", - "vuex": "~2.3.1" + "@glimpse/glimpse": "0.22.15", + "@panter/vue-i18next": "0.5.1", + "babel-cli": "6.24.1", + "babel-jest": "20.0.3", + "babel-plugin-transform-object-assign": "6.22.0", + "babel-preset-es2015": "6.24.1", + "brace": "0.10.0", + "colors": "1.1.2", + "consolidate": "0.14.5", + "eslint": "4.4.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-node": "5.1.1", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", + "fuse-box": "2.2.1", + "i18next-xhr-backend": "1.4.2", + "jest": "20.0.4", + "jquery": "3.2.1", + "jquery-contextmenu": "2.5.0", + "jquery-simple-upload": "1.0.0", + "jquery-smooth-scroll": "2.2.0", + "jquery-sticky": "1.0.4", + "lodash-cli": "4.17.4", + "lodash-es": "4.17.4", + "node-sass": "4.5.3", + "nodemon": "1.11.0", + "pug-lint": "2.4.0", + "twemoji-awesome": "1.0.6", + "typescript": "2.4.2", + "uglify-es": "3.0.27", + "vee-validate": "2.0.0-rc.8", + "vue": "2.4.2", + "vue-clipboards": "1.1.0", + "vue-lodash": "1.0.3", + "vue-resource": "1.3.4", + "vue-template-compiler": "2.4.2", + "vue-template-es2015-compiler": "1.5.3", + "vuex": "2.3.1" }, "jest": { "collectCoverage": false, diff --git a/yarn.lock b/yarn.lock index d6f8684e..55ea2d98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,15 +2,16 @@ # yarn lockfile v1 -"@glimpse/glimpse-agent-node@0.22.13": - version "0.22.13" - resolved "https://registry.yarnpkg.com/@glimpse/glimpse-agent-node/-/glimpse-agent-node-0.22.13.tgz#5d03dfbdc22cedfa69732db79ddc6642d4aac593" +"@glimpse/glimpse-agent-node@0.22.15": + version "0.22.15" + resolved "https://registry.yarnpkg.com/@glimpse/glimpse-agent-node/-/glimpse-agent-node-0.22.15.tgz#93075fc56a234f716ed37dc8743be3f58121cfb2" dependencies: - "@glimpse/glimpse-common" "0.22.13" + "@glimpse/glimpse-common" "0.22.15" config-chain "^1.1.10" continuation-local-storage "^3.1.4" cookie "^0.2.3" dicer "^0.2.5" + escape-html "^1.0.3" htmlparser2 "^3.9.1" lodash "^4.3.0" moment "^2.16.1" @@ -23,9 +24,9 @@ uuid "^2.0.2" zone.js "^0.8.10" -"@glimpse/glimpse-common@0.22.13": - version "0.22.13" - resolved "https://registry.yarnpkg.com/@glimpse/glimpse-common/-/glimpse-common-0.22.13.tgz#48020a55638ea9c702104748f28155f08f7313af" +"@glimpse/glimpse-common@0.22.15": + version "0.22.15" + resolved "https://registry.yarnpkg.com/@glimpse/glimpse-common/-/glimpse-common-0.22.15.tgz#0e71aa973e07b4131548b4ad905189cff003510c" dependencies: applicationinsights "^0.19.0" chalk "^1.1.3" @@ -34,11 +35,11 @@ semver "^5.3.0" uuid "^2.0.2" -"@glimpse/glimpse-server@0.22.13": - version "0.22.13" - resolved "https://registry.yarnpkg.com/@glimpse/glimpse-server/-/glimpse-server-0.22.13.tgz#e4c25391caf9b1db6606f94cb66c96d9c49def24" +"@glimpse/glimpse-server@0.22.15": + version "0.22.15" + resolved "https://registry.yarnpkg.com/@glimpse/glimpse-server/-/glimpse-server-0.22.15.tgz#21025baa1d370921aad59f1f7e3e7c80abe269b5" dependencies: - "@glimpse/glimpse-common" "0.22.13" + "@glimpse/glimpse-common" "0.22.15" body-parser "^1.14.2" cors "^2.7.1" crc "^3.4.0" @@ -47,15 +48,17 @@ lru-cache "^4.0.0" moment "^2.16.1" -"@glimpse/glimpse@~0.22.13": - version "0.22.13" - resolved "https://registry.yarnpkg.com/@glimpse/glimpse/-/glimpse-0.22.13.tgz#bfc9a516ce5f620c5ebc772445f47c98af54f114" +"@glimpse/glimpse@0.22.15": + version "0.22.15" + resolved "https://registry.yarnpkg.com/@glimpse/glimpse/-/glimpse-0.22.15.tgz#593adafc9173bafa6aa6dab301575b9ce88e6ece" dependencies: - "@glimpse/glimpse-agent-node" "0.22.13" - "@glimpse/glimpse-server" "0.22.13" + "@glimpse/glimpse-agent-node" "0.22.15" + "@glimpse/glimpse-server" "0.22.15" + command-line-args "^4.0.6" + command-line-usage "^4.0.0" lodash "^4.15.0" -"@panter/vue-i18next@~0.5.0": +"@panter/vue-i18next@0.5.1": version "0.5.1" resolved "https://registry.yarnpkg.com/@panter/vue-i18next/-/vue-i18next-0.5.1.tgz#714bbeb62c25850231f2681ad11142d3c6e3c645" @@ -198,7 +201,7 @@ acorn@^4.0.1, acorn@^4.0.4, acorn@~4.0.2: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" -acorn@^5.0.1, acorn@^5.0.3: +acorn@^5.0.3, acorn@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75" @@ -255,6 +258,12 @@ amp@0.3.1, amp@~0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/amp/-/amp-0.3.1.tgz#6adf8d58a74f361e82c1fa8d389c079e139fc47d" +ansi-escape-sequences@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-escape-sequences/-/ansi-escape-sequences-3.0.0.tgz#1c18394b6af9b76ff9a63509fa497669fd2ce53e" + dependencies: + array-back "^1.0.3" + ansi-escapes@^1.1.0, ansi-escapes@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -306,19 +315,19 @@ apollo-server-core@^1.0.2: optionalDependencies: "@types/graphql" "^0.9.0" -apollo-server-express@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.0.4.tgz#fad6045493d818b09ad4610faa389768386a68b6" +apollo-server-express@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.0.5.tgz#4475684462a9f530f1d2630112ed45295e98dcf1" dependencies: apollo-server-core "^1.0.2" - apollo-server-module-graphiql "^1.0.4" + apollo-server-module-graphiql "^1.0.5" optionalDependencies: "@types/express" "^4.0.35" "@types/graphql" "^0.9.1" -apollo-server-module-graphiql@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.0.4.tgz#d6db21a8c60f052649124da5cde1d88dab702319" +apollo-server-module-graphiql@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.0.5.tgz#31639acb1dc4bd7e2edb334cf619f84ebff600a6" app-root-path@^1.3.0: version "1.4.0" @@ -371,6 +380,12 @@ arr-flatten@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + dependencies: + typical "^2.6.0" + array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -462,7 +477,7 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -auto-load@~3.0.0: +auto-load@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/auto-load/-/auto-load-3.0.0.tgz#f3c91d15120a32c89524b420d7283584c72088aa" @@ -474,14 +489,14 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -axios@~0.16.2: +axios@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d" dependencies: follow-redirects "^1.2.3" is-buffer "^1.1.5" -babel-cli@~6.24.1: +babel-cli@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.24.1.tgz#207cd705bba61489b2ea41b5312341cf6aca2283" dependencies: @@ -622,7 +637,7 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@^20.0.3, babel-jest@~20.0.3: +babel-jest@20.0.3, babel-jest@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-20.0.3.tgz#e4a03b13dc10389e140fc645d09ffc4ced301671" dependencies: @@ -822,7 +837,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.24.1: babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-object-assign@~6.22.0: +babel-plugin-transform-object-assign@6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba" dependencies: @@ -849,7 +864,7 @@ babel-polyfill@6.23.0, babel-polyfill@^6.23.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-preset-es2015@~6.24.1: +babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" dependencies: @@ -983,7 +998,7 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bcryptjs-then@~1.0.1: +bcryptjs-then@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/bcryptjs-then/-/bcryptjs-then-1.0.1.tgz#0c03b22a5032dec7e25109faa6ce425eb5015158" dependencies: @@ -1036,7 +1051,7 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@^3.5.0, bluebird@~3.5.0: +bluebird@3.5.0, bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" @@ -1044,7 +1059,7 @@ bmp-js@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a" -body-parser@^1.14.2, body-parser@~1.17.2: +body-parser@1.17.2, body-parser@^1.14.2: version "1.17.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee" dependencies: @@ -1076,7 +1091,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace@~0.10.0: +brace@0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/brace/-/brace-0.10.0.tgz#edef4eb9b0928ba1ee5f717ffc157749a6dd5d76" dependencies: @@ -1124,7 +1139,7 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bull@/home/nick3.0.0-rc.4: +bull@3.0.0-rc.4: version "3.0.0-rc.4" resolved "https://registry.yarnpkg.com/bull/-/bull-3.0.0-rc.4.tgz#dea18e870787037183849fc0198982ed756589b7" dependencies: @@ -1136,7 +1151,16 @@ bull@/home/nick3.0.0-rc.4: semver "^5.3.0" uuid "^3.1.0" -bunyan@^1.8.1, bunyan@^1.8.10, bunyan@^1.8.3, bunyan@~1.8.10: +bunyan@1.8.12: + version "1.8.12" + resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797" + optionalDependencies: + dtrace-provider "~0.8" + moment "^2.10.6" + mv "~2" + safe-json-stringify "~1" + +bunyan@^1.8.1, bunyan@^1.8.10, bunyan@^1.8.3: version "1.8.10" resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.10.tgz#201fedd26c7080b632f416072f53a90b9a52981c" optionalDependencies: @@ -1248,7 +1272,7 @@ charm@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/charm/-/charm-0.1.2.tgz#06c21eed1a1b06aeb67553cdc53e23274bac2296" -cheerio@~1.0.0-rc.2: +cheerio@1.0.0-rc.2: version "1.0.0-rc.2" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" dependencies: @@ -1259,13 +1283,7 @@ cheerio@~1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" -child-process-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-1.1.0.tgz#131e01a705f15ed4a05d554dd5e032e52612cf30" - dependencies: - q "^1.1.2" - -child-process-promise@~2.2.1: +child-process-promise@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-2.2.1.tgz#4730a11ef610fad450b8f223c79d31d7bdad8074" dependencies: @@ -1273,7 +1291,13 @@ child-process-promise@~2.2.1: node-version "^1.0.0" promise-polyfill "^6.0.1" -chokidar@^1.4.3, chokidar@^1.6.1, chokidar@^1.7, chokidar@~1.7.0: +child-process-promise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-1.1.0.tgz#131e01a705f15ed4a05d554dd5e032e52612cf30" + dependencies: + q "^1.1.2" + +chokidar@1.7.0, chokidar@^1.4.3, chokidar@^1.6.1, chokidar@^1.7: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -1400,7 +1424,7 @@ colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" -colors@~1.1.2: +colors@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -1410,7 +1434,24 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2.11.0, commander@^2.8.1, commander@^2.9.0: +command-line-args@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.6.tgz#0ff87a1dd159890dcaeb2a005abdae71e55059fc" + dependencies: + array-back "^1.0.4" + find-replace "^1.0.3" + typical "^2.6.1" + +command-line-usage@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-4.0.0.tgz#816b32788b58f9feba44d1e6dac60fcaeb29b5ea" + dependencies: + ansi-escape-sequences "^3.0.0" + array-back "^1.0.4" + table-layout "^0.4.0" + typical "^2.6.0" + +commander@2.11.0, commander@^2.8.1, commander@^2.9.0, commander@~2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" @@ -1420,12 +1461,6 @@ commander@2.8.x: dependencies: graceful-readlink ">= 1.0.0" -commander@~2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" @@ -1444,7 +1479,7 @@ compressible@~2.0.10: dependencies: mime-db ">= 1.27.0 < 2" -compression@~1.7.0: +compression@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.0.tgz#030c9f198f1643a057d776a738e922da4373012d" dependencies: @@ -1494,11 +1529,11 @@ configstore@^1.0.0: write-file-atomic "^1.1.2" xdg-basedir "^2.0.0" -connect-flash@~0.1.1: +connect-flash@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/connect-flash/-/connect-flash-0.1.1.tgz#d8630f26d95a7f851f9956b1e8cc6732f3b6aa30" -connect-redis@~3.3.0: +connect-redis@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/connect-redis/-/connect-redis-3.3.0.tgz#c9510c1a567ff710eb2510e6a7509fa92b2232df" dependencies: @@ -1509,7 +1544,7 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" -consolidate@~0.14.5: +consolidate@0.14.5: version "0.14.5" resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.14.5.tgz#5a25047bc76f73072667c8cb52c989888f494c63" dependencies: @@ -1553,7 +1588,7 @@ convert-source-map@^1.1.0, convert-source-map@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" -cookie-parser@~1.4.3: +cookie-parser@1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.3.tgz#0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5" dependencies: @@ -1735,7 +1770,7 @@ decompress-response@^3.2.0: dependencies: mimic-response "^1.0.0" -deep-extend@~0.4.0: +deep-extend@~0.4.0, deep-extend@~0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" @@ -1794,6 +1829,10 @@ depd@1.1.0, depd@^1.1.0, depd@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" +depd@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" + deprecated-decorator@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37" @@ -1815,7 +1854,7 @@ dicer@0.2.5, dicer@^0.2.5: readable-stream "1.1.x" streamsearch "0.1.2" -diff2html@~2.3.0: +diff2html@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/diff2html/-/diff2html-2.3.0.tgz#375fb0783ca8fa90307749399bc9c75eb7cf6580" dependencies: @@ -2057,7 +2096,7 @@ es6-promise@^3.0.2: version "3.3.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2080,7 +2119,7 @@ escodegen@^1.6.1, escodegen@^1.8.1: optionalDependencies: source-map "~0.2.0" -eslint-config-standard@~10.2.1: +eslint-config-standard@10.2.1: version "10.2.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" @@ -2098,7 +2137,7 @@ eslint-module-utils@^2.1.1: debug "^2.6.8" pkg-dir "^1.0.0" -eslint-plugin-import@~2.7.0: +eslint-plugin-import@2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f" dependencies: @@ -2113,7 +2152,7 @@ eslint-plugin-import@~2.7.0: minimatch "^3.0.3" read-pkg-up "^2.0.0" -eslint-plugin-node@~5.1.0: +eslint-plugin-node@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.1.1.tgz#a7ed956e780c22aef6afd1116005acd82f26eac6" dependencies: @@ -2122,11 +2161,11 @@ eslint-plugin-node@~5.1.0: resolve "^1.3.3" semver "5.3.0" -eslint-plugin-promise@~3.5.0: +eslint-plugin-promise@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" -eslint-plugin-standard@~3.0.1: +eslint-plugin-standard@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" @@ -2137,9 +2176,9 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@~4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.3.0.tgz#fcd7c96376bbf34c85ee67ed0012a299642b108f" +eslint@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.0.tgz#a3e153e704b64f78290ef03592494eaba228d3bc" dependencies: ajv "^5.2.0" babel-code-frame "^6.22.0" @@ -2149,7 +2188,7 @@ eslint@~4.3.0: debug "^2.6.8" doctrine "^2.0.0" eslint-scope "^3.7.1" - espree "^3.4.3" + espree "^3.5.0" esquery "^1.0.0" estraverse "^4.2.0" esutils "^2.0.2" @@ -2161,7 +2200,7 @@ eslint@~4.3.0: imurmurhash "^0.1.4" inquirer "^3.0.6" is-resolvable "^1.0.0" - js-yaml "^3.8.4" + js-yaml "^3.9.1" json-stable-stringify "^1.0.1" levn "^0.3.0" lodash "^4.17.4" @@ -2178,11 +2217,11 @@ eslint@~4.3.0: table "^4.0.1" text-table "~0.2.0" -espree@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374" +espree@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d" dependencies: - acorn "^5.0.1" + acorn "^5.1.1" acorn-jsx "^3.0.0" esprima@^2.6.0, esprima@^2.7.1: @@ -2252,24 +2291,24 @@ exec-sh@^0.2.0: dependencies: merge "^1.1.3" -execa@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.5.1.tgz#de3fb85cb8d6e91c85bcbceb164581785cb57b36" +execa@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" dependencies: - cross-spawn "^4.0.0" - get-stream "^2.2.0" + cross-spawn "^5.0.1" + get-stream "^3.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" +execa@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.5.1.tgz#de3fb85cb8d6e91c85bcbceb164581785cb57b36" dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" + cross-spawn "^4.0.0" + get-stream "^2.2.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" @@ -2296,7 +2335,7 @@ expand-template@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a" -express-brute-redis@~0.0.1: +express-brute-redis@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/express-brute-redis/-/express-brute-redis-0.0.1.tgz#0f4c833a5c3c2505c0c5c9ba55108e224a247ef8" dependencies: @@ -2318,21 +2357,21 @@ express-brute@~0.4.2: memcached "~0.2.4" underscore "~1.5.1" -express-session@~1.15.3: - version "1.15.4" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.4.tgz#5e2cdcf6defe3c1eda4e980f13b986cc58cfb954" +express-session@1.15.5: + version "1.15.5" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.5.tgz#f49a18227263b316f6f8544da5fee25a540259ec" dependencies: cookie "0.3.1" cookie-signature "1.0.6" crc "3.4.4" debug "2.6.8" - depd "~1.1.0" + depd "~1.1.1" on-headers "~1.0.1" parseurl "~1.3.1" uid-safe "~2.1.4" utils-merge "1.0.0" -express@^4.14.0, express@~4.15.3: +express@4.15.3, express@^4.14.0: version "4.15.3" resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662" dependencies: @@ -2469,6 +2508,12 @@ fclone@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.8.tgz#a0d4a73d983249978c0e0671a161520b996467eb" +feature-detect-es6@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/feature-detect-es6/-/feature-detect-es6-1.3.1.tgz#f888736af9cb0c91f55663bfa4762eb96ee7047f" + dependencies: + array-back "^1.0.3" + figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -2495,14 +2540,14 @@ file-system@^2.1.0, file-system@^2.1.1: file-match "^1.0.1" utils-extend "^1.0.4" +file-type@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + file-type@^3.1.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" -file-type@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -2514,7 +2559,7 @@ fileset@^2.0.2: glob "^7.0.3" minimatch "^3.0.3" -filesize.js@~1.0.2: +filesize.js@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/filesize.js/-/filesize.js-1.0.2.tgz#934c013395a71804875cf11e6f1ffe211c3f2192" @@ -2553,6 +2598,13 @@ find-line-column@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/find-line-column/-/find-line-column-0.5.2.tgz#db00238ff868551a182e74a103416d295a98c8ca" +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -2585,7 +2637,7 @@ fliplog@^0.3.13: dependencies: chain-able "^1.0.1" -follow-redirects@^1.2.3, follow-redirects@~1.2.4: +follow-redirects@1.2.4, follow-redirects@^1.2.3: version "1.2.4" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea" dependencies: @@ -2639,6 +2691,14 @@ from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" +fs-extra@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + fs-extra@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" @@ -2646,14 +2706,6 @@ fs-extra@^2.0.0: graceful-fs "^4.1.2" jsonfile "^2.1.0" -fs-extra@~4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.0.tgz#414fb4ca2d2170ba0014159d3a8aec3303418d9e" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^3.0.0" - universalify "^0.1.0" - fs-readdir-recursive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz#8cd1745c8b4f8a29c8caec392476921ba195f560" @@ -2694,7 +2746,7 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -fuse-box@~2.2.1: +fuse-box@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.1.tgz#444dc3bd01a47b8044210d7344495cae92d3af3a" dependencies: @@ -2789,7 +2841,7 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -git-wrapper2-promise@~0.2.9: +git-wrapper2-promise@0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/git-wrapper2-promise/-/git-wrapper2-promise-0.2.9.tgz#2c781e26a16246b05eba45fa17df687403bbfd7d" dependencies: @@ -2930,7 +2982,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" -graphql-tools@/home/nick1.1.0: +graphql-tools@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.1.0.tgz#8d86ea6997b0dea3089b62dc655e47146a663ebb" dependencies: @@ -2940,7 +2992,7 @@ graphql-tools@/home/nick1.1.0: optionalDependencies: "@types/graphql" "^0.9.0" -graphql@~0.10.5: +graphql@0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" dependencies: @@ -3035,7 +3087,7 @@ he@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" -highlight.js@~9.12.0: +highlight.js@9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" @@ -3102,24 +3154,24 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" -i18next-express-middleware@~1.0.5: +i18next-express-middleware@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.0.5.tgz#12dce7c553866e11c108943d46ce494baf982219" dependencies: cookies "0.6.1" -i18next-node-fs-backend@~1.0.0: +i18next-node-fs-backend@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/i18next-node-fs-backend/-/i18next-node-fs-backend-1.0.0.tgz#f5a625a3b287c1d098c7171b7dd376bb07299b59" dependencies: js-yaml "3.5.4" json5 "0.5.0" -i18next-xhr-backend@~1.4.2: +i18next-xhr-backend@1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.2.tgz#7aa766292c46ca83ff6477bb55074b363a646a62" -i18next@~8.4.3: +i18next@8.4.3: version "8.4.3" resolved "https://registry.yarnpkg.com/i18next/-/i18next-8.4.3.tgz#36b6ff516c4f992010eedcce24a36c4609e8c7dc" @@ -3147,7 +3199,7 @@ ignore@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" -image-size@~0.6.0: +image-size@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.1.tgz#98122a562d59dcc097ef1b2c8191866eb8f5d663" @@ -3255,7 +3307,7 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" -ioredis@^3.1.1: +ioredis@3.1.2, ioredis@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.2.tgz#2579e3eba6dc490f68f14c7b51346281332b467b" dependencies: @@ -3268,19 +3320,6 @@ ioredis@^3.1.1: redis-commands "^1.2.0" redis-parser "^2.4.0" -ioredis@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.1.tgz#cc2f1d3232b8c95cc153046bce168f2baa1186e8" - dependencies: - bluebird "^3.3.4" - cluster-key-slot "^1.0.6" - debug "^2.2.0" - denque "^1.1.0" - flexbuffer "0.0.6" - lodash "^4.8.2" - redis-commands "^1.2.0" - redis-parser "^2.4.0" - ip-regex@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" @@ -3794,13 +3833,13 @@ jest-validate@^20.0.3: leven "^2.1.0" pretty-format "^20.0.3" -jest@~20.0.4: +jest@20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac" dependencies: jest-cli "^20.0.4" -jimp@~0.2.28: +jimp@0.2.28: version "0.2.28" resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.2.28.tgz#dd529a937190f42957a7937d1acc3a7762996ea2" dependencies: @@ -3834,29 +3873,29 @@ jpeg-js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482" -jquery-contextmenu@~2.5.0: +jquery-contextmenu@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/jquery-contextmenu/-/jquery-contextmenu-2.5.0.tgz#940dbadbd0f2d7e0a0a8f1bbc5e71667d8257405" -jquery-simple-upload@~1.0.0: +jquery-simple-upload@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/jquery-simple-upload/-/jquery-simple-upload-1.0.0.tgz#0b89238bf9b35b77b41bfe11840c1b383e97a3bd" dependencies: jquery ">=1.7.0" -jquery-smooth-scroll@~2.2.0: +jquery-smooth-scroll@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/jquery-smooth-scroll/-/jquery-smooth-scroll-2.2.0.tgz#87dc1add84168b7f466b3cdaeeb81c803fd22a2a" dependencies: jquery ">=1.7.0" -jquery-sticky@~1.0.4: +jquery-sticky@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/jquery-sticky/-/jquery-sticky-1.0.4.tgz#2fe8d03dc904685340daa12cbdd1ca0c921b09ac" dependencies: jquery "*" -jquery@*, jquery@>=1.7.0, jquery@~3.2.1: +jquery@*, jquery@3.2.1, jquery@>=1.7.0: version "3.2.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787" @@ -3879,7 +3918,14 @@ js-yaml@3.5.4: argparse "^1.0.2" esprima "^2.6.0" -js-yaml@^3.7.0, js-yaml@^3.8.4, js-yaml@~3.9.0: +js-yaml@3.9.1, js-yaml@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^3.7.0: version "3.9.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.0.tgz#4ffbbf25c2ac963b8299dc74da7e3740de1c18ce" dependencies: @@ -3997,9 +4043,9 @@ jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" -jsonwebtoken@~7.4.1: - version "7.4.1" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz#7ca324f5215f8be039cd35a6c45bb8cb74a448fb" +jsonwebtoken@7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.2.tgz#571b903c07e875c0fc59203d1ac78667d80e09cd" dependencies: joi "^6.10.1" jws "^3.1.4" @@ -4056,7 +4102,7 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -klaw@~2.0.0: +klaw@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/klaw/-/klaw-2.0.0.tgz#59c128e0dc5ce410201151194eeb9cbf858650f6" dependencies: @@ -4124,6 +4170,10 @@ level-codec@~6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-6.1.0.tgz#f5df0a99582f76dac43855151ab6f4e4d0d60045" +level-codec@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.0.tgz#c755b68d0d44ffa0b1cba044b8f81a55a14ad39b" + level-errors@^1.0.3, level-errors@~1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.4.tgz#3585e623974c737a93755492a43c0267cda4425f" @@ -4149,7 +4199,19 @@ leveldown@^1.6.0, leveldown@^1.7.1: nan "~2.6.1" prebuild-install "^2.1.0" -levelup@^1.3.8, levelup@~1.3.8: +levelup@1.3.9: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + +levelup@^1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.8.tgz#fb442c488efbea1043f7eb9929a792a74fbd1da6" dependencies: @@ -4216,7 +4278,7 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash-cli@~4.17.4: +lodash-cli@4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash-cli/-/lodash-cli-4.17.4.tgz#23b727cd0e91e28484fafda1521900a8a811df81" dependencies: @@ -4226,7 +4288,7 @@ lodash-cli@~4.17.4: semver "5.3.0" uglify-js "2.7.5" -lodash-es@~4.17.4: +lodash-es@4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" @@ -4332,6 +4394,10 @@ lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" +lodash.padend@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" + lodash.repeat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44" @@ -4424,25 +4490,25 @@ map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" -markdown-it-abbr@~1.0.4: +markdown-it-abbr@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz#d66b5364521cbb3dd8aa59dadfba2fb6865c8fd8" -markdown-it-anchor@~4.0.0: +markdown-it-anchor@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-4.0.0.tgz#e87fb5543e01965adf71506c6bf7b0491841b7e3" dependencies: string "^3.3.3" -markdown-it-attrs@~0.9.0: +markdown-it-attrs@0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-0.9.0.tgz#dd4dfff1ad0b7acbf16bbfa3a97041da08c25fdd" -markdown-it-emoji@~1.4.0: +markdown-it-emoji@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc" -markdown-it-expand-tabs@~1.0.12: +markdown-it-expand-tabs@1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/markdown-it-expand-tabs/-/markdown-it-expand-tabs-1.0.12.tgz#f54bd2f303f858ee6798ca2bd83fe70144814ca0" dependencies: @@ -4452,21 +4518,21 @@ markdown-it-external-links@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/markdown-it-external-links/-/markdown-it-external-links-0.0.6.tgz#9503258fce4c81010ea15fe71769d63a1346d801" -markdown-it-footnote@~3.0.1: +markdown-it-footnote@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/markdown-it-footnote/-/markdown-it-footnote-3.0.1.tgz#7f3730747cacc86e2fe0bf8a17a710f34791517a" -markdown-it-mathjax@~2.0.0: +markdown-it-mathjax@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz#ae2b4f4c5c719a03f9e475c664f7b2685231d9e9" -markdown-it-task-lists@~2.0.1: +markdown-it-task-lists@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/markdown-it-task-lists/-/markdown-it-task-lists-2.0.1.tgz#a9ce7f55cde9f45e0fca629071d11d3fd5a69416" -markdown-it@~8.3.1: - version "8.3.1" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.1.tgz#2f4b622948ccdc193d66f3ca2d43125ac4ac7323" +markdown-it@8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.2.tgz#df4b86530d17c3bc9beec3b68d770b92ea17ae96" dependencies: argparse "^1.0.7" entities "~1.1.1" @@ -4478,7 +4544,7 @@ marked@*: version "0.3.6" resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" -mathjax-node@~1.1.0: +mathjax-node@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.1.0.tgz#96cce47fa2900245322e10cd79ec97f47f6a8ab6" dependencies: @@ -4510,7 +4576,7 @@ memcached@~0.2.4: hashring "0.0.x" jackpot ">=0.0.6" -memdown@~1.2.4: +memdown@1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.2.4.tgz#cd9a34aaf074d53445a271108eb4b8dd4ec0f27f" dependencies: @@ -4565,7 +4631,7 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -"mime-db@>= 1.27.0 < 2": +"mime-db@>= 1.27.0 < 2", mime-db@~1.29.0: version "1.29.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878" @@ -4573,6 +4639,12 @@ mime-db@~1.27.0: version "1.27.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" +mime-types@2.1.16: + version "2.1.16" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23" + dependencies: + mime-db "~1.29.0" + mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.6, mime-types@~2.1.7: version "2.1.15" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" @@ -4641,13 +4713,13 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -moment-timezone@^0.5.0, moment-timezone@^0.5.4, moment-timezone@^0.5.x, moment-timezone@~0.5.13: +moment-timezone@0.5.13, moment-timezone@^0.5.0, moment-timezone@^0.5.4, moment-timezone@^0.5.x: version "0.5.13" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.13.tgz#99ce5c7d827262eb0f1f702044177f60745d7b90" dependencies: moment ">= 2.9.0" -moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.16.1, moment@^2.18, moment@~2.18.1: +moment@2.18.1, moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.16.1, moment@^2.18: version "2.18.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" @@ -4663,7 +4735,7 @@ ms@2.0.0, ms@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -multer@~1.3.0: +multer@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/multer/-/multer-1.3.0.tgz#092b2670f6846fa4914965efc8cf94c20fec6cd2" dependencies: @@ -4733,7 +4805,7 @@ ngraminator@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/ngraminator/-/ngraminator-0.0.1.tgz#29cfd699df6970f42de9b2f0bdc7f4b60fad6f8e" -node-2fa@~1.1.2: +node-2fa@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/node-2fa/-/node-2fa-1.1.2.tgz#5bc5691474afe35ae6b3b76459b98b7c20c7158c" dependencies: @@ -4751,7 +4823,7 @@ node-fetch@1.6.3: encoding "^0.1.11" is-stream "^1.0.1" -node-graceful@~0.2.3: +node-graceful@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/node-graceful/-/node-graceful-0.2.3.tgz#ab120e1eed8c0c2b5e2ac874bf2754519c3fa942" @@ -4800,7 +4872,7 @@ node-pre-gyp@^0.6.36: tar "^2.2.1" tar-pack "^3.4.0" -node-sass@~4.5.3: +node-sass@4.5.3: version "4.5.3" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568" dependencies: @@ -4827,7 +4899,7 @@ node-version@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.0.0.tgz#1b9b9584a9a7f7a6123f215cd14a652bf21ab19e" -nodemon@~1.11.0: +nodemon@1.11.0: version "1.11.0" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.11.0.tgz#226c562bd2a7b13d3d7518b49ad4828a3623d06c" dependencies: @@ -5023,7 +5095,7 @@ options@>=0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" -ora@~1.3.0: +ora@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a" dependencies: @@ -5183,25 +5255,25 @@ passport-azure-ad-oauth2@0.0.4: dependencies: passport-oauth "1.0.x" -passport-facebook@~2.1.1: +passport-facebook@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/passport-facebook/-/passport-facebook-2.1.1.tgz#c39d0b52ae4d59163245a4e21a7b9b6321303311" dependencies: passport-oauth2 "1.x.x" -passport-github2@~0.1.10: +passport-github2@0.1.10: version "0.1.10" resolved "https://registry.yarnpkg.com/passport-github2/-/passport-github2-0.1.10.tgz#50a21c1e95b83113e4da32c81c2c1a64429bb5bd" dependencies: passport-oauth2 "1.x.x" -passport-google-oauth20@~1.0.0: +passport-google-oauth20@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-1.0.0.tgz#3b960e8a1d70d1dbe794615c827c68c40392a5d0" dependencies: passport-oauth2 "1.x.x" -passport-ldapauth@~2.0.0: +passport-ldapauth@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/passport-ldapauth/-/passport-ldapauth-2.0.0.tgz#42dff004417185d0a4d9f776a3eed8d4731fd689" dependencies: @@ -5210,7 +5282,7 @@ passport-ldapauth@~2.0.0: ldapauth-fork "^4.0.1" passport-strategy "^1.0.0" -passport-local@~1.0.0: +passport-local@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" dependencies: @@ -5259,18 +5331,25 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" -passport-windowslive@~1.0.2: +passport-windowslive@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/passport-windowslive/-/passport-windowslive-1.0.2.tgz#383cfee6589ffb5ecc2ad19c3a41ef691462a705" dependencies: passport-oauth2 "1.x.x" -passport.socketio@~3.7.0: +passport.socketio@3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/passport.socketio/-/passport.socketio-3.7.0.tgz#2ee5fafe9695d4281c8cddd3fe975ecd18e6726e" dependencies: xtend "^4.0.0" +passport@0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.3.2.tgz#9dd009f915e8fe095b0124a01b8f82da07510102" + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + passport@~0.1.1: version "0.1.18" resolved "https://registry.yarnpkg.com/passport/-/passport-0.1.18.tgz#c8264479dcb6414cadbb66752d12b37e0b6525a1" @@ -5278,13 +5357,6 @@ passport@~0.1.1: pause "0.0.1" pkginfo "0.2.x" -passport@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.3.2.tgz#9dd009f915e8fe095b0124a01b8f82da07510102" - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" @@ -5347,15 +5419,15 @@ pg-connection-string@0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" -pg-hstore@~2.3.2: +pg-hstore@2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/pg-hstore/-/pg-hstore-2.3.2.tgz#f7ef053e7b9b892ae986af2f7cbe86432dfcf24f" dependencies: underscore "^1.7.0" -pg-minify@0.4: - version "0.4.2" - resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.4.2.tgz#c75b4b5878960fb09c3b9a4d4eb1036aea7ea0e3" +pg-minify@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.5.2.tgz#42f4ad4e83231818635089c16c05c67039c83857" pg-pool@1.*: version "1.8.0" @@ -5368,13 +5440,13 @@ pg-pool@2.*: version "2.0.1" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.1.tgz#8b12541df271b57f7020c50a3f5566471f82c77e" -pg-promise@~6.3.5: - version "6.3.5" - resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.3.5.tgz#61db54e4cd269d6c7c789ee8989ae5b0aa778caa" +pg-promise@6.3.7: + version "6.3.7" + resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.3.7.tgz#7f65c29f1eba7efd3fe854e4ca3cd0244f6f8e20" dependencies: manakin "0.4" - pg "^6.4.0" - pg-minify "0.4" + pg "^6.4.1" + pg-minify "^0.5.1" spex "1.2" pg-types@1.*: @@ -5387,28 +5459,28 @@ pg-types@1.*: postgres-date "~1.0.0" postgres-interval "^1.1.0" -pg@^6.4.0: - version "6.4.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.1.tgz#3eabd8ca056814437c769f17ff7a0c36ac7023c5" +pg@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.1.0.tgz#9da3f09d3983521521c1d8369b6d9a1306cfe9fe" dependencies: buffer-writer "1.0.1" packet-reader "0.3.1" pg-connection-string "0.1.3" - pg-pool "1.*" + pg-pool "2.*" pg-types "1.*" - pgpass "1.*" + pgpass "1.x" semver "4.3.2" -pg@~7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.0.2.tgz#b9c2fe8168e7edfe9343aebe6fc48591e766ada7" +pg@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.1.tgz#3eabd8ca056814437c769f17ff7a0c36ac7023c5" dependencies: buffer-writer "1.0.1" packet-reader "0.3.1" pg-connection-string "0.1.3" - pg-pool "2.*" + pg-pool "1.*" pg-types "1.*" - pgpass "1.x" + pgpass "1.*" semver "4.3.2" pgpass@1.*, pgpass@1.x: @@ -5425,6 +5497,10 @@ pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -5484,7 +5560,7 @@ pm2-multimeter@^0.1.2: dependencies: charm "~0.1.1" -pm2@~2.6.1: +pm2@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/pm2/-/pm2-2.6.1.tgz#a9c2fdb7bf1676655935eb4176239003fca5c8da" dependencies: @@ -5702,15 +5778,15 @@ pug-error@^1.3.0, pug-error@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.2.tgz#53ae7d9d29bb03cf564493a026109f54c47f5f26" -pug-filters@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.3.tgz#d59767a220de797dd755489f66834cf9aa83aa54" +pug-filters@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.4.tgz#ab247c0f58765414b61be7b54fe979e9f6fc898f" dependencies: clean-css "^3.3.0" constantinople "^3.0.1" jstransformer "1.0.0" pug-error "^1.3.2" - pug-walk "^1.1.3" + pug-walk "^1.1.4" resolve "^1.1.6" uglify-js "^2.6.1" @@ -5730,14 +5806,14 @@ pug-lexer@^3.1.0: is-expression "^3.0.0" pug-error "^1.3.2" -pug-linker@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.1.tgz#ba3f8ff213ca8f3a304859b44fed13ca7b9dfa19" +pug-linker@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.2.tgz#cc0780cf9f3f5522b270871785492b99588d3142" dependencies: pug-error "^1.3.2" - pug-walk "^1.1.3" + pug-walk "^1.1.4" -pug-lint@~2.4.0: +pug-lint@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/pug-lint/-/pug-lint-2.4.0.tgz#1f584c1624fac48e5a0d03e40823caef736702e0" dependencies: @@ -5755,16 +5831,16 @@ pug-lint@~2.4.0: strip-json-comments "^2.0.1" void-elements "^2.0.1" -pug-load@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.7.tgz#531d0c6e11546010e984630d03df406367d2de77" +pug-load@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.8.tgz#1df1c1716f3e68c70d71699cff9458472dc38b9b" dependencies: object-assign "^4.1.0" - pug-walk "^1.1.3" + pug-walk "^1.1.4" -pug-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-3.0.0.tgz#37c619dd800f642187ce4d6ce1a164cdd75487a3" +pug-parser@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-3.0.1.tgz#dc0c5dd6c9c2d89da6105abbdf3d1b0fb4d39b5e" dependencies: pug-error "^1.3.2" token-stream "0.0.1" @@ -5779,20 +5855,20 @@ pug-strip-comments@^1.0.2: dependencies: pug-error "^1.3.2" -pug-walk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.3.tgz#d7cd5b23db3ca87c636c86a0973f9cd8e030436c" +pug-walk@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.4.tgz#29e5174af43b67e99c31b448632e1ff86ddd671c" -pug@~2.0.0-rc.2: - version "2.0.0-rc.2" - resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.2.tgz#07845527790ab2c6be67dcf5eb1f31804081f04a" +pug@2.0.0-rc.3: + version "2.0.0-rc.3" + resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.3.tgz#553cb3c3a97bb54ec3cb1e08591dcae3b6f58891" dependencies: pug-code-gen "^1.1.1" - pug-filters "^2.1.3" + pug-filters "^2.1.4" pug-lexer "^3.1.0" - pug-linker "^3.0.1" - pug-load "^2.0.7" - pug-parser "^3.0.0" + pug-linker "^3.0.2" + pug-load "^2.0.8" + pug-parser "^3.0.1" pug-runtime "^2.0.3" pug-strip-comments "^1.0.2" @@ -5870,16 +5946,17 @@ read-all-stream@^3.0.0: pinkie-promise "^2.0.0" readable-stream "^2.0.0" +read-chunk@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655" + dependencies: + pify "^3.0.0" + safe-buffer "^5.1.1" + read-chunk@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194" -read-chunk@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.0.0.tgz#3246e877829116cec059674c4d5f300f7a9261f3" - dependencies: - pify "^2.3.0" - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -5986,6 +6063,10 @@ redis@~0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/redis/-/redis-0.10.3.tgz#8927fe2110ee39617bcf3fd37b89d8e123911bb6" +reduce-flatten@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-1.0.1.tgz#258c78efd153ddf93cb561237f61184f3696e327" + regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" @@ -6033,9 +6114,9 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -remove-markdown@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/remove-markdown/-/remove-markdown-0.2.0.tgz#47f5efe3478db48c265db41e4706676a6820ec95" +remove-markdown@0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/remove-markdown/-/remove-markdown-0.2.1.tgz#1799cd8551d1942f4f308e5685436be9930c28fe" remove-trailing-separator@^1.0.1: version "1.0.2" @@ -6061,7 +6142,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2, request@^2.55.0, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0, request@~2.81.0: +request@2, request@2.81.0, request@^2.55.0, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" dependencies: @@ -6178,7 +6259,7 @@ safe-buffer@5.0.1, safe-buffer@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -6218,7 +6299,7 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -search-index-adder@~0.3.9: +search-index-adder@0.3.9: version "0.3.9" resolved "https://registry.yarnpkg.com/search-index-adder/-/search-index-adder-0.3.9.tgz#a94b5fc5b27f1827c43eab599c760dcc4c29599d" dependencies: @@ -6231,7 +6312,7 @@ search-index-adder@~0.3.9: optionalDependencies: leveldown "^1.7.1" -search-index-searcher@~0.2.10: +search-index-searcher@0.2.10: version "0.2.10" resolved "https://registry.yarnpkg.com/search-index-searcher/-/search-index-searcher-0.2.10.tgz#3b52b8bb643065883997dfce57c6c792ec551cb0" dependencies: @@ -6266,6 +6347,10 @@ semver@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" +semver@5.4.1, semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + semver@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19" @@ -6322,7 +6407,7 @@ send@0.15.3: range-parser "~1.2.0" statuses "~1.3.1" -sequelize@~4.4.2: +sequelize@4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.4.2.tgz#95292e0a752e2586ec92a0e72362b76e4fcb8eae" dependencies: @@ -6345,7 +6430,7 @@ sequelize@~4.4.2: validator "^6.3.0" wkx "^0.4.1" -serve-favicon@~2.4.3: +serve-favicon@2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.4.3.tgz#5986b17b0502642b641c21f818b1acce32025d23" dependencies: @@ -6434,7 +6519,7 @@ simple-lru-cache@0.0.x: version "0.0.2" resolved "https://registry.yarnpkg.com/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz#d59cc3a193c1a5d0320f84ee732f6e4713e511dd" -simplemde@~1.11.2: +simplemde@1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/simplemde/-/simplemde-1.11.2.tgz#a23a35d978d2c40ef07dec008c92f070d8e080e3" dependencies: @@ -6493,7 +6578,7 @@ socket.io-parser@~3.1.1: has-binary2 "~1.0.2" isarray "2.0.1" -socket.io@~2.0.2: +socket.io@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.0.3.tgz#4359f06a24933ae6bd087798af78c680eae345e3" dependencies: @@ -6596,7 +6681,7 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -stopword@~0.1.6: +stopword@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/stopword/-/stopword-0.1.6.tgz#435cc3e9d4311aedca2876ed4cae79153cd3d0fb" @@ -6622,7 +6707,7 @@ stream-to-buffer@^0.1.0: dependencies: stream-to "~0.2.0" -stream-to-promise@~2.2.0: +stream-to-promise@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/stream-to-promise/-/stream-to-promise-2.2.0.tgz#b1edb2e1c8cb11289d1b503c08d3f2aef51e650f" dependencies: @@ -6733,6 +6818,16 @@ supports-color@^4.0.0, supports-color@^4.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" +table-layout@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-0.4.0.tgz#c70ff0455d9add63b91f7c15a77926295c0e0e7d" + dependencies: + array-back "^1.0.4" + deep-extend "~0.4.1" + lodash.padend "^4.6.1" + typical "^2.6.0" + wordwrapjs "^2.0.0" + table@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" @@ -6775,6 +6870,15 @@ tar-stream@^1.1.2: readable-stream "^2.0.0" xtend "^4.0.0" +tar@3.1.9: + version "3.1.9" + resolved "https://registry.yarnpkg.com/tar/-/tar-3.1.9.tgz#2d58fe9fc5dd54652387746e1415223229c9bbeb" + dependencies: + minipass "^2.0.2" + minizlib "^1.0.3" + mkdirp "^0.5.0" + yallist "^3.0.2" + tar@^2.0.0, tar@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" @@ -6783,15 +6887,6 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" -tar@~3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/tar/-/tar-3.1.5.tgz#4981e97ab7bad4cb1d5da9232047c9047a681aef" - dependencies: - minipass "^2.0.2" - minizlib "^1.0.3" - mkdirp "^0.5.0" - yallist "^3.0.2" - term-frequency@^0.0.15: version "0.0.15" resolved "https://registry.yarnpkg.com/term-frequency/-/term-frequency-0.0.15.tgz#ff4aeaff2ac31ee1096b5c685852816a5da676e7" @@ -6824,6 +6919,13 @@ test-exclude@^4.1.1: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6836,7 +6938,7 @@ throat@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836" -through2@~2.0.3: +through2@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" dependencies: @@ -6941,7 +7043,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -twemoji-awesome@~1.0.6: +twemoji-awesome@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/twemoji-awesome/-/twemoji-awesome-1.0.6.tgz#3167c3abb95753da997291f8f1c53cbac61852a5" @@ -6968,10 +7070,14 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@~2.4.1: +typescript@2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844" +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + typo-js@*: version "1.0.3" resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.0.3.tgz#54d8ebc7949f1a7810908b6002c6841526c99d5a" @@ -6980,11 +7086,11 @@ uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" -uglify-es@~3.0.24: - version "3.0.25" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.25.tgz#b5a1de9cd7b279f4487dbb136eb7097d3432af77" +uglify-es@3.0.27: + version "3.0.27" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.27.tgz#391790388f369196be23a49caeb0d5c424fa774e" dependencies: - commander "~2.9.0" + commander "~2.11.0" source-map "~0.5.1" uglify-js@2.7.5: @@ -7137,7 +7243,7 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" -validator-as-promised@~1.0.2: +validator-as-promised@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/validator-as-promised/-/validator-as-promised-1.0.2.tgz#2ea062b2fa703b7dfd71cb34a2f12fe0894f41ce" dependencies: @@ -7145,6 +7251,10 @@ validator-as-promised@~1.0.2: lodash "^4.14.0" validator "^5.5.0" +validator@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-8.0.0.tgz#00d6ec230ab5d3353ab1174162a96462b947bdbd" + validator@^5.5.0: version "5.7.0" resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c" @@ -7153,10 +7263,6 @@ validator@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/validator/-/validator-6.3.0.tgz#47ce23ed8d4eaddfa9d4b8ef0071b6cf1078d7c8" -validator@~8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-8.0.0.tgz#00d6ec230ab5d3353ab1174162a96462b947bdbd" - vary@^1, vary@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" @@ -7171,9 +7277,9 @@ vasync@^1.6.4: dependencies: verror "1.6.0" -vee-validate@~2.0.0-rc.6: - version "2.0.0-rc.7" - resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.7.tgz#b3191ed25f7903d3b7408361f0e862f32cdf40ef" +vee-validate@2.0.0-rc.8: + version "2.0.0-rc.8" + resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.8.tgz#2a1f176f0bc1bb9a5758a5d1840b305762f7452b" verror@1.3.6: version "1.3.6" @@ -7205,38 +7311,38 @@ void-elements@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" -vue-clipboards@~1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vue-clipboards/-/vue-clipboards-1.0.4.tgz#f920b34d1d2023b8ef999a6201a04c8dc8ee8ed6" +vue-clipboards@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vue-clipboards/-/vue-clipboards-1.1.0.tgz#708d95b64e64f83e565f7fc464e7213fb6ef2d8a" dependencies: clipboard "^1.7.1" -vue-lodash@~1.0.3: +vue-lodash@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/vue-lodash/-/vue-lodash-1.0.3.tgz#777ef3e190a4cdde0d211a614e52a0b38659c13f" -vue-resource@~1.3.4: +vue-resource@1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.3.4.tgz#9fc0bdf6a2f5cab430129fc99d347b3deae7b099" dependencies: got "^7.0.0" -vue-template-compiler@~2.4.2: +vue-template-compiler@2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.4.2.tgz#5a45d843f148b098f6c1d1e35ac20c4956d30ad1" dependencies: de-indent "^1.0.2" he "^1.1.0" -vue-template-es2015-compiler@~1.5.3: +vue-template-es2015-compiler@1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.3.tgz#22787de4e37ebd9339b74223bc467d1adee30545" -vue@~2.4.2: +vue@2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/vue/-/vue-2.4.2.tgz#a9855261f191c978cc0dc1150531b8d08149b58c" -vuex@~2.3.1: +vuex@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.3.1.tgz#cde8e997c1f9957719bc7dea154f9aa691d981a6" @@ -7333,7 +7439,7 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -winston@~2.3.1: +winston@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119" dependencies: @@ -7369,6 +7475,15 @@ wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" +wordwrapjs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-2.0.0.tgz#ab55f695e6118da93858fdd70c053d1c5e01ac20" + dependencies: + array-back "^1.0.3" + feature-detect-es6 "^1.3.1" + reduce-flatten "^1.0.1" + typical "^2.6.0" + worker-farm@^1.3.1: version "1.4.1" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.4.1.tgz#a438bc993a7a7d133bcb6547c95eca7cff4897d8" @@ -7490,6 +7605,24 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" +yargs@8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" + yargs@^7.0.0, yargs@^7.0.2: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" @@ -7517,24 +7650,6 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" -yargs@~8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" From e0b788501dff6c959a815c84295fe853e5429045 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Tue, 8 Aug 2017 19:07:07 -0400 Subject: [PATCH 10/33] chore: updated dependencies --- package.json | 8 ++-- yarn.lock | 118 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 111 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 0d54a593..58238db4 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "cookie-parser": "1.4.3", "diff2html": "2.3.0", "execa": "0.8.0", - "express": "4.15.3", + "express": "4.15.4", "express-brute": "1.0.1", "express-brute-redis": "0.0.1", "express-session": "1.15.5", @@ -80,7 +80,7 @@ "markdown-it": "8.3.2", "markdown-it-abbr": "1.0.4", "markdown-it-anchor": "4.0.0", - "markdown-it-attrs": "0.9.0", + "markdown-it-attrs": "1.0.0", "markdown-it-emoji": "1.4.0", "markdown-it-expand-tabs": "1.0.12", "markdown-it-external-links": "0.0.6", @@ -140,7 +140,7 @@ "brace": "0.10.0", "colors": "1.1.2", "consolidate": "0.14.5", - "eslint": "4.4.0", + "eslint": "4.4.1", "eslint-config-standard": "10.2.1", "eslint-plugin-import": "2.7.0", "eslint-plugin-node": "5.1.1", @@ -162,7 +162,7 @@ "twemoji-awesome": "1.0.6", "typescript": "2.4.2", "uglify-es": "3.0.27", - "vee-validate": "2.0.0-rc.8", + "vee-validate": "2.0.0-rc.9", "vue": "2.4.2", "vue-clipboards": "1.1.0", "vue-lodash": "1.0.3", diff --git a/yarn.lock b/yarn.lock index 55ea2d98..1cd1121b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1829,7 +1829,7 @@ depd@1.1.0, depd@^1.1.0, depd@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" -depd@~1.1.1: +depd@1.1.1, depd@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" @@ -2176,9 +2176,9 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.0.tgz#a3e153e704b64f78290ef03592494eaba228d3bc" +eslint@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.1.tgz#99cd7eafcffca2ff99a5c8f5f2a474d6364b4bd3" dependencies: ajv "^5.2.0" babel-code-frame "^6.22.0" @@ -2371,7 +2371,40 @@ express-session@1.15.5: uid-safe "~2.1.4" utils-merge "1.0.0" -express@4.15.3, express@^4.14.0: +express@4.15.4: + version "4.15.4" + resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1" + dependencies: + accepts "~1.3.3" + array-flatten "1.1.1" + content-disposition "0.5.2" + content-type "~1.0.2" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.8" + depd "~1.1.1" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.0" + finalhandler "~1.0.4" + fresh "0.5.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.1" + path-to-regexp "0.1.7" + proxy-addr "~1.1.5" + qs "6.5.0" + range-parser "~1.2.0" + send "0.15.4" + serve-static "1.12.4" + setprototypeof "1.0.3" + statuses "~1.3.1" + type-is "~1.6.15" + utils-merge "1.0.0" + vary "~1.1.1" + +express@^4.14.0: version "4.15.3" resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662" dependencies: @@ -2594,6 +2627,18 @@ finalhandler@~1.0.3: statuses "~1.3.1" unpipe "~1.0.0" +finalhandler@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7" + dependencies: + debug "2.6.8" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.1" + statuses "~1.3.1" + unpipe "~1.0.0" + find-line-column@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/find-line-column/-/find-line-column-0.5.2.tgz#db00238ff868551a182e74a103416d295a98c8ca" @@ -3146,6 +3191,15 @@ http-errors@~1.6.1: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" +http-errors@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + http-signature@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" @@ -3332,6 +3386,10 @@ ipaddr.js@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec" +ipaddr.js@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -4500,9 +4558,9 @@ markdown-it-anchor@4.0.0: dependencies: string "^3.3.3" -markdown-it-attrs@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-0.9.0.tgz#dd4dfff1ad0b7acbf16bbfa3a97041da08c25fdd" +markdown-it-attrs@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-1.0.0.tgz#31698fbec4c54fb0cbac6e344ada6f02d682a4a1" markdown-it-emoji@1.4.0: version "1.4.0" @@ -5735,6 +5793,13 @@ proxy-addr@~1.1.4: forwarded "~0.1.0" ipaddr.js "1.3.0" +proxy-addr@~1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918" + dependencies: + forwarded "~0.1.0" + ipaddr.js "1.4.0" + prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" @@ -5903,6 +5968,10 @@ qs@6.4.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +qs@6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" + random-bytes@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" @@ -6407,6 +6476,24 @@ send@0.15.3: range-parser "~1.2.0" statuses "~1.3.1" +send@0.15.4: + version "0.15.4" + resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9" + dependencies: + debug "2.6.8" + depd "~1.1.1" + destroy "~1.0.4" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.0" + fresh "0.5.0" + http-errors "~1.6.2" + mime "1.3.4" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.3.1" + sequelize@4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.4.2.tgz#95292e0a752e2586ec92a0e72362b76e4fcb8eae" @@ -6449,6 +6536,15 @@ serve-static@1.12.3: parseurl "~1.3.1" send "0.15.3" +serve-static@1.12.4: + version "1.12.4" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961" + dependencies: + encodeurl "~1.0.1" + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.15.4" + serve-static@~1.10.2: version "1.10.3" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" @@ -7277,9 +7373,9 @@ vasync@^1.6.4: dependencies: verror "1.6.0" -vee-validate@2.0.0-rc.8: - version "2.0.0-rc.8" - resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.8.tgz#2a1f176f0bc1bb9a5758a5d1840b305762f7452b" +vee-validate@2.0.0-rc.9: + version "2.0.0-rc.9" + resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.9.tgz#6f6b881ee542d5bfbfc7f9f0a45a3f85283a0e94" verror@1.3.6: version "1.3.6" From 7e1cb3d1710c2c98cfa5873d7ead53f637a0db22 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Tue, 8 Aug 2017 22:36:29 -0400 Subject: [PATCH 11/33] feat: GraphQL mutations for User + Group --- server/modules/graphql.js | 13 +++++------- server/schemas/resolvers-group.js | 13 +++++++++--- server/schemas/resolvers-user.js | 13 +++++++++--- server/schemas/types.graphql | 35 ++++++++++++++++++++++++++++--- tools/fuse.js | 2 +- 5 files changed, 58 insertions(+), 18 deletions(-) diff --git a/server/modules/graphql.js b/server/modules/graphql.js index d40b6d04..ed6f776c 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -5,20 +5,17 @@ const gqlTools = require('graphql-tools') const fs = require('fs') const path = require('path') +const _ = require('lodash') const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8') const GroupResolvers = require('../schemas/resolvers-group') const UserResolvers = require('../schemas/resolvers-user') -const resolvers = { - Query: { - groups: GroupResolvers.Query, - users: UserResolvers.Query - }, - Group: GroupResolvers.Type, - User: UserResolvers.Type -} +const resolvers = _.merge( + GroupResolvers, + UserResolvers +) const Schema = gqlTools.makeExecutableSchema({ typeDefs, diff --git a/server/schemas/resolvers-group.js b/server/schemas/resolvers-group.js index bde68195..14f5296c 100644 --- a/server/schemas/resolvers-group.js +++ b/server/schemas/resolvers-group.js @@ -3,10 +3,17 @@ /* global wiki */ module.exports = { - Query(obj, args, context, info) { - return wiki.db.Group.findAll({ where: args }) + Query: { + groups(obj, args, context, info) { + return wiki.db.Group.findAll({ where: args }) + } + }, + Mutation: { + createGroup(obj, args) { + return wiki.db.Group.create(args) + } }, - Type: { + Group: { users(grp) { return grp.getUsers() } diff --git a/server/schemas/resolvers-user.js b/server/schemas/resolvers-user.js index d7a876fd..7bd6278c 100644 --- a/server/schemas/resolvers-user.js +++ b/server/schemas/resolvers-user.js @@ -3,10 +3,17 @@ /* global wiki */ module.exports = { - Query(obj, args, context, info) { - return wiki.db.User.findAll({ where: args }) + Query: { + users(obj, args, context, info) { + return wiki.db.User.findAll({ where: args }) + } + }, + Mutation: { + createUser(obj, args) { + return wiki.db.User.create(args) + } }, - Type: { + User: { groups(usr) { return usr.getGroups() } diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index 90722ddc..a7e6e20d 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -102,6 +102,7 @@ type Setting implements Base { config: String! } +# Tags are attached to one or more documents type Tag implements Base { id: Int! createdOn: Date @@ -109,20 +110,20 @@ type Tag implements Base { key: String! } +# A User type User implements Base { id: Int! createdOn: Date updatedOn: Date email: String! - provider: String + provider: String! providerId: String name: String role: UserRole! groups: [Group] } -# QUERY - +# Query (Read) type Query { comments(id: Int): [Comment] documents(id: Int, path: String): [Document] @@ -134,3 +135,31 @@ type Query { tags(key: String): [Tag] users(id: Int, email: String, provider: String, providerId: String, role: UserRole): [User] } + +# Mutations (Create, Update, Delete) +type Mutation { + assignUserToGroup( + userId: Int! + groupId: Int! + ): Boolean + createGroup( + name: String! + ): Group + createUser( + email: String! + name: String + provider: String! + providerId: String + role: UserRole! + ): User + deleteGroup( + id: Int! + ): Boolean + deleteUser( + id: Int! + ): Boolean + removeUserFromGroup( + userId: Int! + groupId: Int! + ): Boolean +} diff --git a/tools/fuse.js b/tools/fuse.js index 719bf6ef..9fc79274 100644 --- a/tools/fuse.js +++ b/tools/fuse.js @@ -140,7 +140,7 @@ globalTasks.then(() => { nodemon({ exec: (args.d) ? 'node server' : 'node wiki configure', ignore: ['assets/', 'client/', 'data/', 'repo/', 'tests/'], - ext: 'js json', + ext: 'js json graphql', watch: (args.d) ? ['server'] : ['server/configure.js'], env: { 'NODE_ENV': 'development' } }) From 1405b822f4d5188a62bdd931b322c5ba25b2117c Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 13 Aug 2017 14:39:07 -0400 Subject: [PATCH 12/33] feat: GraphQL Date scalar --- server/configure.js | 10 ++++----- server/modules/graphql.js | 4 +++- server/schemas/scalar-date.js | 22 +++++++++++++++++++ server/schemas/types.graphql | 40 +++++++++++++++++------------------ 4 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 server/schemas/scalar-date.js diff --git a/server/configure.js b/server/configure.js index 0766d695..bc6a282c 100644 --- a/server/configure.js +++ b/server/configure.js @@ -81,9 +81,9 @@ module.exports = (port, spinner) => { () => { const semver = require('semver') if (!semver.satisfies(semver.clean(process.version), '>=6.9.0')) { - throw new Error('Node.js version is too old. Minimum is v6.6.0.') + throw new Error('Node.js version is too old. Minimum is v6.11.1.') } - return 'Node.js ' + process.version + ' detected. Minimum is v6.9.0.' + return 'Node.js ' + process.version + ' detected.' }, () => { return Promise.try(() => { @@ -110,10 +110,10 @@ module.exports = (port, spinner) => { }, () => { const os = require('os') - if (os.totalmem() < 1000 * 1000 * 768) { - throw new Error('Not enough memory. Minimum is 768 MB.') + if (os.totalmem() < 1000 * 1000 * 512) { + throw new Error('Not enough memory. Minimum is 512 MB.') } - return _.round(os.totalmem() / (1024 * 1024)) + ' MB of system memory available. Minimum is 768 MB.' + return _.round(os.totalmem() / (1024 * 1024)) + ' MB of system memory available. Minimum is 512 MB.' }, () => { let fs = require('fs') diff --git a/server/modules/graphql.js b/server/modules/graphql.js index ed6f776c..a7f073b1 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -9,12 +9,14 @@ const _ = require('lodash') const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8') +const DateScalar = require('../schemas/scalar-date') const GroupResolvers = require('../schemas/resolvers-group') const UserResolvers = require('../schemas/resolvers-user') const resolvers = _.merge( GroupResolvers, - UserResolvers + UserResolvers, + DateScalar ) const Schema = gqlTools.makeExecutableSchema({ diff --git a/server/schemas/scalar-date.js b/server/schemas/scalar-date.js new file mode 100644 index 00000000..6fa5b585 --- /dev/null +++ b/server/schemas/scalar-date.js @@ -0,0 +1,22 @@ +'use strict' + +const gql = require('graphql') + +module.exports = { + Date: new gql.GraphQLScalarType({ + name: 'Date', + description: 'ISO date-time string at UTC', + parseValue(value) { + return new Date(value) + }, + serialize(value) { + return value.toISOString() + }, + parseLiteral(ast) { + if (ast.kind !== gql.Kind.STRING) { + throw new TypeError('Date value must be an string!') + } + return new Date(ast.value) + } + }) +} diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index a7e6e20d..95ce6ff8 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -25,16 +25,16 @@ enum RightRole { interface Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date } # TYPES type Comment implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date content: String document: Document! author: User! @@ -42,8 +42,8 @@ type Comment implements Base { type Document implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date path: String! title: String! subtitle: String @@ -57,8 +57,8 @@ type Document implements Base { type File implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date category: FileType! mime: String! extra: String @@ -70,15 +70,15 @@ type File implements Base { type Folder implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date name: String! } type Group implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date name: String! users: [User] rights: [Right] @@ -86,8 +86,8 @@ type Group implements Base { type Right implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date path: String! role: RightRole! exact: Boolean! @@ -96,8 +96,8 @@ type Right implements Base { type Setting implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date key: String! config: String! } @@ -105,16 +105,16 @@ type Setting implements Base { # Tags are attached to one or more documents type Tag implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date key: String! } # A User type User implements Base { id: Int! - createdOn: Date - updatedOn: Date + createdAt: Date + updatedAt: Date email: String! provider: String! providerId: String From 840eb7e70575c4999e3f66c946705a49318750c0 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 13 Aug 2017 20:33:06 -0400 Subject: [PATCH 13/33] feat: GraphQL mutations for folder, group, tag, user --- server/models/_relations.js | 6 ++-- server/modules/graphql.js | 4 +++ server/queues/git-sync.js | 2 +- server/queues/upl-clear-temp.js | 2 +- server/schemas/resolvers-folder.js | 29 +++++++++++++++ server/schemas/resolvers-group.js | 36 +++++++++++++++++++ server/schemas/resolvers-tag.js | 57 ++++++++++++++++++++++++++++++ server/schemas/resolvers-user.js | 8 +++++ server/schemas/types.graphql | 24 ++++++++++++- 9 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 server/schemas/resolvers-folder.js create mode 100644 server/schemas/resolvers-tag.js diff --git a/server/models/_relations.js b/server/models/_relations.js index 73436762..61b84250 100644 --- a/server/models/_relations.js +++ b/server/models/_relations.js @@ -6,9 +6,11 @@ module.exports = db => { db.User.belongsToMany(db.Group, { through: 'userGroups' }) db.Group.belongsToMany(db.User, { through: 'userGroups' }) - db.Group.hasMany(db.Right, { as: 'groupRights' }) - db.Document.hasMany(db.Tag, { as: 'documentTags' }) + db.Group.hasMany(db.Right) + db.Document.belongsToMany(db.Tag, { through: 'documentTags' }) + db.Tag.belongsToMany(db.Document, { through: 'documentTags' }) db.File.belongsTo(db.Folder) + db.Folder.hasMany(db.File) db.Comment.belongsTo(db.Document) db.Comment.belongsTo(db.User, { as: 'author' }) } diff --git a/server/modules/graphql.js b/server/modules/graphql.js index a7f073b1..c3100774 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -10,11 +10,15 @@ const _ = require('lodash') const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8') const DateScalar = require('../schemas/scalar-date') +const FolderResolvers = require('../schemas/resolvers-folder') const GroupResolvers = require('../schemas/resolvers-group') +const TagResolvers = require('../schemas/resolvers-tag') const UserResolvers = require('../schemas/resolvers-user') const resolvers = _.merge( + FolderResolvers, GroupResolvers, + TagResolvers, UserResolvers, DateScalar ) diff --git a/server/queues/git-sync.js b/server/queues/git-sync.js index ab4fefae..6c46e8ef 100644 --- a/server/queues/git-sync.js +++ b/server/queues/git-sync.js @@ -9,7 +9,7 @@ const moment = require('moment') const path = require('path') const entryHelper = require('../helpers/entry') -module.exports = (job, done) => { +module.exports = (job) => { return wiki.git.resync().then(() => { // -> Stream all documents diff --git a/server/queues/upl-clear-temp.js b/server/queues/upl-clear-temp.js index 00e2bf1e..9c3a1b5b 100644 --- a/server/queues/upl-clear-temp.js +++ b/server/queues/upl-clear-temp.js @@ -7,7 +7,7 @@ const fs = Promise.promisifyAll(require('fs-extra')) const moment = require('moment') const path = require('path') -module.exports = (job, done) => { +module.exports = (job) => { return fs.readdirAsync(wiki.UPLTEMPPATH).then((ls) => { let fifteenAgo = moment().subtract(15, 'minutes') diff --git a/server/schemas/resolvers-folder.js b/server/schemas/resolvers-folder.js new file mode 100644 index 00000000..de7add8e --- /dev/null +++ b/server/schemas/resolvers-folder.js @@ -0,0 +1,29 @@ +'use strict' + +/* global wiki */ + +module.exports = { + Query: { + folders(obj, args, context, info) { + return wiki.db.Folder.findAll({ where: args }) + } + }, + Mutation: { + createFolder(obj, args) { + return wiki.db.Folder.create(args) + }, + deleteGroup(obj, args) { + return wiki.db.Folder.destroy({ + where: { + id: args.id + }, + limit: 1 + }) + } + }, + Folder: { + files(grp) { + return grp.getFiles() + } + } +} diff --git a/server/schemas/resolvers-group.js b/server/schemas/resolvers-group.js index 14f5296c..189c0fd3 100644 --- a/server/schemas/resolvers-group.js +++ b/server/schemas/resolvers-group.js @@ -2,6 +2,8 @@ /* global wiki */ +const gql = require('graphql') + module.exports = { Query: { groups(obj, args, context, info) { @@ -9,8 +11,42 @@ module.exports = { } }, Mutation: { + assignUserToGroup(obj, args) { + return wiki.db.Group.findById(args.groupId).then(grp => { + if (!grp) { + throw new gql.GraphQLError('Invalid Group ID') + } + return wiki.db.User.findById(args.userId).then(usr => { + if (!usr) { + throw new gql.GraphQLError('Invalid User ID') + } + return grp.addUser(usr) + }) + }) + }, createGroup(obj, args) { return wiki.db.Group.create(args) + }, + deleteGroup(obj, args) { + return wiki.db.Group.destroy({ + where: { + id: args.id + }, + limit: 1 + }) + }, + removeUserFromGroup(obj, args) { + return wiki.db.Group.findById(args.groupId).then(grp => { + if (!grp) { + throw new gql.GraphQLError('Invalid Group ID') + } + return wiki.db.User.findById(args.userId).then(usr => { + if (!usr) { + throw new gql.GraphQLError('Invalid User ID') + } + return grp.removeUser(usr) + }) + }) } }, Group: { diff --git a/server/schemas/resolvers-tag.js b/server/schemas/resolvers-tag.js new file mode 100644 index 00000000..ecf05fda --- /dev/null +++ b/server/schemas/resolvers-tag.js @@ -0,0 +1,57 @@ +'use strict' + +/* global wiki */ + +const gql = require('graphql') + +module.exports = { + Query: { + tags(obj, args, context, info) { + return wiki.db.Tag.findAll({ where: args }) + } + }, + Mutation: { + assignTagToDocument(obj, args) { + return wiki.db.Tag.findById(args.tagId).then(tag => { + if (!tag) { + throw new gql.GraphQLError('Invalid Tag ID') + } + return wiki.db.Document.findById(args.documentId).then(doc => { + if (!doc) { + throw new gql.GraphQLError('Invalid Document ID') + } + return tag.addDocument(doc) + }) + }) + }, + createTag(obj, args) { + return wiki.db.Tag.create(args) + }, + deleteTag(obj, args) { + return wiki.db.Tag.destroy({ + where: { + id: args.id + }, + limit: 1 + }) + }, + removeTagFromDocument(obj, args) { + return wiki.db.Tag.findById(args.tagId).then(tag => { + if (!tag) { + throw new gql.GraphQLError('Invalid Tag ID') + } + return wiki.db.Document.findById(args.documentId).then(doc => { + if (!doc) { + throw new gql.GraphQLError('Invalid Document ID') + } + return tag.removeDocument(doc) + }) + }) + } + }, + Tag: { + documents(tag) { + return tag.getDocuments() + } + } +} diff --git a/server/schemas/resolvers-user.js b/server/schemas/resolvers-user.js index 7bd6278c..140ba83b 100644 --- a/server/schemas/resolvers-user.js +++ b/server/schemas/resolvers-user.js @@ -11,6 +11,14 @@ module.exports = { Mutation: { createUser(obj, args) { return wiki.db.User.create(args) + }, + deleteUser(obj, args) { + return wiki.db.User.destroy({ + where: { + id: args.id + }, + limit: 1 + }) } }, User: { diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index 95ce6ff8..9b347058 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -73,6 +73,7 @@ type Folder implements Base { createdAt: Date updatedAt: Date name: String! + files: [File] } type Group implements Base { @@ -107,7 +108,8 @@ type Tag implements Base { id: Int! createdAt: Date updatedAt: Date - key: String! + key: String!, + documents: [Document] } # A User @@ -138,13 +140,23 @@ type Query { # Mutations (Create, Update, Delete) type Mutation { + assignTagToDocument( + tagId: Int! + documentId: Int! + ): Boolean assignUserToGroup( userId: Int! groupId: Int! ): Boolean + createFolder( + name: String! + ): Folder createGroup( name: String! ): Group + createTag( + name: String! + ): Tag createUser( email: String! name: String @@ -152,12 +164,22 @@ type Mutation { providerId: String role: UserRole! ): User + deleteFolder( + id: Int! + ): Boolean deleteGroup( id: Int! ): Boolean + deleteTag( + id: Int! + ): Boolean deleteUser( id: Int! ): Boolean + removeTagFromDocument( + tagId: Int! + documentId: Int! + ): Boolean removeUserFromGroup( userId: Int! groupId: Int! From 02183f82ecc783d79ed88bd20af16394ca0cad4f Mon Sep 17 00:00:00 2001 From: NGPixel Date: Fri, 18 Aug 2017 21:21:29 -0400 Subject: [PATCH 14/33] feat: mutations + updated deps --- package.json | 34 +- server/modules/graphql.js | 2 + server/schemas/resolvers-document.js | 29 ++ server/schemas/types.graphql | 89 ++++- yarn.lock | 495 ++++++++++++++++++--------- 5 files changed, 452 insertions(+), 197 deletions(-) create mode 100644 server/schemas/resolvers-document.js diff --git a/package.json b/package.json index 58238db4..d3ed5237 100644 --- a/package.json +++ b/package.json @@ -37,13 +37,13 @@ "node": ">=6.11.1" }, "dependencies": { - "apollo-server-express": "1.0.5", + "apollo-server-express": "1.1.0", "auto-load": "3.0.0", "axios": "0.16.2", "bcryptjs-then": "1.0.1", "bluebird": "3.5.0", "body-parser": "1.17.2", - "bull": "3.0.0-rc.4", + "bull": "3.0.0-rc.7", "bunyan": "1.8.12", "cheerio": "1.0.0-rc.2", "child-process-promise": "2.2.1", @@ -58,23 +58,23 @@ "express-brute": "1.0.1", "express-brute-redis": "0.0.1", "express-session": "1.15.5", - "file-type": "5.2.0", + "file-type": "6.1.0", "filesize.js": "1.0.2", "follow-redirects": "1.2.4", "fs-extra": "4.0.1", "git-wrapper2-promise": "0.2.9", "graphql": "0.10.5", - "graphql-tools": "1.1.0", + "graphql-tools": "1.2.1", "highlight.js": "9.12.0", "i18next": "8.4.3", "i18next-express-middleware": "1.0.5", "i18next-node-fs-backend": "1.0.0", "image-size": "0.6.1", - "ioredis": "3.1.2", + "ioredis": "3.1.4", "jimp": "0.2.28", "js-yaml": "3.9.1", - "jsonwebtoken": "7.4.2", - "klaw": "2.0.0", + "jsonwebtoken": "7.4.3", + "klaw": "2.1.0", "levelup": "1.3.9", "lodash": "4.17.4", "markdown-it": "8.3.2", @@ -87,7 +87,7 @@ "markdown-it-footnote": "3.0.1", "markdown-it-mathjax": "2.0.0", "markdown-it-task-lists": "2.0.1", - "mathjax-node": "1.1.0", + "mathjax-node": "1.1.1", "memdown": "1.2.4", "mime-types": "2.1.16", "moment": "2.18.1", @@ -96,7 +96,7 @@ "node-2fa": "1.1.2", "node-graceful": "0.2.3", "ora": "1.3.0", - "passport": "0.3.2", + "passport": "0.4.0", "passport-azure-ad-oauth2": "0.0.4", "passport-facebook": "2.1.1", "passport-github2": "0.1.10", @@ -106,24 +106,24 @@ "passport-slack": "0.0.7", "passport-windowslive": "1.0.2", "passport.socketio": "3.7.0", - "pg": "7.1.0", + "pg": "7.1.2", "pg-hstore": "2.3.2", - "pg-promise": "6.3.7", + "pg-promise": "6.5.0", "pm2": "2.6.1", "pug": "2.0.0-rc.3", "read-chunk": "2.1.0", - "remove-markdown": "0.2.1", + "remove-markdown": "0.2.2", "request": "2.81.0", "search-index-adder": "0.3.9", "search-index-searcher": "0.2.10", "semver": "5.4.1", - "sequelize": "4.4.2", + "sequelize": "4.5.0", "serve-favicon": "2.4.3", "simplemde": "1.11.2", "socket.io": "2.0.3", "stopword": "0.1.6", "stream-to-promise": "2.2.0", - "tar": "3.1.9", + "tar": "4.0.0", "through2": "2.0.3", "validator": "8.0.0", "validator-as-promised": "1.0.2", @@ -133,7 +133,7 @@ "devDependencies": { "@glimpse/glimpse": "0.22.15", "@panter/vue-i18next": "0.5.1", - "babel-cli": "6.24.1", + "babel-cli": "6.26.0", "babel-jest": "20.0.3", "babel-plugin-transform-object-assign": "6.22.0", "babel-preset-es2015": "6.24.1", @@ -146,7 +146,7 @@ "eslint-plugin-node": "5.1.1", "eslint-plugin-promise": "3.5.0", "eslint-plugin-standard": "3.0.1", - "fuse-box": "2.2.1", + "fuse-box": "2.2.2", "i18next-xhr-backend": "1.4.2", "jest": "20.0.4", "jquery": "3.2.1", @@ -162,7 +162,7 @@ "twemoji-awesome": "1.0.6", "typescript": "2.4.2", "uglify-es": "3.0.27", - "vee-validate": "2.0.0-rc.9", + "vee-validate": "2.0.0-rc.13", "vue": "2.4.2", "vue-clipboards": "1.1.0", "vue-lodash": "1.0.3", diff --git a/server/modules/graphql.js b/server/modules/graphql.js index c3100774..58304fd4 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -10,12 +10,14 @@ const _ = require('lodash') const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8') const DateScalar = require('../schemas/scalar-date') +const DocumentResolvers = require('../schemas/resolvers-document') const FolderResolvers = require('../schemas/resolvers-folder') const GroupResolvers = require('../schemas/resolvers-group') const TagResolvers = require('../schemas/resolvers-tag') const UserResolvers = require('../schemas/resolvers-user') const resolvers = _.merge( + DocumentResolvers, FolderResolvers, GroupResolvers, TagResolvers, diff --git a/server/schemas/resolvers-document.js b/server/schemas/resolvers-document.js new file mode 100644 index 00000000..59963ace --- /dev/null +++ b/server/schemas/resolvers-document.js @@ -0,0 +1,29 @@ +'use strict' + +/* global wiki */ + +module.exports = { + Query: { + documents(obj, args, context, info) { + return wiki.db.Document.findAll({ where: args }) + } + }, + Mutation: { + createDocument(obj, args) { + return wiki.db.Document.create(args) + }, + deleteDocument(obj, args) { + return wiki.db.Document.destroy({ + where: { + id: args.id + }, + limit: 1 + }) + } + }, + Document: { + tags(doc) { + return doc.getTags() + } + } +} diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index 9b347058..9518dc5a 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -108,7 +108,7 @@ type Tag implements Base { id: Int! createdAt: Date updatedAt: Date - key: String!, + key: String! documents: [Document] } @@ -125,6 +125,11 @@ type User implements Base { groups: [Group] } +type OperationResult { + succeded: Boolean! + message: String +} + # Query (Read) type Query { comments(id: Int): [Comment] @@ -143,45 +148,111 @@ type Mutation { assignTagToDocument( tagId: Int! documentId: Int! - ): Boolean + ): OperationResult + assignUserToGroup( userId: Int! groupId: Int! - ): Boolean + ): OperationResult + + createDocument( + path: String! + title: String! + subtitle: String + ): Document + createFolder( name: String! ): Folder + createGroup( name: String! ): Group + createTag( name: String! ): Tag + createUser( email: String! name: String + passwordRaw: String provider: String! providerId: String role: UserRole! ): User + + deleteDocument( + id: Int! + ): OperationResult + deleteFolder( id: Int! - ): Boolean + ): OperationResult + deleteGroup( id: Int! - ): Boolean + ): OperationResult + deleteTag( id: Int! - ): Boolean + ): OperationResult + deleteUser( id: Int! - ): Boolean + ): OperationResult + + modifyDocument( + id: Int! + title: String + subtitle: String + ): Document + + modifyUser( + id: Int! + email: String + name: String + provider: String + providerId: String + role: UserRole + ): User + + moveDocument( + id: Int! + path: String! + ): OperationResult + + renameFolder( + id: Int! + name: String! + ): OperationResult + + renameGroup( + id: Int! + name: String! + ): OperationResult + + renameTag( + id: Int! + name: String! + ): OperationResult + removeTagFromDocument( tagId: Int! documentId: Int! - ): Boolean + ): OperationResult + removeUserFromGroup( userId: Int! groupId: Int! - ): Boolean + ): OperationResult + + resetUserPassword( + id: Int! + ): OperationResult + + setUserPassword( + id: Int! + passwordRaw: String! + ): OperationResult } diff --git a/yarn.lock b/yarn.lock index 1cd1121b..8420b745 100644 --- a/yarn.lock +++ b/yarn.lock @@ -68,7 +68,7 @@ dependencies: "@types/node" "*" -"@types/express@*", "@types/express@^4.0.35": +"@types/express@*": version "4.0.36" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.0.36.tgz#14eb47de7ecb10319f0a2fb1cf971aa8680758c2" dependencies: @@ -79,7 +79,7 @@ version "1.0.2" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.2.tgz#b02d10ab028e2928ac592a051aaa4981a1941d03" -"@types/graphql@^0.9.0", "@types/graphql@^0.9.1": +"@types/graphql@^0.9.0": version "0.9.4" resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.4.tgz#cdeb6bcbef9b6c584374b81aa7f48ecf3da404fa" @@ -125,7 +125,7 @@ JSONStream@^1.2.1: jsonparse "^1.2.0" through ">=2.2.7 <3" -abab@^1.0.0, abab@^1.0.3: +abab@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d" @@ -159,18 +159,16 @@ accepts@~1.2.12: mime-types "~2.1.6" negotiator "0.5.3" +acorn-es7-plugin@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz#f2ee1f3228a90eead1245f9ab1922eb2e71d336b" + acorn-es7@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/acorn-es7/-/acorn-es7-0.1.0.tgz#4a6de4522faacb4c31209e1b73b5f301ed2bb30a" dependencies: acorn "^2.6.4" -acorn-globals@^1.0.4: - version "1.0.9" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" - dependencies: - acorn "^2.1.0" - acorn-globals@^3.0.0, acorn-globals@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" @@ -189,7 +187,7 @@ acorn-jsx@^4.0.1: dependencies: acorn "^5.0.3" -acorn@^2.1.0, acorn@^2.4.0, acorn@^2.6.4: +acorn@^2.6.4: version "2.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" @@ -309,25 +307,28 @@ ap@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" -apollo-server-core@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.0.2.tgz#6860a6b5680c42c8727153c524eefc84fb91e500" - optionalDependencies: - "@types/graphql" "^0.9.0" +apollo-server-core@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.1.0.tgz#74c3bf4394e14eae7ab60b1d999a3c5b8aa94e9a" + dependencies: + apollo-tracing "^0.0.7" -apollo-server-express@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.0.5.tgz#4475684462a9f530f1d2630112ed45295e98dcf1" +apollo-server-express@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.1.0.tgz#48d5027b41698c386e415cf182924c2a79da0497" dependencies: - apollo-server-core "^1.0.2" - apollo-server-module-graphiql "^1.0.5" - optionalDependencies: - "@types/express" "^4.0.35" - "@types/graphql" "^0.9.1" + apollo-server-core "^1.1.0" + apollo-server-module-graphiql "^1.1.0" -apollo-server-module-graphiql@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.0.5.tgz#31639acb1dc4bd7e2edb334cf619f84ebff600a6" +apollo-server-module-graphiql@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.0.tgz#f10333e50659d61dc48e2ed6afac6f313b1f418b" + +apollo-tracing@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.0.7.tgz#78466cfefdb52a0802a57b488d26a1a67a25909f" + dependencies: + graphql-tools "^1.1.0" app-root-path@^1.3.0: version "1.4.0" @@ -496,24 +497,24 @@ axios@0.16.2: follow-redirects "^1.2.3" is-buffer "^1.1.5" -babel-cli@6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.24.1.tgz#207cd705bba61489b2ea41b5312341cf6aca2283" +babel-cli@6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" dependencies: - babel-core "^6.24.1" - babel-polyfill "^6.23.0" - babel-register "^6.24.1" - babel-runtime "^6.22.0" - commander "^2.8.1" - convert-source-map "^1.1.0" + babel-core "^6.26.0" + babel-polyfill "^6.26.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + commander "^2.11.0" + convert-source-map "^1.5.0" fs-readdir-recursive "^1.0.0" - glob "^7.0.0" - lodash "^4.2.0" - output-file-sync "^1.1.0" - path-is-absolute "^1.0.0" + glob "^7.1.2" + lodash "^4.17.4" + output-file-sync "^1.1.2" + path-is-absolute "^1.0.1" slash "^1.0.0" - source-map "^0.5.0" - v8flags "^2.0.10" + source-map "^0.5.6" + v8flags "^2.1.1" optionalDependencies: chokidar "^1.6.1" @@ -525,6 +526,14 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + babel-core@^6.0.0, babel-core@^6.24.1: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" @@ -549,6 +558,30 @@ babel-core@^6.0.0, babel-core@^6.24.1: slash "^1.0.0" source-map "^0.5.0" +babel-core@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + babel-generator@^6.18.0, babel-generator@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" @@ -562,6 +595,19 @@ babel-generator@^6.18.0, babel-generator@^6.25.0: source-map "^0.5.0" trim-right "^1.0.1" +babel-generator@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" + babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" @@ -856,7 +902,7 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-polyfill@6.23.0, babel-polyfill@^6.23.0: +babel-polyfill@6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" dependencies: @@ -864,6 +910,14 @@ babel-polyfill@6.23.0, babel-polyfill@^6.23.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" +babel-polyfill@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + dependencies: + babel-runtime "^6.26.0" + core-js "^2.5.0" + regenerator-runtime "^0.10.5" + babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" @@ -911,6 +965,18 @@ babel-register@^6.24.1: mkdirp "^0.5.1" source-map-support "^0.4.2" +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + babel-runtime@^6.18.0, babel-runtime@^6.22.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" @@ -918,6 +984,13 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" +babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" @@ -928,6 +1001,16 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0: babylon "^6.17.2" lodash "^4.2.0" +babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" @@ -942,6 +1025,20 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.25.0: invariant "^2.2.0" lodash "^4.2.0" +babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" @@ -951,10 +1048,23 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25 lodash "^4.2.0" to-fast-properties "^1.0.1" +babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + babylon@^6.17.2, babylon@^6.17.4: version "6.17.4" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a" +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -1139,16 +1249,16 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bull@3.0.0-rc.4: - version "3.0.0-rc.4" - resolved "https://registry.yarnpkg.com/bull/-/bull-3.0.0-rc.4.tgz#dea18e870787037183849fc0198982ed756589b7" +bull@3.0.0-rc.7: + version "3.0.0-rc.7" + resolved "https://registry.yarnpkg.com/bull/-/bull-3.0.0-rc.7.tgz#6e16c9fd43552045820153abbbfc03016d4ab9dd" dependencies: bluebird "^3.5.0" cron-parser "^2.4.1" debuglog "^1.0.0" - ioredis "^3.1.1" + ioredis "^3.1.4" lodash "^4.17.4" - semver "^5.3.0" + semver "^5.4.1" uuid "^3.1.0" bunyan@1.8.12: @@ -1451,7 +1561,7 @@ command-line-usage@^4.0.0: table-layout "^0.4.0" typical "^2.6.0" -commander@2.11.0, commander@^2.8.1, commander@^2.9.0, commander@~2.11.0: +commander@2.11.0, commander@^2.11.0, commander@^2.9.0, commander@~2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" @@ -1584,7 +1694,7 @@ continuation-local-storage@^3.1.4: async-listener "^0.6.0" emitter-listener "^1.0.1" -convert-source-map@^1.1.0, convert-source-map@^1.4.0: +convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" @@ -1622,6 +1732,10 @@ core-js@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" +core-js@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.0.tgz#569c050918be6486b3837552028ae0466b717086" + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1702,11 +1816,11 @@ css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" -cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0", "cssom@>= 0.3.2 < 0.4.0": +cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" -"cssstyle@>= 0.2.36 < 0.3.0", "cssstyle@>= 0.2.37 < 0.3.0": +"cssstyle@>= 0.2.37 < 0.3.0": version "0.2.37" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" dependencies: @@ -2074,12 +2188,6 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -env-cmd@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/env-cmd/-/env-cmd-5.1.0.tgz#0236db393c3f033005204fcd0a92ee40723a9c9e" - dependencies: - cross-spawn "^5.0.1" - errno@^0.1.4, errno@~0.1.1: version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" @@ -2573,9 +2681,9 @@ file-system@^2.1.0, file-system@^2.1.1: file-match "^1.0.1" utils-extend "^1.0.4" -file-type@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" +file-type@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.1.0.tgz#5a7dba98138fa0abec7afc43e5a9a0b2aac729f1" file-type@^3.1.0: version "3.9.0" @@ -2791,12 +2899,13 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -fuse-box@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.1.tgz#444dc3bd01a47b8044210d7344495cae92d3af3a" +fuse-box@2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.2.tgz#eec3c4c49496dbfca08d43179a189fbfbce67fda" dependencies: acorn "^5.0.3" acorn-es7 "^0.1.0" + acorn-es7-plugin "^1.1.7" acorn-jsx "^4.0.1" ansi "^0.3.1" app-root-path "^2.0.1" @@ -2952,7 +3061,7 @@ global@~4.3.0: min-document "^2.19.0" process "~0.5.1" -globals@^9.0.0, globals@^9.17.0: +globals@^9.0.0, globals@^9.17.0, globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -3027,12 +3136,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" -graphql-tools@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.1.0.tgz#8d86ea6997b0dea3089b62dc655e47146a663ebb" +graphql-tools@1.2.1, graphql-tools@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.1.tgz#8d462abaa7b0f3bb2aa633df1e7a848720197671" dependencies: deprecated-decorator "^0.1.6" - lodash "^4.3.0" uuid "^3.0.1" optionalDependencies: "@types/graphql" "^0.9.0" @@ -3237,7 +3345,7 @@ iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" -iconv-lite@^0.4.13, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.18" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" @@ -3351,7 +3459,7 @@ intersect-arrays-to-stream@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/intersect-arrays-to-stream/-/intersect-arrays-to-stream-0.0.3.tgz#fc0318953e872f12a12f3d33d04f4e7630e59f3b" -invariant@^2.2.0: +invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -3361,16 +3469,31 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" -ioredis@3.1.2, ioredis@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.2.tgz#2579e3eba6dc490f68f14c7b51346281332b467b" +ioredis@3.1.4, ioredis@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.4.tgz#8688293f5f2f1757e1c812ad17cce49f46d811bc" dependencies: bluebird "^3.3.4" cluster-key-slot "^1.0.6" debug "^2.2.0" denque "^1.1.0" flexbuffer "0.0.6" - lodash "^4.8.2" + lodash.assign "^4.2.0" + lodash.bind "^4.2.1" + lodash.clone "^4.5.0" + lodash.clonedeep "^4.5.0" + lodash.defaults "^4.2.0" + lodash.difference "^4.5.0" + lodash.flatten "^4.4.0" + lodash.foreach "^4.5.0" + lodash.isempty "^4.4.0" + lodash.keys "^4.2.0" + lodash.noop "^3.0.1" + lodash.partial "^4.2.1" + lodash.pick "^4.4.0" + lodash.sample "^4.2.1" + lodash.shuffle "^4.2.0" + lodash.values "^4.3.0" redis-commands "^1.2.0" redis-parser "^2.4.0" @@ -3961,11 +4084,15 @@ js-base64@^2.1.8: version "2.1.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" +js-string-escape@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + js-stringify@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" -js-tokens@^3.0.0: +js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -3998,32 +4125,7 @@ jschardet@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.0.tgz#a61f310306a5a71188e1b1acd08add3cfbb08b1e" -"jsdom@7.0 - 9.8": - version "9.8.3" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.8.3.tgz#fde29c109c32a1131e0b6c65914e64198f97c370" - dependencies: - abab "^1.0.0" - acorn "^2.4.0" - acorn-globals "^1.0.4" - array-equal "^1.0.0" - content-type-parser "^1.0.1" - cssom ">= 0.3.0 < 0.4.0" - cssstyle ">= 0.2.36 < 0.3.0" - escodegen "^1.6.1" - html-encoding-sniffer "^1.0.1" - iconv-lite "^0.4.13" - nwmatcher ">= 1.3.7 < 2.0.0" - parse5 "^1.5.1" - request "^2.55.0" - sax "^1.1.4" - symbol-tree ">= 3.1.0 < 4.0.0" - tough-cookie "^2.3.1" - webidl-conversions "^3.0.1" - whatwg-encoding "^1.0.1" - whatwg-url "^3.0.0" - xml-name-validator ">= 2.0.1 < 3.0.0" - -jsdom@^9.12.0: +"jsdom@7.0 - 9.12", jsdom@^9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4" dependencies: @@ -4077,7 +4179,7 @@ json5@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.0.tgz#9b20715b026cbe3778fd769edccd822d8332a5b2" -json5@^0.5.0: +json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -4101,9 +4203,9 @@ jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" -jsonwebtoken@7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.2.tgz#571b903c07e875c0fc59203d1ac78667d80e09cd" +jsonwebtoken@7.4.3: + version "7.4.3" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638" dependencies: joi "^6.10.1" jws "^3.1.4" @@ -4160,9 +4262,9 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -klaw@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-2.0.0.tgz#59c128e0dc5ce410201151194eeb9cbf858650f6" +klaw@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-2.1.0.tgz#694a269019f4321d9233fb1b9abdae21e38259fb" dependencies: graceful-fs "^4.1.9" @@ -4393,7 +4495,15 @@ lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" -lodash.clonedeep@^4.3.2: +lodash.bind@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + +lodash.clone@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" + +lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -4408,6 +4518,10 @@ lodash.defaults@^3.1.2: lodash.assign "^3.0.0" lodash.restparam "^3.0.0" +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + lodash.difference@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" @@ -4416,6 +4530,14 @@ lodash.findindex@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.findindex/-/lodash.findindex-4.6.0.tgz#a3245dee61fb9b6e0624b535125624bb69c11106" +lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + +lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + lodash.intersection@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.intersection/-/lodash.intersection-4.4.0.tgz#0a11ba631d0e95c23c7f2f4cbb9a692ed178e705" @@ -4428,6 +4550,10 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.isempty@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" + lodash.isequal@^4.0.0, lodash.isequal@^4.1.3: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -4440,6 +4566,10 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" +lodash.keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" + lodash.merge@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" @@ -4448,6 +4578,10 @@ lodash.mergewith@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" +lodash.noop@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-3.0.1.tgz#38188f4d650a3a474258439b96ec45b32617133c" + lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" @@ -4456,6 +4590,14 @@ lodash.padend@^4.6.1: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" +lodash.partial@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.partial/-/lodash.partial-4.2.1.tgz#49f3d8cfdaa3bff8b3a91d127e923245418961d4" + +lodash.pick@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + lodash.repeat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44" @@ -4464,6 +4606,14 @@ lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" +lodash.sample@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.sample/-/lodash.sample-4.2.1.tgz#5e4291b0c753fa1abeb0aab8fb29df1b66f07f6d" + +lodash.shuffle@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.shuffle/-/lodash.shuffle-4.2.0.tgz#145b5053cf875f6f5c2a33f48b6e9948c6ec7b4b" + lodash.sortedindexof@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/lodash.sortedindexof/-/lodash.sortedindexof-4.1.0.tgz#7b661d2f86f55668770802d56baa8f02d6620f3c" @@ -4480,7 +4630,11 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.2, lodash@~4.17.4: +lodash.values@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" + +lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4536,9 +4690,9 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -manakin@0.4: - version "0.4.7" - resolved "https://registry.yarnpkg.com/manakin/-/manakin-0.4.7.tgz#41ca449b55bea9c4c4fecec393b9c4d63818fc3f" +manakin@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/manakin/-/manakin-0.5.1.tgz#c4a7116f6b00df3d5f1a37ad3ca515d22065a658" map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" @@ -4602,11 +4756,11 @@ marked@*: version "0.3.6" resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" -mathjax-node@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.1.0.tgz#96cce47fa2900245322e10cd79ec97f47f6a8ab6" +mathjax-node@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.1.1.tgz#c9cb4c4d55f08e5116c9c49d01a8d226404a0405" dependencies: - jsdom "7.0 - 9.8" + jsdom "7.0 - 9.12" mathjax "*" mathjax@*: @@ -5046,7 +5200,7 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -"nwmatcher@>= 1.3.7 < 2.0.0", "nwmatcher@>= 1.3.9 < 2.0.0": +"nwmatcher@>= 1.3.9 < 2.0.0": version "1.4.1" resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.1.tgz#7ae9b07b0ea804db7e25f05cb5fe4097d4e4949f" @@ -5191,7 +5345,7 @@ osenv@0, osenv@^0.1.0, osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -output-file-sync@^1.1.0: +output-file-sync@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" dependencies: @@ -5401,9 +5555,9 @@ passport.socketio@3.7.0: dependencies: xtend "^4.0.0" -passport@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.3.2.tgz#9dd009f915e8fe095b0124a01b8f82da07510102" +passport@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.0.tgz#c5095691347bd5ad3b5e180238c3914d16f05811" dependencies: passport-strategy "1.x.x" pause "0.0.1" @@ -5425,7 +5579,7 @@ path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" -path-is-absolute@^1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -5483,9 +5637,9 @@ pg-hstore@2.3.2: dependencies: underscore "^1.7.0" -pg-minify@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.5.2.tgz#42f4ad4e83231818635089c16c05c67039c83857" +pg-minify@~0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.5.3.tgz#aa09befa3cbe29fab6461bf819100e0471215011" pg-pool@1.*: version "1.8.0" @@ -5498,14 +5652,14 @@ pg-pool@2.*: version "2.0.1" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.1.tgz#8b12541df271b57f7020c50a3f5566471f82c77e" -pg-promise@6.3.7: - version "6.3.7" - resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.3.7.tgz#7f65c29f1eba7efd3fe854e4ca3cd0244f6f8e20" +pg-promise@6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.5.0.tgz#ffcf1dbb2957700ddb9f2c6dd7c647d714a11ee6" dependencies: - manakin "0.4" - pg "^6.4.1" - pg-minify "^0.5.1" - spex "1.2" + manakin "~0.5.1" + pg "~6.4.2" + pg-minify "~0.5.3" + spex "~1.2.0" pg-types@1.*: version "1.12.0" @@ -5517,11 +5671,12 @@ pg-types@1.*: postgres-date "~1.0.0" postgres-interval "^1.1.0" -pg@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.1.0.tgz#9da3f09d3983521521c1d8369b6d9a1306cfe9fe" +pg@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.1.2.tgz#5dce20f3ed680651444dc311061d719cc920c3d8" dependencies: buffer-writer "1.0.1" + js-string-escape "1.0.1" packet-reader "0.3.1" pg-connection-string "0.1.3" pg-pool "2.*" @@ -5529,11 +5684,12 @@ pg@7.1.0: pgpass "1.x" semver "4.3.2" -pg@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.1.tgz#3eabd8ca056814437c769f17ff7a0c36ac7023c5" +pg@~6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.2.tgz#c364011060eac7a507a2ae063eb857ece910e27f" dependencies: buffer-writer "1.0.1" + js-string-escape "1.0.1" packet-reader "0.3.1" pg-connection-string "0.1.3" pg-pool "1.*" @@ -5743,7 +5899,7 @@ prettysize@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/prettysize/-/prettysize-0.0.3.tgz#14afff6a645e591a4ddf1c72919c23b4146181a1" -private@^0.1.6: +private@^0.1.6, private@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" @@ -6140,10 +6296,14 @@ regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" -regenerator-runtime@^0.10.0: +regenerator-runtime@^0.10.0, regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" +regenerator-runtime@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" + regenerator-transform@0.9.11: version "0.9.11" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.11.tgz#3a7d067520cb7b7176769eb5ff868691befe1283" @@ -6183,9 +6343,9 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -remove-markdown@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/remove-markdown/-/remove-markdown-0.2.1.tgz#1799cd8551d1942f4f308e5685436be9930c28fe" +remove-markdown@0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/remove-markdown/-/remove-markdown-0.2.2.tgz#66b0ceeba9fb77ca9636bb1b0307ce21a32a12a6" remove-trailing-separator@^1.0.1: version "1.0.2" @@ -6211,7 +6371,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2, request@2.81.0, request@^2.55.0, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0: +request@2, request@2.81.0, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" dependencies: @@ -6357,7 +6517,7 @@ sass-graph@^2.1.1: scss-tokenizer "^0.2.3" yargs "^7.0.0" -sax@>=0.6.0, sax@^1.1.4, sax@^1.2.1: +sax@>=0.6.0, sax@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -6416,7 +6576,7 @@ semver@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" -semver@5.4.1, semver@~5.4.1: +semver@5.4.1, semver@^5.4.1, semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -6494,16 +6654,15 @@ send@0.15.4: range-parser "~1.2.0" statuses "~1.3.1" -sequelize@4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.4.2.tgz#95292e0a752e2586ec92a0e72362b76e4fcb8eae" +sequelize@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.5.0.tgz#d8a5b1b641728890fa96761b1704203e7ae30ebb" dependencies: bluebird "^3.4.6" cls-bluebird "^2.0.1" debug "^2.3.0" depd "^1.1.0" dottie "^2.0.0" - env-cmd "^5.0.0" generic-pool "^3.1.6" inflection "1.10.0" lodash "^4.17.1" @@ -6721,7 +6880,7 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" -spex@1.2: +spex@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/spex/-/spex-1.2.0.tgz#6264b3b8acbc444477f06dbb66d425c0ee1074c0" @@ -6910,7 +7069,7 @@ supports-color@^4.0.0, supports-color@^4.2.0: dependencies: has-flag "^2.0.0" -"symbol-tree@>= 3.1.0 < 4.0.0", symbol-tree@^3.2.1: +symbol-tree@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -6966,10 +7125,11 @@ tar-stream@^1.1.2: readable-stream "^2.0.0" xtend "^4.0.0" -tar@3.1.9: - version "3.1.9" - resolved "https://registry.yarnpkg.com/tar/-/tar-3.1.9.tgz#2d58fe9fc5dd54652387746e1415223229c9bbeb" +tar@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.0.0.tgz#aa7d58cfb750cc919d9da1d3319f9ccabac339e0" dependencies: + chownr "^1.0.1" minipass "^2.0.2" minizlib "^1.0.3" mkdirp "^0.5.0" @@ -7075,7 +7235,7 @@ to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" -to-fast-properties@^1.0.1: +to-fast-properties@^1.0.1, to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -7099,7 +7259,7 @@ touch@1.0.0: dependencies: nopt "~1.0.10" -tough-cookie@^2.3.1, tough-cookie@^2.3.2, tough-cookie@~2.3.0: +tough-cookie@^2.3.2, tough-cookie@~2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" dependencies: @@ -7326,7 +7486,7 @@ uws@~0.14.4: version "0.14.5" resolved "https://registry.yarnpkg.com/uws/-/uws-0.14.5.tgz#67aaf33c46b2a587a5f6666d00f7691328f149dc" -v8flags@^2.0.10: +v8flags@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" dependencies: @@ -7373,9 +7533,9 @@ vasync@^1.6.4: dependencies: verror "1.6.0" -vee-validate@2.0.0-rc.9: - version "2.0.0-rc.9" - resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.9.tgz#6f6b881ee542d5bfbfc7f9f0a45a3f85283a0e94" +vee-validate@2.0.0-rc.13: + version "2.0.0-rc.13" + resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.13.tgz#b2aadf729c277d7a908bec5d71169d02c54b7890" verror@1.3.6: version "1.3.6" @@ -7479,7 +7639,7 @@ watch@~0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc" -webidl-conversions@^3.0.0, webidl-conversions@^3.0.1: +webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -7497,13 +7657,6 @@ whatwg-fetch@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" -whatwg-url@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-3.1.0.tgz#7bdcae490f921aef6451fb6739ec6bbd8e907bf6" - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - whatwg-url@^4.3.0: version "4.8.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.8.0.tgz#d2981aa9148c1e00a41c5a6131166ab4683bbcc0" @@ -7641,7 +7794,7 @@ xhr@^2.0.1: parse-headers "^2.0.0" xtend "^4.0.0" -"xml-name-validator@>= 2.0.1 < 3.0.0", xml-name-validator@^2.0.1: +xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" From 574e4b97f40d087c5267a7ad976329aec357cc2e Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 19 Aug 2017 22:51:25 -0400 Subject: [PATCH 15/33] feat: GraphQL setting, right, folder resolvers --- server/models/_relations.js | 2 ++ server/models/document.js | 5 +++ server/modules/graphql.js | 4 +++ server/schemas/resolvers-comment.js | 43 ++++++++++++++++++++++ server/schemas/resolvers-document.js | 18 ++++++++++ server/schemas/resolvers-folder.js | 7 ++++ server/schemas/resolvers-group.js | 7 ++++ server/schemas/resolvers-right.js | 54 ++++++++++++++++++++++++++++ server/schemas/resolvers-setting.js | 25 +++++++++++++ server/schemas/resolvers-tag.js | 7 ++++ server/schemas/resolvers-user.js | 17 +++++++++ server/schemas/types.graphql | 44 ++++++++++++++++++++++- 12 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 server/schemas/resolvers-comment.js create mode 100644 server/schemas/resolvers-right.js create mode 100644 server/schemas/resolvers-setting.js diff --git a/server/models/_relations.js b/server/models/_relations.js index 61b84250..e14fe007 100644 --- a/server/models/_relations.js +++ b/server/models/_relations.js @@ -7,7 +7,9 @@ module.exports = db => { db.User.belongsToMany(db.Group, { through: 'userGroups' }) db.Group.belongsToMany(db.User, { through: 'userGroups' }) db.Group.hasMany(db.Right) + db.Right.belongsTo(db.Group) db.Document.belongsToMany(db.Tag, { through: 'documentTags' }) + db.Document.hasMany(db.Comment) db.Tag.belongsToMany(db.Document, { through: 'documentTags' }) db.File.belongsTo(db.Folder) db.Folder.hasMany(db.File) diff --git a/server/models/document.js b/server/models/document.js index 76c9e0c7..2e0d9717 100644 --- a/server/models/document.js +++ b/server/models/document.js @@ -41,6 +41,11 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, defaultValue: false }, + isDraft: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, searchContent: { type: DataTypes.TEXT, allowNull: true, diff --git a/server/modules/graphql.js b/server/modules/graphql.js index 58304fd4..2224d64b 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -10,16 +10,20 @@ const _ = require('lodash') const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8') const DateScalar = require('../schemas/scalar-date') +const CommentResolvers = require('../schemas/resolvers-comment') const DocumentResolvers = require('../schemas/resolvers-document') const FolderResolvers = require('../schemas/resolvers-folder') const GroupResolvers = require('../schemas/resolvers-group') +const SettingResolvers = require('../schemas/resolvers-setting') const TagResolvers = require('../schemas/resolvers-tag') const UserResolvers = require('../schemas/resolvers-user') const resolvers = _.merge( + CommentResolvers, DocumentResolvers, FolderResolvers, GroupResolvers, + SettingResolvers, TagResolvers, UserResolvers, DateScalar diff --git a/server/schemas/resolvers-comment.js b/server/schemas/resolvers-comment.js new file mode 100644 index 00000000..f8d00ee2 --- /dev/null +++ b/server/schemas/resolvers-comment.js @@ -0,0 +1,43 @@ +'use strict' + +/* global wiki */ + +module.exports = { + Query: { + comments(obj, args, context, info) { + return wiki.db.Comment.findAll({ where: args }) + } + }, + Mutation: { + createComment(obj, args) { + return wiki.db.Comment.create({ + content: args.content, + author: args.userId, + document: args.documentId + }) + }, + deleteComment(obj, args) { + return wiki.db.Comment.destroy({ + where: { + id: args.id + }, + limit: 1 + }) + }, + modifyComment(obj, args) { + return wiki.db.Comment.update({ + content: args.content + }, { + where: { id: args.id } + }) + } + }, + Comment: { + author(cm) { + return cm.getAuthor() + }, + document(cm) { + return cm.getDocument() + } + } +} diff --git a/server/schemas/resolvers-document.js b/server/schemas/resolvers-document.js index 59963ace..666f8fef 100644 --- a/server/schemas/resolvers-document.js +++ b/server/schemas/resolvers-document.js @@ -19,9 +19,27 @@ module.exports = { }, limit: 1 }) + }, + modifyDocument(obj, args) { + return wiki.db.Document.update({ + title: args.title, + subtitle: args.subtitle + }, { + where: { id: args.id } + }) + }, + moveDocument(obj, args) { + return wiki.db.Document.update({ + path: args.path + }, { + where: { id: args.id } + }) } }, Document: { + comments(doc) { + return doc.getComments() + }, tags(doc) { return doc.getTags() } diff --git a/server/schemas/resolvers-folder.js b/server/schemas/resolvers-folder.js index de7add8e..4acf2806 100644 --- a/server/schemas/resolvers-folder.js +++ b/server/schemas/resolvers-folder.js @@ -19,6 +19,13 @@ module.exports = { }, limit: 1 }) + }, + renameFolder(obj, args) { + return wiki.db.Folder.update({ + name: args.name + }, { + where: { id: args.id } + }) } }, Folder: { diff --git a/server/schemas/resolvers-group.js b/server/schemas/resolvers-group.js index 189c0fd3..61afc2d0 100644 --- a/server/schemas/resolvers-group.js +++ b/server/schemas/resolvers-group.js @@ -47,6 +47,13 @@ module.exports = { return grp.removeUser(usr) }) }) + }, + renameGroup(obj, args) { + return wiki.db.Group.update({ + name: args.name + }, { + where: { id: args.id } + }) } }, Group: { diff --git a/server/schemas/resolvers-right.js b/server/schemas/resolvers-right.js new file mode 100644 index 00000000..72e42b76 --- /dev/null +++ b/server/schemas/resolvers-right.js @@ -0,0 +1,54 @@ +'use strict' + +/* global wiki */ + +const gql = require('graphql') + +module.exports = { + Query: { + rights(obj, args, context, info) { + return wiki.db.Right.findAll({ where: args }) + } + }, + Mutation: { + addRightToGroup(obj, args) { + return wiki.db.Group.findById(args.groupId).then(grp => { + if (!grp) { + throw new gql.GraphQLError('Invalid Group ID') + } + return wiki.db.Right.create({ + path: args.path, + role: args.role, + exact: args.exact, + allow: args.allow, + group: grp + }) + }) + }, + removeRightFromGroup(obj, args) { + return wiki.db.Right.destroy({ + where: { + id: args.rightId + }, + limit: 1 + }) + }, + modifyRight(obj, args) { + return wiki.db.Right.update({ + path: args.path, + role: args.role, + exact: args.exact, + allow: args.allow + }, { + where: { + id: args.id + } + }) + } + }, + Right: { + group(rt) { + return rt.getGroup() + } + } +} diff --git a/server/schemas/resolvers-setting.js b/server/schemas/resolvers-setting.js new file mode 100644 index 00000000..1ece4a0e --- /dev/null +++ b/server/schemas/resolvers-setting.js @@ -0,0 +1,25 @@ +'use strict' + +/* global wiki */ + +const _ = require('lodash') + +module.exports = { + Query: { + settings(obj, args, context, info) { + return wiki.db.Setting.findAll({ where: args, raw: true }).then(entries => { + return _.map(entries, entry => { + entry.config = JSON.stringify(entry.config) + return entry + }) + }) + } + }, + Mutation: { + setConfigEntry(obj, args) { + return wiki.db.Setting.update({ + value: args.value + }, { where: { key: args.key } }) + } + } +} diff --git a/server/schemas/resolvers-tag.js b/server/schemas/resolvers-tag.js index ecf05fda..ad11f674 100644 --- a/server/schemas/resolvers-tag.js +++ b/server/schemas/resolvers-tag.js @@ -47,6 +47,13 @@ module.exports = { return tag.removeDocument(doc) }) }) + }, + renameTag(obj, args) { + return wiki.db.Group.update({ + key: args.key + }, { + where: { id: args.id } + }) } }, Tag: { diff --git a/server/schemas/resolvers-user.js b/server/schemas/resolvers-user.js index 140ba83b..694306e2 100644 --- a/server/schemas/resolvers-user.js +++ b/server/schemas/resolvers-user.js @@ -19,6 +19,23 @@ module.exports = { }, limit: 1 }) + }, + modifyUser(obj, args) { + return wiki.db.User.update({ + email: args.email, + name: args.name, + provider: args.provider, + providerId: args.providerId, + role: args.role + }, { + where: { id: args.id } + }) + }, + resetUserPassword(obj, args) { + return false + }, + setUserPassword(obj, args) { + return false } }, User: { diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index 9518dc5a..18bcf1d9 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -52,6 +52,7 @@ type Document implements Base { isDirectory: Boolean! isEntry: Boolean! searchContent: String + comments: [Comment] tags: [Tag] } @@ -93,6 +94,7 @@ type Right implements Base { role: RightRole! exact: Boolean! allow: Boolean! + group: Group! } type Setting implements Base { @@ -145,6 +147,14 @@ type Query { # Mutations (Create, Update, Delete) type Mutation { + addRightToGroup( + groupId: Int! + path: String! + role: RightRole! + exact: Boolean! + allow: Boolean! + ): Right + assignTagToDocument( tagId: Int! documentId: Int! @@ -155,6 +165,12 @@ type Mutation { groupId: Int! ): OperationResult + createComment( + userId: Int! + documentId: Int! + content: String! + ): Comment + createDocument( path: String! title: String! @@ -182,6 +198,10 @@ type Mutation { role: UserRole! ): User + deleteComment( + id: Int! + ): OperationResult + deleteDocument( id: Int! ): OperationResult @@ -202,6 +222,11 @@ type Mutation { id: Int! ): OperationResult + modifyComment( + id: Int! + content: String! + ): Document + modifyDocument( id: Int! title: String @@ -217,6 +242,14 @@ type Mutation { role: UserRole ): User + modifyRight( + id: Int! + path: String + role: RightRole + exact: Boolean + allow: Boolean + ): Right + moveDocument( id: Int! path: String! @@ -234,7 +267,7 @@ type Mutation { renameTag( id: Int! - name: String! + key: String! ): OperationResult removeTagFromDocument( @@ -242,6 +275,10 @@ type Mutation { documentId: Int! ): OperationResult + removeRightFromGroup( + rightId: Int! + ): OperationResult + removeUserFromGroup( userId: Int! groupId: Int! @@ -251,6 +288,11 @@ type Mutation { id: Int! ): OperationResult + setConfigEntry( + key: String! + value: String! + ): OperationResult + setUserPassword( id: Int! passwordRaw: String! From 35cb56c69452aba33cc5e7bfab4315f2ca841170 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Mon, 4 Sep 2017 13:03:15 -0400 Subject: [PATCH 16/33] feat: file resolvers + pull changes from master --- CHANGELOG.md | 11 + README.md | 31 +- package.json | 46 +-- server/modules/git.js | 5 +- server/modules/graphql.js | 2 + server/schemas/resolvers-file.js | 52 +++ server/schemas/types.graphql | 19 + tools/docker-compose.yml | 2 +- wercker.yml | 13 +- yarn.lock | 591 +++++++++++++++++-------------- 10 files changed, 459 insertions(+), 313 deletions(-) create mode 100644 server/schemas/resolvers-file.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 751ae0f1..83bd69c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [v1.0.8] - 2017-08-31 +### Changed +- **Misc**: Updated dependencies + +## [v1.0.7] - 2017-08-29 +### Fixed +- **Authentication**: Azure AD client Id is now referenced correctly ([#219](https://github.com/Requarks/wiki/issues/219)) +- **Git**: Git Branch is now referenced correctly ([#215](https://github.com/Requarks/wiki/issues/215)) + ## [v1.0.6] - 2017-08-10 ### Fixed - **Authentication**: LDAP no longer cause the social login text to appear on the login screen. @@ -208,6 +217,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Updated dependencies + snyk policy +[v1.0.8]: https://github.com/Requarks/wiki/releases/tag/v1.0.8 +[v1.0.7]: https://github.com/Requarks/wiki/releases/tag/v1.0.7 [v1.0.6]: https://github.com/Requarks/wiki/releases/tag/v1.0.6 [v1.0.5]: https://github.com/Requarks/wiki/releases/tag/v1.0.5 [v1.0.4]: https://github.com/Requarks/wiki/releases/tag/v1.0.4 diff --git a/README.md b/README.md index 278795f8..efc2e507 100644 --- a/README.md +++ b/README.md @@ -53,34 +53,37 @@ You can also use a Dockerfile ([see example](https://github.com/Requarks/wiki/bl Current and upcoming milestones *(major features only, see the [changelog](https://github.com/Requarks/wiki/blob/master/CHANGELOG.md) for complete list of features and bug fixes)*: -### 1.0.0 - Beta 13 +### 1.0.8 - Stable ![Progress](http://progressed.io/bar/100) -- [x] Color Themes -- [x] Server-side TeX/MathML rendering -- [x] Render line breaks by default (GitHub style) -- [x] New Localization: German - -### 1.0.6 - Stable -![Progress](http://progressed.io/bar/100) - -- [x] Bug fixes release -- [x] New Localization: Dutch +- [x] Fix: Azure AD client Id is now referenced correctly ([#219](https://github.com/Requarks/wiki/issues/219)) +- [x] Fix: Git Branch is now referenced correctly ([#215](https://github.com/Requarks/wiki/issues/215)) +- [x] Updated dependencies ### 2.0.0 - Dev -![Progress](http://progressed.io/bar/20) +![Progress](http://progressed.io/bar/25) **Breaking Changes**: MongoDB is being phased out in favor of PostgreSQL + Redis. An upgrade tool will be provided to migrate existing data to the new system. -- [ ] GraphQL API +- [x] GraphQL API + - [x] Comments + - [x] Documents + - [x] Files + - [x] Folders + - [x] Groups + - [x] Rights + - [x] Settings + - [x] Tags + - [x] Users - [x] Migrate to PostgreSQL + Redis datastore +- [ ] New Login page - [ ] History / Revert to previous version - [ ] Optional Two-Steps Authentication (2FA) - [x] Docker support + Auto compile/publish to Docker Hub - [ ] Support sub-directory installations (e.g. example.com/wiki) - [ ] Persist system settings to database instead of file-based - [ ] User Groups + Better permissions management -- [ ] Make use of all available CPU cores, distributed jobs queue +- [x] Make use of all available CPU cores, distributed jobs queue - [ ] Tags per document / folder - [ ] Comments / Discussion per document - [ ] Profile page per user diff --git a/package.json b/package.json index d3ed5237..7545f72b 100644 --- a/package.json +++ b/package.json @@ -37,13 +37,13 @@ "node": ">=6.11.1" }, "dependencies": { - "apollo-server-express": "1.1.0", + "apollo-server-express": "1.1.2", "auto-load": "3.0.0", "axios": "0.16.2", "bcryptjs-then": "1.0.1", "bluebird": "3.5.0", "body-parser": "1.17.2", - "bull": "3.0.0-rc.7", + "bull": "3.0.0", "bunyan": "1.8.12", "cheerio": "1.0.0-rc.2", "child-process-promise": "2.2.1", @@ -63,10 +63,10 @@ "follow-redirects": "1.2.4", "fs-extra": "4.0.1", "git-wrapper2-promise": "0.2.9", - "graphql": "0.10.5", - "graphql-tools": "1.2.1", + "graphql": "0.11.2", + "graphql-tools": "1.2.2", "highlight.js": "9.12.0", - "i18next": "8.4.3", + "i18next": "9.0.0", "i18next-express-middleware": "1.0.5", "i18next-node-fs-backend": "1.0.0", "image-size": "0.6.1", @@ -77,19 +77,19 @@ "klaw": "2.1.0", "levelup": "1.3.9", "lodash": "4.17.4", - "markdown-it": "8.3.2", + "markdown-it": "8.4.0", "markdown-it-abbr": "1.0.4", "markdown-it-anchor": "4.0.0", - "markdown-it-attrs": "1.0.0", + "markdown-it-attrs": "1.1.0", "markdown-it-emoji": "1.4.0", "markdown-it-expand-tabs": "1.0.12", "markdown-it-external-links": "0.0.6", "markdown-it-footnote": "3.0.1", "markdown-it-mathjax": "2.0.0", "markdown-it-task-lists": "2.0.1", - "mathjax-node": "1.1.1", + "mathjax-node": "1.2.0", "memdown": "1.2.4", - "mime-types": "2.1.16", + "mime-types": "2.1.17", "moment": "2.18.1", "moment-timezone": "0.5.13", "multer": "1.3.0", @@ -106,9 +106,9 @@ "passport-slack": "0.0.7", "passport-windowslive": "1.0.2", "passport.socketio": "3.7.0", - "pg": "7.1.2", + "pg": "7.3.0", "pg-hstore": "2.3.2", - "pg-promise": "6.5.0", + "pg-promise": "6.5.1", "pm2": "2.6.1", "pug": "2.0.0-rc.3", "read-chunk": "2.1.0", @@ -117,15 +117,15 @@ "search-index-adder": "0.3.9", "search-index-searcher": "0.2.10", "semver": "5.4.1", - "sequelize": "4.5.0", + "sequelize": "4.8.0", "serve-favicon": "2.4.3", "simplemde": "1.11.2", "socket.io": "2.0.3", "stopword": "0.1.6", "stream-to-promise": "2.2.0", - "tar": "4.0.0", + "tar": "4.0.1", "through2": "2.0.3", - "validator": "8.0.0", + "validator": "8.1.0", "validator-as-promised": "1.0.2", "winston": "2.3.1", "yargs": "8.0.2" @@ -134,21 +134,21 @@ "@glimpse/glimpse": "0.22.15", "@panter/vue-i18next": "0.5.1", "babel-cli": "6.26.0", - "babel-jest": "20.0.3", + "babel-jest": "21.0.0", "babel-plugin-transform-object-assign": "6.22.0", "babel-preset-es2015": "6.24.1", "brace": "0.10.0", "colors": "1.1.2", "consolidate": "0.14.5", - "eslint": "4.4.1", + "eslint": "4.6.1", "eslint-config-standard": "10.2.1", "eslint-plugin-import": "2.7.0", "eslint-plugin-node": "5.1.1", "eslint-plugin-promise": "3.5.0", "eslint-plugin-standard": "3.0.1", - "fuse-box": "2.2.2", + "fuse-box": "2.2.3", "i18next-xhr-backend": "1.4.2", - "jest": "20.0.4", + "jest": "21.0.0", "jquery": "3.2.1", "jquery-contextmenu": "2.5.0", "jquery-simple-upload": "1.0.0", @@ -158,18 +158,18 @@ "lodash-es": "4.17.4", "node-sass": "4.5.3", "nodemon": "1.11.0", - "pug-lint": "2.4.0", + "pug-lint": "2.5.0", "twemoji-awesome": "1.0.6", - "typescript": "2.4.2", - "uglify-es": "3.0.27", - "vee-validate": "2.0.0-rc.13", + "typescript": "2.5.2", + "uglify-es": "3.0.28", + "vee-validate": "2.0.0-rc.14", "vue": "2.4.2", "vue-clipboards": "1.1.0", "vue-lodash": "1.0.3", "vue-resource": "1.3.4", "vue-template-compiler": "2.4.2", "vue-template-es2015-compiler": "1.5.3", - "vuex": "2.3.1" + "vuex": "2.4.0" }, "jest": { "collectCoverage": false, diff --git a/server/modules/git.js b/server/modules/git.js index dedd9b6b..f34ff829 100644 --- a/server/modules/git.js +++ b/server/modules/git.js @@ -53,10 +53,9 @@ module.exports = { self.onReady = (wiki.IS_MASTER) ? self._initRepo() : Promise.resolve() - // Define signature - if (wiki.config.git) { - self._signature.email = wiki.config.git.serverEmail || 'wiki@example.com' + self._repo.branch = appconfig.git.branch || 'master' + self._signature.email = appconfig.git.serverEmail || 'wiki@example.com' } return self diff --git a/server/modules/graphql.js b/server/modules/graphql.js index 2224d64b..e1897390 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -12,6 +12,7 @@ const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graph const DateScalar = require('../schemas/scalar-date') const CommentResolvers = require('../schemas/resolvers-comment') const DocumentResolvers = require('../schemas/resolvers-document') +const FileResolvers = require('../schemas/resolvers-file') const FolderResolvers = require('../schemas/resolvers-folder') const GroupResolvers = require('../schemas/resolvers-group') const SettingResolvers = require('../schemas/resolvers-setting') @@ -21,6 +22,7 @@ const UserResolvers = require('../schemas/resolvers-user') const resolvers = _.merge( CommentResolvers, DocumentResolvers, + FileResolvers, FolderResolvers, GroupResolvers, SettingResolvers, diff --git a/server/schemas/resolvers-file.js b/server/schemas/resolvers-file.js new file mode 100644 index 00000000..c1011d95 --- /dev/null +++ b/server/schemas/resolvers-file.js @@ -0,0 +1,52 @@ +'use strict' + +/* global wiki */ + +const gql = require('graphql') + +module.exports = { + Query: { + files(obj, args, context, info) { + return wiki.db.File.findAll({ where: args }) + } + }, + Mutation: { + uploadFile(obj, args) { + // todo + return wiki.db.File.create(args) + }, + deleteFile(obj, args) { + return wiki.db.File.destroy({ + where: { + id: args.id + }, + limit: 1 + }) + }, + renameFile(obj, args) { + return wiki.db.File.update({ + filename: args.filename + }, { + where: { id: args.id } + }) + }, + moveFile(obj, args) { + return wiki.db.File.findById(args.fileId).then(fl => { + if (!fl) { + throw new gql.GraphQLError('Invalid File ID') + } + return wiki.db.Folder.findById(args.folderId).then(fld => { + if (!fld) { + throw new gql.GraphQLError('Invalid Folder ID') + } + return fl.setFolder(fld) + }) + }) + } + }, + File: { + folder(fl) { + return fl.getFolder() + } + } +} diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index 18bcf1d9..4f5cc929 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -206,6 +206,10 @@ type Mutation { id: Int! ): OperationResult + deleteFile( + id: Int! + ): OperationResult + deleteFolder( id: Int! ): OperationResult @@ -255,6 +259,16 @@ type Mutation { path: String! ): OperationResult + moveFile( + id: Int! + folderId: Int! + ): OperationResult + + renameFile( + id: Int! + name: String! + ): OperationResult + renameFolder( id: Int! name: String! @@ -297,4 +311,9 @@ type Mutation { id: Int! passwordRaw: String! ): OperationResult + + uploadFile( + category: FileType! + filename: String! + ): File } diff --git a/tools/docker-compose.yml b/tools/docker-compose.yml index c7f9595a..7407a580 100644 --- a/tools/docker-compose.yml +++ b/tools/docker-compose.yml @@ -14,6 +14,6 @@ services: ports: - '80:3000' environment: - - WIKI_ADMIN_EMAIL: admin@example.com + WIKI_ADMIN_EMAIL: admin@example.com volumes: - ./config.yml:/var/wiki/config.yml diff --git a/wercker.yml b/wercker.yml index 369bc30a..62bdd216 100644 --- a/wercker.yml +++ b/wercker.yml @@ -33,7 +33,7 @@ deploy-docker-master: name: copy app files code: | mkdir -p /var/wiki - cp -LR assets node_modules server config.sample.yml package.json /var/wiki + cp -LR assets node_modules server config.sample.yml package.json LICENSE /var/wiki rm -rf /pipeline - internal/docker-push: username: $DOCKER_HUB_USERNAME @@ -58,7 +58,7 @@ deploy-docker-dev: name: copy app files code: | mkdir -p /var/wiki - cp -LR assets node_modules server config.sample.yml package.json /var/wiki + cp -LR assets node_modules server config.sample.yml package.json LICENSE /var/wiki rm -rf /pipeline - internal/docker-push: username: $DOCKER_HUB_USERNAME @@ -76,15 +76,14 @@ deploy-github: - script: name: package code: | - tar -chzfv wiki-js.tar.gz * -X .build/.deployexclude - tar -chzfv node_modules.tar.gz node_modules - SEMVER_LAST=`npm show wiki.js version` - chmod +x ./.build/semver_next.sh - SEMVER_NEXT=`./.build/semver_next.sh -p $SEMVER_LAST` + tar -chzf wiki-js.tar.gz assets server config.sample.yml package.json wiki.js LICENSE + tar -chzf node_modules.tar.gz node_modules + SEMVER_NEXT=`curl --request POST --url https://beta.requarks.io/api/version/increment --header "authorization: $WIKIJSORG_TOKEN" --header 'cache-control: no-cache' --header 'content-type: application/json' --data '{"channel": "stable"}'` - github-create-release: token: $GITHUB_TOKEN tag: "v${SEMVER_NEXT}" prerelease: true + title: "$SEMVER_NEXT Release" - github-upload-asset: token: $GITHUB_TOKEN file: wiki-js.tar.gz diff --git a/yarn.lock b/yarn.lock index 8420b745..5d936277 100644 --- a/yarn.lock +++ b/yarn.lock @@ -262,7 +262,7 @@ ansi-escape-sequences@^3.0.0: dependencies: array-back "^1.0.3" -ansi-escapes@^1.1.0, ansi-escapes@^1.4.0: +ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -270,7 +270,7 @@ ansi-escapes@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" -ansi-regex@^2.0.0, ansi-regex@^2.1.1: +ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -282,12 +282,18 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.0.0, ansi-styles@^3.1.0: +ansi-styles@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750" dependencies: color-convert "^1.0.0" +ansi-styles@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + ansi@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" @@ -313,16 +319,16 @@ apollo-server-core@^1.1.0: dependencies: apollo-tracing "^0.0.7" -apollo-server-express@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.1.0.tgz#48d5027b41698c386e415cf182924c2a79da0497" +apollo-server-express@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.1.2.tgz#6933c77fe5dfb9a7f30dd393239ad9953a613cd9" dependencies: apollo-server-core "^1.1.0" - apollo-server-module-graphiql "^1.1.0" + apollo-server-module-graphiql "^1.1.2" -apollo-server-module-graphiql@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.0.tgz#f10333e50659d61dc48e2ed6afac6f313b1f418b" +apollo-server-module-graphiql@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.2.tgz#49a154cf80e984acb082bd0096175b561e1bfbcc" apollo-tracing@^0.0.7: version "0.0.7" @@ -683,13 +689,12 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@20.0.3, babel-jest@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-20.0.3.tgz#e4a03b13dc10389e140fc645d09ffc4ced301671" +babel-jest@21.0.0, babel-jest@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.0.0.tgz#4f636a7dce105aa5753d5f3dde4422ff50c1d6c5" dependencies: - babel-core "^6.0.0" babel-plugin-istanbul "^4.0.0" - babel-preset-jest "^20.0.3" + babel-preset-jest "^21.0.0" babel-messages@^6.23.0: version "6.23.0" @@ -711,9 +716,9 @@ babel-plugin-istanbul@^4.0.0: istanbul-lib-instrument "^1.7.2" test-exclude "^4.1.1" -babel-plugin-jest-hoist@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-20.0.3.tgz#afedc853bd3f8dc3548ea671fbe69d03cc2c1767" +babel-plugin-jest-hoist@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.0.0.tgz#aa2dbab7b0d58fa635640efd53aab730be7b3273" babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" @@ -947,11 +952,11 @@ babel-preset-es2015@6.24.1: babel-plugin-transform-es2015-unicode-regex "^6.24.1" babel-plugin-transform-regenerator "^6.24.1" -babel-preset-jest@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-20.0.3.tgz#cbacaadecb5d689ca1e1de1360ebfc66862c178a" +babel-preset-jest@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.0.0.tgz#13a8d82e999aa49f8b2dc14d0023d362f2e4ba23" dependencies: - babel-plugin-jest-hoist "^20.0.3" + babel-plugin-jest-hoist "^21.0.0" babel-register@^6.24.1: version "6.24.1" @@ -1221,12 +1226,6 @@ browser-resolve@^1.11.2: dependencies: resolve "1.1.7" -bser@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169" - dependencies: - node-int64 "^0.4.0" - bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -1249,9 +1248,9 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bull@3.0.0-rc.7: - version "3.0.0-rc.7" - resolved "https://registry.yarnpkg.com/bull/-/bull-3.0.0-rc.7.tgz#6e16c9fd43552045820153abbbfc03016d4ab9dd" +bull@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bull/-/bull-3.0.0.tgz#39e76f9b3942dfe5d4209ab49e141ecd837d9430" dependencies: bluebird "^3.5.0" cron-parser "^2.4.1" @@ -1372,6 +1371,14 @@ chalk@^2.0.0, chalk@^2.0.1: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + character-parser@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" @@ -1520,7 +1527,7 @@ codemirror@*: version "5.27.4" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.27.4.tgz#0e817c839bfea9959dd16cd48ae14acc0e43c3b6" -color-convert@^1.0.0: +color-convert@^1.0.0, color-convert@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" dependencies: @@ -1846,7 +1853,7 @@ de-indent@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" -debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.3.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6: +debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: @@ -1864,6 +1871,12 @@ debug@2.6.7: dependencies: ms "2.0.0" +debug@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.1.tgz#0564c612b521dc92d9f2988f0549e34f9c98db64" + dependencies: + ms "2.0.0" + debug@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" @@ -2284,13 +2297,13 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.1.tgz#99cd7eafcffca2ff99a5c8f5f2a474d6364b4bd3" +eslint@4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.6.1.tgz#ddc7fc7fd70bf93205b0b3449bb16a1e9e7d4950" dependencies: ajv "^5.2.0" babel-code-frame "^6.22.0" - chalk "^1.1.3" + chalk "^2.1.0" concat-stream "^1.6.0" cross-spawn "^5.1.0" debug "^2.6.8" @@ -2321,6 +2334,7 @@ eslint@4.4.1: progress "^2.0.0" require-uncached "^1.0.3" semver "^5.3.0" + strip-ansi "^4.0.0" strip-json-comments "~2.0.1" table "^4.0.1" text-table "~0.2.0" @@ -2443,6 +2457,17 @@ expand-template@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a" +expect@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-21.0.0.tgz#55fbb07e989479863663975ae8e9ec51753c99ca" + dependencies: + ansi-styles "^3.2.0" + jest-diff "^21.0.0" + jest-get-type "^21.0.0" + jest-matcher-utils "^21.0.0" + jest-message-util "^21.0.0" + jest-regex-util "^21.0.0" + express-brute-redis@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/express-brute-redis/-/express-brute-redis-0.0.1.tgz#0f4c833a5c3c2505c0c5c9ba55108e224a247ef8" @@ -2629,12 +2654,6 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" -fb-watchman@^1.8.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-1.9.2.tgz#a24cf47827f82d38fb59a69ad70b76e3b6ae7383" - dependencies: - bser "1.0.2" - fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -2867,7 +2886,7 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fsevents@^1.0.0: +fsevents@^1.0.0, fsevents@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4" dependencies: @@ -2899,9 +2918,9 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -fuse-box@2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.2.tgz#eec3c4c49496dbfca08d43179a189fbfbce67fda" +fuse-box@2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.3.tgz#411cc10f55329a462a5e1641d6864953e89ec79a" dependencies: acorn "^5.0.3" acorn-es7 "^0.1.0" @@ -3136,7 +3155,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" -graphql-tools@1.2.1, graphql-tools@^1.1.0: +graphql-tools@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.2.tgz#ff791e91b78e05eec18a32716a7732bc7bf5cb4d" + dependencies: + deprecated-decorator "^0.1.6" + uuid "^3.0.1" + optionalDependencies: + "@types/graphql" "^0.9.0" + +graphql-tools@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.1.tgz#8d462abaa7b0f3bb2aa633df1e7a848720197671" dependencies: @@ -3145,9 +3173,9 @@ graphql-tools@1.2.1, graphql-tools@^1.1.0: optionalDependencies: "@types/graphql" "^0.9.0" -graphql@0.10.5: - version "0.10.5" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" +graphql@0.11.2: + version "0.11.2" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.2.tgz#13edb9f982f3571dd68ec4e9f3d6aca7e1ba57ef" dependencies: iterall "^1.1.0" @@ -3333,9 +3361,9 @@ i18next-xhr-backend@1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.2.tgz#7aa766292c46ca83ff6477bb55074b363a646a62" -i18next@8.4.3: - version "8.4.3" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-8.4.3.tgz#36b6ff516c4f992010eedcce24a36c4609e8c7dc" +i18next@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-9.0.0.tgz#a89ab0481b5b6b3964f55b12f03de9063d8f4500" iconv-lite@0.4.13: version "0.4.13" @@ -3391,9 +3419,9 @@ infinity-agent@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/infinity-agent/-/infinity-agent-2.0.3.tgz#45e0e2ff7a9eb030b27d62b74b3744b7a7ac4216" -inflection@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.10.0.tgz#5bffcb1197ad3e81050f8e17e21668087ee9eb2f" +inflection@1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" inflight@^1.0.4: version "1.0.6" @@ -3809,216 +3837,230 @@ jackpot@>=0.0.6: dependencies: retry "0.6.0" -jest-changed-files@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8" +jest-changed-files@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.0.0.tgz#fa7cfc353187e2fb852dd5830e8d09068dde78d1" + dependencies: + throat "^4.0.0" -jest-cli@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.4.tgz#e532b19d88ae5bc6c417e8b0593a6fe954b1dc93" +jest-cli@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.0.0.tgz#25fc36badb6a78dc180a67f02c037c0209d12a98" dependencies: - ansi-escapes "^1.4.0" - callsites "^2.0.0" - chalk "^1.1.3" + ansi-escapes "^2.0.0" + chalk "^2.0.1" + glob "^7.1.2" graceful-fs "^4.1.11" is-ci "^1.0.10" istanbul-api "^1.1.1" istanbul-lib-coverage "^1.0.1" istanbul-lib-instrument "^1.4.2" istanbul-lib-source-maps "^1.1.0" - jest-changed-files "^20.0.3" - jest-config "^20.0.4" - jest-docblock "^20.0.3" - jest-environment-jsdom "^20.0.3" - jest-haste-map "^20.0.4" - jest-jasmine2 "^20.0.4" - jest-message-util "^20.0.3" - jest-regex-util "^20.0.3" - jest-resolve-dependencies "^20.0.3" - jest-runtime "^20.0.4" - jest-snapshot "^20.0.3" - jest-util "^20.0.3" + jest-changed-files "^21.0.0" + jest-config "^21.0.0" + jest-environment-jsdom "^21.0.0" + jest-haste-map "^21.0.0" + jest-message-util "^21.0.0" + jest-regex-util "^21.0.0" + jest-resolve-dependencies "^21.0.0" + jest-runner "^21.0.0" + jest-runtime "^21.0.0" + jest-snapshot "^21.0.0" + jest-util "^21.0.0" micromatch "^2.3.11" node-notifier "^5.0.2" pify "^2.3.0" slash "^1.0.0" string-length "^1.0.1" - throat "^3.0.0" + strip-ansi "^4.0.0" which "^1.2.12" worker-farm "^1.3.1" yargs "^7.0.2" -jest-config@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-20.0.4.tgz#e37930ab2217c913605eff13e7bd763ec48faeea" +jest-config@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.0.0.tgz#81dcb20d15971f31bf44a82c6fe85b4423d98d95" dependencies: - chalk "^1.1.3" + chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^20.0.3" - jest-environment-node "^20.0.3" - jest-jasmine2 "^20.0.4" - jest-matcher-utils "^20.0.3" - jest-regex-util "^20.0.3" - jest-resolve "^20.0.4" - jest-validate "^20.0.3" - pretty-format "^20.0.3" - -jest-diff@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-20.0.3.tgz#81f288fd9e675f0fb23c75f1c2b19445fe586617" + jest-environment-jsdom "^21.0.0" + jest-environment-node "^21.0.0" + jest-get-type "^21.0.0" + jest-jasmine2 "^21.0.0" + jest-regex-util "^21.0.0" + jest-resolve "^21.0.0" + jest-util "^21.0.0" + jest-validate "^21.0.0" + pretty-format "^21.0.0" + +jest-diff@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.0.0.tgz#b996ba2963a783125e6bc59fd5623bce67df7f17" dependencies: - chalk "^1.1.3" + chalk "^2.0.1" diff "^3.2.0" - jest-matcher-utils "^20.0.3" - pretty-format "^20.0.3" + jest-get-type "^21.0.0" + pretty-format "^21.0.0" -jest-docblock@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712" +jest-docblock@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.0.0.tgz#7dd57568543aec98910f749540afc15fab53a27f" -jest-environment-jsdom@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz#048a8ac12ee225f7190417713834bb999787de99" +jest-environment-jsdom@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.0.0.tgz#1d53e34b1656254b8c539700e35360d8f8ebb579" dependencies: - jest-mock "^20.0.3" - jest-util "^20.0.3" + jest-mock "^21.0.0" + jest-util "^21.0.0" jsdom "^9.12.0" -jest-environment-node@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-20.0.3.tgz#d488bc4612af2c246e986e8ae7671a099163d403" +jest-environment-node@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.0.0.tgz#ffc781b82569f3f4bc2d8fb8f1ea7373cb11f043" dependencies: - jest-mock "^20.0.3" - jest-util "^20.0.3" + jest-mock "^21.0.0" + jest-util "^21.0.0" -jest-haste-map@^20.0.4: - version "20.0.5" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.5.tgz#abad74efb1a005974a7b6517e11010709cab9112" +jest-get-type@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.0.0.tgz#ed8667533c0a24a4feebbf492661f23abac3620b" + +jest-haste-map@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.0.0.tgz#1f099ff6aedb52ec55fa9773ce26e4bbb00b0580" dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" - jest-docblock "^20.0.3" + jest-docblock "^21.0.0" micromatch "^2.3.11" - sane "~1.6.0" + sane "^2.0.0" worker-farm "^1.3.1" -jest-jasmine2@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-20.0.4.tgz#fcc5b1411780d911d042902ef1859e852e60d5e1" +jest-jasmine2@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.0.0.tgz#539725989e45ab0b00029fcf37bc679aa39c2941" dependencies: - chalk "^1.1.3" + chalk "^2.0.1" + expect "^21.0.0" graceful-fs "^4.1.11" - jest-diff "^20.0.3" - jest-matcher-utils "^20.0.3" - jest-matchers "^20.0.3" - jest-message-util "^20.0.3" - jest-snapshot "^20.0.3" - once "^1.4.0" - p-map "^1.1.1" - -jest-matcher-utils@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-20.0.3.tgz#b3a6b8e37ca577803b0832a98b164f44b7815612" - dependencies: - chalk "^1.1.3" - pretty-format "^20.0.3" + jest-diff "^21.0.0" + jest-matcher-utils "^21.0.0" + jest-message-util "^21.0.0" + jest-snapshot "^21.0.0" + p-cancelable "^0.3.0" -jest-matchers@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-matchers/-/jest-matchers-20.0.3.tgz#ca69db1c32db5a6f707fa5e0401abb55700dfd60" +jest-matcher-utils@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.0.0.tgz#493dc25b9ed6a23a61802ca20656f0f1c16f15b1" dependencies: - jest-diff "^20.0.3" - jest-matcher-utils "^20.0.3" - jest-message-util "^20.0.3" - jest-regex-util "^20.0.3" + chalk "^2.0.1" + jest-get-type "^21.0.0" + pretty-format "^21.0.0" -jest-message-util@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-20.0.3.tgz#6aec2844306fcb0e6e74d5796c1006d96fdd831c" +jest-message-util@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.0.0.tgz#cd49c2e91d7a227e622884c418185a1a7cbe1fd6" dependencies: - chalk "^1.1.3" + chalk "^2.0.1" micromatch "^2.3.11" slash "^1.0.0" -jest-mock@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-20.0.3.tgz#8bc070e90414aa155c11a8d64c869a0d5c71da59" +jest-mock@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.0.0.tgz#948fdbb44ef702ca998e078ca62b4968780e102e" -jest-regex-util@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-20.0.3.tgz#85bbab5d133e44625b19faf8c6aa5122d085d762" +jest-regex-util@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.0.0.tgz#f13c382a1c55515c20471390ab38e5d71cbd320e" -jest-resolve-dependencies@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-20.0.3.tgz#6e14a7b717af0f2cb3667c549de40af017b1723a" +jest-resolve-dependencies@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.0.0.tgz#09dfd9654a8af92880a2f66076871d48810bd48d" dependencies: - jest-regex-util "^20.0.3" + jest-regex-util "^21.0.0" -jest-resolve@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-20.0.4.tgz#9448b3e8b6bafc15479444c6499045b7ffe597a5" +jest-resolve@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.0.0.tgz#04d3939203633cc57ae8219b34ad42687dd8d111" dependencies: browser-resolve "^1.11.2" + chalk "^2.0.1" is-builtin-module "^1.0.0" - resolve "^1.3.2" -jest-runtime@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-20.0.4.tgz#a2c802219c4203f754df1404e490186169d124d8" +jest-runner@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.0.0.tgz#8969dd22ff73911c84043cf16b6cfadf609f3d1f" + dependencies: + jest-config "^21.0.0" + jest-docblock "^21.0.0" + jest-haste-map "^21.0.0" + jest-jasmine2 "^21.0.0" + jest-message-util "^21.0.0" + jest-runtime "^21.0.0" + jest-util "^21.0.0" + pify "^2.3.0" + throat "^3.0.0" + worker-farm "^1.3.1" + +jest-runtime@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.0.0.tgz#54af290dc664a49ddc251c7d7ce1a5661afc1ead" dependencies: babel-core "^6.0.0" - babel-jest "^20.0.3" + babel-jest "^21.0.0" babel-plugin-istanbul "^4.0.0" - chalk "^1.1.3" + chalk "^2.0.1" convert-source-map "^1.4.0" graceful-fs "^4.1.11" - jest-config "^20.0.4" - jest-haste-map "^20.0.4" - jest-regex-util "^20.0.3" - jest-resolve "^20.0.4" - jest-util "^20.0.3" + jest-config "^21.0.0" + jest-haste-map "^21.0.0" + jest-regex-util "^21.0.0" + jest-resolve "^21.0.0" + jest-util "^21.0.0" json-stable-stringify "^1.0.1" micromatch "^2.3.11" + slash "^1.0.0" strip-bom "3.0.0" + write-file-atomic "^2.1.0" yargs "^7.0.2" -jest-snapshot@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-20.0.3.tgz#5b847e1adb1a4d90852a7f9f125086e187c76566" +jest-snapshot@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.0.0.tgz#00b582b13ef42112bd431b498e37f7829b30cd66" dependencies: - chalk "^1.1.3" - jest-diff "^20.0.3" - jest-matcher-utils "^20.0.3" - jest-util "^20.0.3" + chalk "^2.0.1" + jest-diff "^21.0.0" + jest-matcher-utils "^21.0.0" + mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^20.0.3" + pretty-format "^21.0.0" -jest-util@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-20.0.3.tgz#0c07f7d80d82f4e5a67c6f8b9c3fe7f65cfd32ad" +jest-util@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.0.0.tgz#62b3a3ec3ff91022ef7e1ffbcf3293424715919f" dependencies: - chalk "^1.1.3" + callsites "^2.0.0" + chalk "^2.0.1" graceful-fs "^4.1.11" - jest-message-util "^20.0.3" - jest-mock "^20.0.3" - jest-validate "^20.0.3" - leven "^2.1.0" + jest-message-util "^21.0.0" + jest-mock "^21.0.0" + jest-validate "^21.0.0" mkdirp "^0.5.1" -jest-validate@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-20.0.3.tgz#d0cfd1de4f579f298484925c280f8f1d94ec3cab" +jest-validate@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.0.0.tgz#f906d54eca2a485ffbfb2d8a7d58831c026e6dd5" dependencies: - chalk "^1.1.3" - jest-matcher-utils "^20.0.3" + chalk "^2.0.1" + jest-get-type "^21.0.0" leven "^2.1.0" - pretty-format "^20.0.3" + pretty-format "^21.0.0" -jest@20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac" +jest@21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-21.0.0.tgz#6b1536b73ea1a4fa2f0904d26f32949c39cf4690" dependencies: - jest-cli "^20.0.4" + jest-cli "^21.0.0" jimp@0.2.28: version "0.2.28" @@ -4712,9 +4754,9 @@ markdown-it-anchor@4.0.0: dependencies: string "^3.3.3" -markdown-it-attrs@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-1.0.0.tgz#31698fbec4c54fb0cbac6e344ada6f02d682a4a1" +markdown-it-attrs@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-1.1.0.tgz#6f5c7bc8d0c29e628ef335bcc1e0bf454d204f5d" markdown-it-emoji@1.4.0: version "1.4.0" @@ -4742,9 +4784,9 @@ markdown-it-task-lists@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/markdown-it-task-lists/-/markdown-it-task-lists-2.0.1.tgz#a9ce7f55cde9f45e0fca629071d11d3fd5a69416" -markdown-it@8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.2.tgz#df4b86530d17c3bc9beec3b68d770b92ea17ae96" +markdown-it@8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.0.tgz#e2400881bf171f7018ed1bd9da441dac8af6306d" dependencies: argparse "^1.0.7" entities "~1.1.1" @@ -4756,9 +4798,9 @@ marked@*: version "0.3.6" resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" -mathjax-node@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.1.1.tgz#c9cb4c4d55f08e5116c9c49d01a8d226404a0405" +mathjax-node@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.2.0.tgz#538d01f85ca18b90f3cc6ce68c7caeed44bb9f7f" dependencies: jsdom "7.0 - 9.12" mathjax "*" @@ -4843,7 +4885,7 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -"mime-db@>= 1.27.0 < 2", mime-db@~1.29.0: +"mime-db@>= 1.27.0 < 2": version "1.29.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878" @@ -4851,11 +4893,15 @@ mime-db@~1.27.0: version "1.27.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" -mime-types@2.1.16: - version "2.1.16" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23" +mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + +mime-types@2.1.17: + version "2.1.17" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: - mime-db "~1.29.0" + mime-db "~1.30.0" mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.6, mime-types@~2.1.7: version "2.1.15" @@ -5371,10 +5417,6 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" -p-map@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a" - p-timeout@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.0.tgz#9820f99434c5817868b4f34809ee5291660d5b6c" @@ -5648,13 +5690,13 @@ pg-pool@1.*: generic-pool "2.4.3" object-assign "4.1.0" -pg-pool@2.*: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.1.tgz#8b12541df271b57f7020c50a3f5566471f82c77e" +pg-pool@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257" -pg-promise@6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.5.0.tgz#ffcf1dbb2957700ddb9f2c6dd7c647d714a11ee6" +pg-promise@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.5.1.tgz#d71d262978ea5a8e9ea9be1325e25e4841201c30" dependencies: manakin "~0.5.1" pg "~6.4.2" @@ -5671,16 +5713,25 @@ pg-types@1.*: postgres-date "~1.0.0" postgres-interval "^1.1.0" -pg@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.1.2.tgz#5dce20f3ed680651444dc311061d719cc920c3d8" +pg-types@~1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.1.tgz#d64087e3903b58ffaad279e7595c52208a14c3d2" + dependencies: + postgres-array "~1.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.0" + postgres-interval "^1.1.0" + +pg@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.3.0.tgz#275e27466e54a645f6b4a16f6acadf6b849ad83b" dependencies: buffer-writer "1.0.1" js-string-escape "1.0.1" packet-reader "0.3.1" pg-connection-string "0.1.3" - pg-pool "2.*" - pg-types "1.*" + pg-pool "~2.0.3" + pg-types "~1.12.1" pgpass "1.x" semver "4.3.2" @@ -5881,12 +5932,12 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -pretty-format@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-20.0.3.tgz#020e350a560a1fe1a98dc3beb6ccffb386de8b14" +pretty-format@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.0.0.tgz#bea1522c4c47e49b44db5b6fbf83e7737251f305" dependencies: - ansi-regex "^2.1.1" - ansi-styles "^3.0.0" + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" pretty-time@^0.2.0: version "0.2.0" @@ -6034,9 +6085,9 @@ pug-linker@^3.0.2: pug-error "^1.3.2" pug-walk "^1.1.4" -pug-lint@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/pug-lint/-/pug-lint-2.4.0.tgz#1f584c1624fac48e5a0d03e40823caef736702e0" +pug-lint@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/pug-lint/-/pug-lint-2.5.0.tgz#4419ee301aeca45f54061b0eca4a9a471f3aa9a9" dependencies: acorn "^4.0.1" commander "^2.9.0" @@ -6421,7 +6472,7 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.3.3: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" dependencies: @@ -6496,17 +6547,19 @@ safe-json-stringify@~1: version "1.0.4" resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz#81a098f447e4bbc3ff3312a243521bc060ef5911" -sane@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-1.6.0.tgz#9610c452307a135d29c1fdfe2547034180c46775" +sane@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-2.0.0.tgz#99cb79f21f4a53a69d4d0cd957c2db04024b8eb2" dependencies: anymatch "^1.3.0" exec-sh "^0.2.0" - fb-watchman "^1.8.0" + fb-watchman "^2.0.0" minimatch "^3.0.2" minimist "^1.1.1" walker "~1.0.5" watch "~0.10.0" + optionalDependencies: + fsevents "^1.1.1" sass-graph@^2.1.1: version "2.2.4" @@ -6654,17 +6707,17 @@ send@0.15.4: range-parser "~1.2.0" statuses "~1.3.1" -sequelize@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.5.0.tgz#d8a5b1b641728890fa96761b1704203e7ae30ebb" +sequelize@4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.8.0.tgz#1987a97deceb749da7e25cd27059adb69dbf81c2" dependencies: bluebird "^3.4.6" cls-bluebird "^2.0.1" - debug "^2.3.0" + debug "^3.0.0" depd "^1.1.0" dottie "^2.0.0" generic-pool "^3.1.6" - inflection "1.10.0" + inflection "1.12.0" lodash "^4.17.1" moment "^2.13.0" moment-timezone "^0.5.4" @@ -6673,7 +6726,7 @@ sequelize@4.5.0: terraformer-wkt-parser "^1.1.2" toposort-class "^1.0.1" uuid "^3.0.0" - validator "^6.3.0" + validator "^8.0.0" wkx "^0.4.1" serve-favicon@2.4.3: @@ -7125,9 +7178,9 @@ tar-stream@^1.1.2: readable-stream "^2.0.0" xtend "^4.0.0" -tar@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.0.0.tgz#aa7d58cfb750cc919d9da1d3319f9ccabac339e0" +tar@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.0.1.tgz#3f5b2e5289db30c2abe4c960f43d0d9fff96aaf0" dependencies: chownr "^1.0.1" minipass "^2.0.2" @@ -7194,6 +7247,10 @@ throat@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836" +throat@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" + through2@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" @@ -7326,9 +7383,9 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844" +typescript@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34" typical@^2.6.0, typical@^2.6.1: version "2.6.1" @@ -7342,9 +7399,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" -uglify-es@3.0.27: - version "3.0.27" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.27.tgz#391790388f369196be23a49caeb0d5c424fa774e" +uglify-es@3.0.28: + version "3.0.28" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.28.tgz#1cdedbbcdb7865223065281ad7b2347629851d4b" dependencies: commander "~2.11.0" source-map "~0.5.1" @@ -7507,18 +7564,14 @@ validator-as-promised@1.0.2: lodash "^4.14.0" validator "^5.5.0" -validator@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-8.0.0.tgz#00d6ec230ab5d3353ab1174162a96462b947bdbd" +validator@8.1.0, validator@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-8.1.0.tgz#89cf6b512ff71eba886afd8d10d47f8dc800eac0" validator@^5.5.0: version "5.7.0" resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c" -validator@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-6.3.0.tgz#47ce23ed8d4eaddfa9d4b8ef0071b6cf1078d7c8" - vary@^1, vary@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" @@ -7533,9 +7586,9 @@ vasync@^1.6.4: dependencies: verror "1.6.0" -vee-validate@2.0.0-rc.13: - version "2.0.0-rc.13" - resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.13.tgz#b2aadf729c277d7a908bec5d71169d02c54b7890" +vee-validate@2.0.0-rc.14: + version "2.0.0-rc.14" + resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.14.tgz#ecbd3ddff33fa6a42ebb4a468c343e1eb5d2b38f" verror@1.3.6: version "1.3.6" @@ -7598,9 +7651,9 @@ vue@2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/vue/-/vue-2.4.2.tgz#a9855261f191c978cc0dc1150531b8d08149b58c" -vuex@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.3.1.tgz#cde8e997c1f9957719bc7dea154f9aa691d981a6" +vuex@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.4.0.tgz#e1d0430646282b40007fdd06ec6ae88a9f5a1e14" vxx@^1.2.0: version "1.2.2" @@ -7759,6 +7812,14 @@ write-file-atomic@^1.1.2: imurmurhash "^0.1.4" slide "^1.1.5" +write-file-atomic@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" From dd73b036d295f98a0e6522170e6db81d993ea9b7 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Mon, 4 Sep 2017 13:05:13 -0400 Subject: [PATCH 17/33] fix: git config typo --- server/modules/git.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/modules/git.js b/server/modules/git.js index f34ff829..68f78e1f 100644 --- a/server/modules/git.js +++ b/server/modules/git.js @@ -54,8 +54,8 @@ module.exports = { self.onReady = (wiki.IS_MASTER) ? self._initRepo() : Promise.resolve() if (wiki.config.git) { - self._repo.branch = appconfig.git.branch || 'master' - self._signature.email = appconfig.git.serverEmail || 'wiki@example.com' + self._repo.branch = wiki.config.git.branch || 'master' + self._signature.email = wiki.config.git.serverEmail || 'wiki@example.com' } return self From 52630127cd4eb3ff1a2158b73c80fedf8c0d0087 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 10 Sep 2017 01:41:22 -0400 Subject: [PATCH 18/33] feat: login page UI --- assets/images/bg.jpg | Bin 0 -> 303916 bytes assets/images/bg_1.jpg | Bin 141800 -> 0 bytes assets/images/bg_2.jpg | Bin 147770 -> 0 bytes assets/images/bg_3.jpg | Bin 137291 -> 0 bytes client/index.js | 17 +- client/js/app.js | 38 +- client/js/app.old.js | 153 +++++ client/js/helpers/index.js | 1 + client/js/login.js | 7 - client/scss/app.scss | 3 +- client/scss/components/button.scss | 10 +- client/scss/pages/_login.scss | 465 ++++++---------- package.json | 30 +- server/master.js | 4 +- server/modules/config.js | 6 +- server/views/auth/login.pug | 125 ++--- server/views/error.pug | 28 +- server/views/layout.pug | 31 +- server/views/master.pug | 30 + tools/fuse.js | 3 +- yarn.lock | 864 +++++++++++++++++------------ 21 files changed, 943 insertions(+), 872 deletions(-) create mode 100644 assets/images/bg.jpg delete mode 100644 assets/images/bg_1.jpg delete mode 100644 assets/images/bg_2.jpg delete mode 100644 assets/images/bg_3.jpg create mode 100644 client/js/app.old.js delete mode 100644 client/js/login.js create mode 100644 server/views/master.pug diff --git a/assets/images/bg.jpg b/assets/images/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d601fcfecd6520be51f2c3ee4cd3b1ed7416df94 GIT binary patch literal 303916 zcmb4qi(iuW9{jK=4vX(!ABqDqHP#fRMZv zFu=6ah6qj(4M^R(Y|GSUIG37Pt)1;`-PUEd*0$5mcFynV_j>*QfFJ7X^CiHV7Xq@-k+MueYy5~eRp z`4ep=lfzlbWV3jg8`kgy&t7_!%Pc z88M&D7yp01{&yB2LO9?F^AZdZ0Ew6-M9lvtfTsWeT!KMg!2f$;Kwt?Lm+%CHKBYZ= z^7!@t9->i!kDvbUGk~xJ1Ay=n7=84^mu2S+YORZ#OO%5#{FwmWUE^;wOle%7oYRQ9 z!6~oQ)?_KjuLSL>viY%E2{>V+LlFQlDBVSl&nm3}Q}y0`rI6aIFw%|>*&F6HZIiNl zer;A~IG7%3-0m0{948F26oY-G>TnqbXjQa;xGLiQWPVDE#%C|F)3n7;remucSTvlt zsaaOiUs_@^UK#dsnhQNw_1fbVC5mRFk~$d#5t12J(~&3!fa&R)s7!>lF>uT*w`m{0 z%y@sW#4~*yS=sqs`U(F;1S-il;N42tlMu17LO-)2ER|iC*V##wlN;&kF)b2qOVxMS z>14W^0b$eOd`MoH!kewnvVuO7h0LLna6X&Jk4rHO;0lP{2i&%nA08Z@%buJ0W@bHe z;owQ*MWTljYq8K$J}mo~IRUx`$l;DVqzbemAC{e z(5GD-vm+FPj8eoQ6;qPyi}p++ zj?EcndC%jpbV$TeeSN=nZa-mt)>wTha#T^IHS?y9b<34S%v0nK%Vsd?=@}{X@_wnONn>nVO{UvbiHbx+ zVgM-$#CK0#TzeE4E%&mWJC55Y>1NM-v|z?2mk^BidHnmh90X8#?&{HRtP#PTjCD^>m6(b3)0fe+tSOUkOJuxmU`T90Zl zfE7T7J}cxfRR&{a>{!{?b2lAxJ2MlKGZ#TbplmS*L$0HWyQknXQaqfW9=cyf&Uc5x zy^}Z#0%8pgrXCVBvDutaFd5jNpouE!IBrt@Pupk6-t{6i)fEr-_DAbgM4Zo(`gCau zgF)Bxn|S*D+A?xGD`fo-hmErZ|#+9*^2{Tjq}*G&T@=)4DZv_l$X|5kh!nME$Hu8lUc!m4yY#7$waV%>BsR+W;b7$2~LQq#$dj`GF+J&SYK%Q7$; z?fXNe6Dh4rNUo=1f_!ekOff_njg(M}O9g6B7 zyq~J^P*%FAR>6z&!^b31{?J6Uz7%anE$H1X1Nc~ehWBO}H~gNk$@2}2VOp`7V|E>} zdy%s6mSogc1`oMzD#AnY`g~lJKI{{Py?h#93*hf-jb`NutZe72i*$8QLUEN9t-dBi zUYM6J$wbJN!PQ`+0lmvoGLyuX8@)#JSPxM)rG@u%8Emg84k2(>gycah8V&2x&VIeLSZ=)Zs^`jR5_KXNJCYuiM)??=ewo1U*1sL+hb0vR zOua+xVy7@vWuDkoZ0X4iN_rruSUf6G+&$8Dryhuki}1ti*IfzXc%0#;VWLc6_DXIv z1gf&86~bVegi(x3B-%03|N$nVkT@!snNw&Xv?IGs?o`N!G?3ceLz*7Og#Y%JV6lVWBd9_ zIP^+w-wbx4tA4ckNREZ#a8@$dq!Zf@C8bYJdN)k>=&+xfV-6oURR`5qc`&@`@&S&= zBu4@x@m75WyS2~DwoXQc>Y;c8n&H@!C88k6sAyJ{nD$_>-7FPsTOvJilKo}IiE^vI zsdFNBa*!80RYY%mmB)6}$S$#Fw+OF~g=$;7veOkKJPOqUpz~$lr$1VQcn2D=g+O5> zE`b?PW#2flplvXLP2pll7fB4VjbUe=Vd+Q-$&qw8oXA8+ZJ3s_cW<;}yFN`gn}1nS zy}7YV(wa2CfNicjk4aVmEujcj-D0{O@0~y+-rZYD?JVC(y%GyVNLTd9OSgpeJI5kE zkH%y(BXE^a>C=f#p_(y`)jPyYD*8yQZ<(1h06$Z%H_UXbs=|v+dT}B~0bf}}V3;aWdrt(t0O@kJ zwqf(`VPAUe1I7Jgiu*$o3qxr9B1dgQ6?i4sP+DTd3wTU?*830MH?kjm-x1A-&M^mG zmTH$g*U62AhP+6o$t(6x{>|I1i5}oDQ{ao29)D|JXdsBJ4>J|Y?)C5X5S+cpY8nUW zMS_Vmj)_YxofoxpQwfpkv~lsMq@O5bv5cvrM8J7Fr+h7j0Hf%(CQ{}{HdDXgR;lr)%O9ponx-BaowZj;FN z`l6MDGfHjyRVZMbjgPr4IKYt(BG^_)#-bYz3iZO9jjk*2Nn5@uOPV>ixS89rylkjp z&92pkDG_UcCsgvt`5n(<=T=cOgyq9wm+d|Mu9X4JQC{S_d{1;wY?16+egNla(`k{%~2PVGFuahW3@p_4cQK7|phpRiv z-y2AN`cJ)|4s;Y;)Cc?YyB%lWCo*HhrKTD@ZM4j}z}8gO+VT_i9R;Js`f%v1NEa;0 zp5wQKPEpV7+meTO^rtWg%khVWCWhO_pg}U&;mD)W^aPQkr79VAFlZ@;nbo+MM6YBq zCwMZ^1Y=1$!_&&%Ik`8wy)22n^X!%R^{aO}{r8S86A*OMplxKjSjo*&4_!7-h-?~*}l)t>QIK!kb z+7)C5UBMP|r1I>*Rz^s5QZ2oJjsy3+9%Q@q8p%GR2026d@xMbRS4oD&9$A?C#tKWUbd{USTh`bYu$L)FQ1i}?rdGHErQK%o1-OmIJ#;{UmFS^+c}WFSQpJECev(D zd^mK5+|oC^scdUOeZ@BG!|c~TZ8x!Jvb~zT*6OMSMk2@i{*adx%2Sbdf{xJb>=`w} z@w|Opzqyggtq|L3)P)mj^8CNIyvPh>R*xriL9(#8DOF}@WcM;DECOt&u?Jahr;)On zV(mpJ`%=-)M%NpZ#Og5yC>o>Bk?l|GBC*=B;LGRAm}ih&ZU4{*Gm(}%wPhxk_ zH5)4)uD`)U1{uX$arrA%#GnO#W+D+1ifjx*gh2?tl?}r2TrQG1ABm#{4?uVTl8Njq zm}5bX=Hrr9&!z6W=L_WZ)bx~#t0dQUM$0e#x{e>kzE_^PSR!OB%V>DJhW){_bw|B4 zN9+=>kU!GgCFWvzhd-RoK9aFxamAUe9P2WU9~+yJ*^(jBhu80l?xGg}n^Dh(MIKYA zZsWS53k`+peq;5?nLWjQBm7W2O!l&w61Tb~Wxlqxqv1&BwQw1|$dq4j3Cw5j9;~yz z*x0(C&uJlQo=9DxO=q(Y_h%pi?TGHjnynhO$Xq7OI6b7_8Xr#BZ`kzntksDxq{n4KvAv{K zdv$wi`Nn|?VQw0OY;Vc%V zMjhB26K2@p*1-J1F8-V;%4by2Lpv9f6f4@-r z%e6FjZIKb1Z!Gl+_K(pk?>M#3fWN)H&2f=2(p-p>ed1xL8f8XoR+mG49+Xydp~!wQ zA;5y>UCHU=x#?}Gvhgt$9>}fHV+~_aJkMTcsv6O6=esG$(lW4AV{c{Hwe5Mf6B)6& z&PI<>BPiD7OXdjKUJ!Og#GnSc@zkCzMc>J{Pk%nfCdHOB5|g{5yXwwaFnl_=99mrd z%*($%ZUN5cvp2s|-d&6K0C~4bTB_+UY&NRqufTJOiA8h~#(E@h|D~KXO6RVV?QP#g zwIY-cxmY99MQT-VimkQMK`Js1u4|>9vqcNlFV2y4NtKtvG5Yo_aW%?uet-1y>E7gQ zTOFad3m=1RJS2sMcT7MgE}Mmi3*l}8h08{dqEvf;R$^BXQ7Mux%R1v=Dcb_oCbqNo z^Pv=n zu-WA4dagmC!id;_PV5Z7k^gMR=craWS+LNh(TmIHU)01$FOlzPJhcJ`na|};C#;y@ zQXNb1>l*ZPTir9n_E(-XcjMfT zYq-5mjE~5&B2qHLnyLBv(usPrG>g~AOcu@`hC-9`*Oqn28){Buec-5B;nlP@Jf$xk zBfnV7j}iiAa}1jOWrO$Lla+F$2vj+^5F(+=tK2XiLgk?B>8r04j0XBLYK@^Lt+&{u zpD$dw+oQUq(Qo!eEylULZ2fkIUhnpsCw=6RRXOtG#kn~>u+?Vv(0TcrYx7IP5PU;6 zWOE}jOyq2mV0U9Pm)z!HHRm&%>o+yMx%WRSR0_kmZhIO-Mdsx>?DL{Ad?(&9=C)Y~ z{_|X`sIh>IDhw;|r-f_dm3F+-uF8z(5-3W5K`Y_&59nk9IkU;qRTn|o%7blqV)%`! z_N}%2STYLxLW<7$LRPJYRQn%{tP5@E$V*!brWkNJvQuO$jo8IFCugWWA3c zIUJXrC5nsj&#X~2Xxvslaqi5dlc&=0$K^2vq zrM25`Tn=9m{@*~6B*0}oT|3fS9=lok^_`rR_RYbFnFRuX*_Vl7dP07PTk-m`Z}-V+ ztZj;_thg~5%V?Hlxh=XzLoQ3zn@Apm4E+RnBE^&$pPl{cfGSgMGgVgx4ed47EN8dX zPe+6SR2|C)Vl?JqgSS zz+zB}``{~LQa1=FAgMPiTViAS1M}Mg16&^t8&Ror!QHml$;SI#;r?o0$ZLNpW|dd) z{T(YuU#SydZ4kis5g`#WQ*s2E<3PE%r}5?<(i|R5levU4$i_9W3<8tphyMX1HyF`? zXe>Sc2c?tH9BLU_FkqMKm zXgNrp#j313 z`Sm9{0&WqdBsCwM`_HYih5j&n3yp#QwB-zwW) zRh4sCh(v1Wh|Eyrp6Fqz5EMi>3n&bS^RY=}_gIDD|9eOAW8I#BDGevn*zLtAo2*XD zPlsBpqLbhqGX>gORWScnYmoZh?8AiJ3H^R4hh%AC^fP?sM0$4Sbk5fg8Lo) z_IKSbbhxYrQx#~D<}b_5@X^gd!k{8GRb<4z9H`wn5t|-4vZJsOJkw2=k+JrO>l_;@ zzk*g!vb`OF3l?Tjy_+bKf%xv??3F%TcU5w$8ZW@*!{I(Pb{s@%UYlX*TQKPIyM#5D!8W6dzWmY`}hEwWWhBN28UhcM|2v}n$P_iO<5E4$| z8Rk5`Mx9Ya2-GOXy6tXn?q@$d(AP1{Exx~n1#-MUk$Yq3*!~D(di{Pl9`hTC>#_uQpgYC6>8y#5@QVMd^{pGq-@qCnT!ka zW%(!na{l6%e<7U+E%q6wJNam_A+X+nWWpfxylhs^Mg5^Pu_st*T^AFE zvmCZ+27XxB>oeF)yh?XFPR|Nw&ZIIOl43&U{FTw%p7b6`FED0LG>R)rm-LK#b%r+Y zmBs8sm54Y@r;B7wdC{LyF2h)&Y^t7%EU*;ibD)N*>C%f(qK`rXy;dop4|64KGl(&{ zn^eR4(qhfL-^_k+xBbDM3~}u1_=ODa>7Z+Kb>T8Tg#|FQ5{e2uLjn`kMfmgV{0kSU z?>@UrFrzK0Y&AZ5^{Juootx_3!SU;VubWv?q{kDR>j;fTcp8EOUZTNZ%S2KQ)$v?x zrrNHx3gLKsK07Pcxk8)5L*OyI(`R!z`-5p*dr4j~)|4qvhg;}N^-C{BE2|DkEcEM= z=z;wPk7<89OXaNMA2TiLcWsLy_ReHiGD1RQ&OsEQq?OO;jiKJL4Dgr=KD*`BEl=c0 zKr_dNibg&RS40*fo@?#9f(ZGNbT{A%w-W=WGyD6Q^V`C$_+A<$1|ORI3cf6mk^}m%<}Y z$pQ>3s^h1$7#d|e88j^+bCajP+w+wjng&yiluDnA8HwkmmOfqjl*uKzdzH%NUyOlOBX!psWY<^lT?XgY)6JOX6 zYSxGoWFijOqyfVbj%dJ;(nQuPzA8U!1JZqxC0+uPGugPam0Z)XEU)&xjMfc;%5Pu> zOU&-C(>kogx|VMXE@6reell9r|F)Cb7i(pst&!vxRvh{1g?G<#GXo0+)Mih7>$$ydskjbw41>;YrG;t_WBOZ&3-0S2-hC`8>)IF#O=zBKbe1cAeZ%)18c{`hq+N=e7lVYudB{bh`E zDX}u@MC4_=9fEU06WvG^((5y^)T z1p+sgGEIZM>YhP(T0oW<;%ZokXN zRA6{#L-AOgk*kzTVivMEhW7y;X}X3imo^K8Hhyb9-=>og8+2`6y-{DOxYh4b_c(_1 zxMZ-ud^c0!rwsm0q9q6X@s|1_mxz>`E^ef#&X{rQ-pTsyznPIlDv_mVF*wkM(C4Ds zBDO>}%9!&@6PIu?s4S|rQfzr1cTf6wFculluUf0NS#8z$`h9woT0X^_pJoNp#tEaj z+!ZONNOb!qd#WxbQuRrAYi^Ep@%-a8K%x>(50aqEi`C?a57&5sUz_76_5bIEn z=~66ojh%)+k5Z>%!gEz?A4Gom<+PBLq#*7mgoPK!d*XM;^TE{#C3gGBS03kAi(ikO zJx0jF4N=Xr$Xdf#N^H~Yjr!V5pW9(`*vBQ!Ac%bfX|GJSS@NRcI$BVK#OY`+!N;ty z4V?1876Z;B=3qET$Yw(ULRygwRS5HSt>tVj&+IdUU|_A3N*V~w$BJ_grB7Ij(#ub} z>#}uyJ_p|3`9`8(bf#yxFjKFYkx=csc`3XncHNDt>cv4$OLg zTtW@Nc3Id}f)Kl{*)}ePjkbrpXdfxrs#jLMVG1+Y=#?af8L=WPj!2Q=U^3FzT+aer z-H-@WA^;xsEyZC=A^?%uUNnW&D1JgM64}fc96;ie6G5TE!BtF1Lt#|wN0on4$pP>A z&Bdg=)?JE_K)&&{Uw%)jZY)|NC$b_!6V_2iDwMkLZ>eq-lJPh(K$^rdsEj6@jUeTy zT~K`Xdir?V(E3r?_4sv35O)8tiB{t2Ug-85C}T75>xOm51i{HhClILoY8v3h)>he6 zvS=cGpl1$|;MwpZDS78_hYXD#w!Uz~j5phUPKFex=~M|mDr!k9D3vA*cm`7mAq)%^ zAd*357-z{tr#}y!4@o>c)8}u(h!BZSGzNk286WBDuJ^K;DCwJL<5OWUqY-T@mZoGG@-+p z9MoaIyU%0V=|;ysW!%b$)Ytw#4xK5hMgQx>C=nEKr1@)uyhPZiGVtEIN%Y0 z)Cis(-08E%xgy>KKwFm&tI65Yu65Ks()wvnfOs7KDGGVqea8xV1i9-V0?3-Vl zdoYnT*o|Q~0VDGqSqO~s2a6Cq=s|QG1rU?ho4diYEIk%&Pp&R!f;CJ$dn|4E!P>hI zhO;p8LR@)PENeK+U8ApWP4G;k{d1Zy2lnalmtAc@h}x-@}LMdnrmfI-(^#s4US=2(KT?I^E6{DJ(RteT6D>T&(4{vKwM0_NU9E z+ntN&Wk};@etr_;Oy*+dY^_8`W+2(N9F&XKvrv<)iDt?3+gng*!YeY1&_x*~$YEfx z9!Mm?JPs=nqftOD^~`uw;BbWpI1H>u>XD**lJ?XUeo_+ej1oTE!ifbreYkY08An2w zcKAaca*M%?GO;zX@v8YB{`*mLAf3r&k-!uOS+ILlUY>=Mbcgse{e^uRlkplIL&n2G z5}Y+*1}9oce3blzZ8fs^-PzeiQJAibkLQl1RJz9x30&6%`=<>LqLs$eS;J(Lp{;DG zFq@p2$Drb9$+9%v)M7T-)8iamPJ(Ml>qBe7s08WD;nBO-7LOP5QNWjQ36L&bqjs5R%q zGhqt@w6}A;=0U8Sj>x0pt z)NTcaLq(rkoZB5fvJ%j!9Wor`*ENaQ&8FRdI`DAqbjCn#S^|*3>QxB?HL_VX#s68A z>rA_#GsYZM?67|LTlOTpV3&M$zk3mpmB0>D&GznW|tKQ#EIEHRco(`|q ztsfedy8g*+%IxlK3_f*IORxO6WJMw*W9T4TaRMNVrKF`5U->0_`igSyT~k=NxMBM7 z)kH`>=3~Z2XMw1?0^6W^mft~&J2Bwg<3i&wK#3(80f@NA(O`Y$mo#oggwDa@NW6YP zs)QXF1*ZuY!E^c`gw+o}vFgsFxA^9hUu31S@OX{Sg=+1rFu$ZaCNuFi&D50AXuL~e z2`{u`*Bwo((Q`>#A_LGx11sL)p*JF;a4xA$VHn88*63*^v{YSnrEh?+9`!F%3^?7( z!OHHhJpXFcF$j+Z!U;leOD9^FG)7+ZJ|l{X?wg`Rh1sb6LV|@%i~+-E060|2x{_O& z2rW;7KbcOCfnE~7S@NSD;R1820y@YBhvt;a=Xq90N56Qhf`B+$}yH} z(ZOYqKzgy|=hNrJ8TGXXJ6;oT4bwbH7cX^(# zhB2b*($GYd%ST`fG^-qVGMylVopjVgxAD;RU@Dijx@u_sQ2E+Qt7uFo_7~Z$*=@^{ zZ9=8%EV<Wd8Od@Jx@c#s##f)TsL$@PiU`*&JQ@6thXq2A^A0yp;t}`*;3y@z$1k z(Hw)1<_z78hhvR;EfxeoofmK@fx>NrrlM*+{p^C(r>juhsdoa1!oa+ee&q5{!{yU= zT`PCcX1@7y)7oYfPDD^xUsKSFAM=fA9n!9K`+KZ23s1V7sa~# z$Q9*9R&S&`*xC*f51%@LBvmfO_QmvOg7Nd!!MJHhw?!XC3zChNsuNNp)C z##GJy_u&wqYEyw`2nMG>U?@I9ia*Sgid%PW_tclsA9Pih+L*+fl{YKxR?)y@W20kn ziba?8(v1ui+-7@?_VHr<3E`p$O`+q8jK)#68>q?%ORhu_y~tsvDp6KuLcecEX*e?d zma$OwhSb}9?9hc0Ml1Qx$A5Ui_u4*jc>k3}v4I!Ibsbv=*B_(FwGbeHdU|UXN$3LS zF=dhg{a>h)A^>z*Wu+?StO#UL$BL&PZohZ5{2%`~wEde;F)s;L`RhBKKw>4knN40o zEXW$(SkPNy4P+fg+aDn##PlatsZvX!P2TXmjDJ4mV=CzYg0M1~{$R?oUq-%>8tJmw(5W*88tt{N~M% zRxejc7+80b;JG{Ry#39`vif`HW=!nzE7^{r+Heg?!B!?Bx#Rfg$qj$& z`}h1pbN1#3@6k(}_+_4f*Z(`D`DR0L&yA1&H1zAO%NN!kd;YakU;OuV3t8Embfi42 zR|OEs@RTXDwEp8R#)?!)(aRUU*jKT-bytRaUKbc1OL3j3um1Gd?ZEBJ@3wB*k*&I# z#2(dJ*Pk?9JX$k3*EJur;+PZW1PeXjbA?+eb4`*Vm%EHCoc&>YRp#BX<~-&^D@00$ zYaQMDwK&>2+PP@hocfHi+i%Me_x0%H#_5DU8*7PPM`VcFZWKC57c%J zb-dH}@PlW$drmxk9kmOW>#8d#9uDt?q}9*py5}>dHDjni0-^vGm8m_ZL5}c4PeW%{d^55E16f3Yo5leq{ZNvxY0_={e`k0CS;8C^5O;<1Y`(g%_WDW9_nkoCw|O8VppHWwAyIOR~Fp zcbeMakR!hiOj21=L3y9OZ8g5rCef7>y zU;JMCx!*=!lE=0U@2xc?CgvNchpVeBs6(A8Bewv!K%jqBg{!QJzL-U0L;_S@Hrb8X zKaRnch^6#g3+j{DP0|@_VnFpZ#1lNBm(lljJAU{qpwrS zaVcgWq$ne#FdRBHL-lsqy?qbPZ#ptkajR_l$Sa1^>+~0*-(L9hz;tPw{vy2zOkznb zpT6_<%*sdYa(*J&X+$`(URf+aA{HQ6n;vGr-Y|3WyM2E=aq;G{eN9jV_17y0_bX<{ zr+1%R^UC##jIy~S#?xy>UO{Yw2v8=*bdhe&74;Z;!e-_?Ks|YIo;nI|ZmEU(yxxyGN(9TN~cWKZ1dY z5K&{&k(!)k`51$LibKbvR`=agRKNJ<@s)=T{qZILnWM+wDgDdKL)UhuUVQn^sgBKm zKQ%S_=OZPrtUOL4imGgk)$e{f{PNwpRqxsmAB&}MlFh8gf<%O61^NBBmDz{hdH&sv z;~#ZC+X**Q39ISXi0(0+a6M&j4BaQa+B$#xgTt5R@3gA$93IfyG?qy8{AV@T_YhGd(_?p!1N9rq%qHm*`jOoc^gwf@zhwfh}d3X75A->VVDlOu$M1Y!Q?J7dI%s0O9%j=E4j=$Y2dA??( z6JKAkVvFS4u5}LvF5td-V|_OW%0VCNiNCybWbWOPKM#CDf?H&=bQ0(B7=&d~lZ)a6 za|&<#d~IaoJ1hp^*q@FXQ8FaJK%FP6ICSTgU6)^Y`?uGBephJ5;ym*X1~j{X0sAxW zt^f2ykDfd~9MhquV0tnErBtGRYv%Z^`{zzx+_3rd@WWe+S<4xaNU;Q=qwWifjtUw0 zM2rDKaT0IJ1`gG)soRqBJ?CcK!s^hLz}}a7AKpsSE!0-?LQ5C47h+fULSeBSl^`}E${ zwLic9-OR3@)aj2)UW)=*=jpgez>VGU+NqBGvj`= z>L>Xy1;TKuoW~%D+ER@Q79j}DpB^NP-n!pT_;P2Bi9`5FGgw8oAIT|i_{+-|FLt6V z8#dFaAOnclWInSyiGS$n55IiwPV4*MKU0uXaV+P*Bl|uQ%V?Hd6~M;3!rfYp*-xh* zs){>MU1aYEeKDL!gL|NGPt_5P_**+lioKr3XT@u8n8^)eRG>Vl%Fwp zZs_)@6T6@K{P$fi?ODE)rHe9PKEZQm%}ZZ>cD253Y04`m1WTU*2T|?G8Qf8g9;4}vHLwsu3L1nAK*VV-+TC9)aX zxmKW!7_4vR`qeaa8AJ$=Pmp{ZnShFS@UZVK>)!Q|F7|QZUv9rUgh%7|s!=P^Mn@eE z{z&$N4L{$ETz&u7cHQOK^{-rgb>A7gU*rmiz{h4mBTOctM+SmJ)mWSc-FzY7Rf$F? z4cD&{HEOM?%wGSMKi&Lm$xQF=)GgDyZ_VBR`l@EN;Nrp2Z69TvSXuwzz^Rr!tm)cL z{CVjir(^O}K}q&;@6Y=-P=396Ozm_etnu4 zbXVJW^TX}w;uI%w)F+_ja>kb~7H1Kf{~fDGzH5;~J(;aRB~B_JCi)0qN*r8*xT1WzIsx9(|vF9)Jv;2r*#LiI)Mq#d6J|n^3j2^ zy}zyb?e~}8>Zby<YJbD7XP%*>zKhpC&fW}ByP%_t?~S{d1;*(n!q3C zjl;G?$YpOnJz+YY{Z;T(4)s=;Sk1hf;b<6Telz{X%#_qSLTU-A@uVXX5hp4`6r=de zeB&cw@6m04+*pv2U>l`s-=`-Zjs8gJ5R|RGcmK`0o?%uDYhl~WSRbj$Tm&aU=w2&b zR0M*dKFF*BnglLvnFt2Wurea!(fgmF{Q48YbM0W)??t@iAHH;nH4&sRV1E8g2om2t-NpZFy6 z+OSwfU~pv}INFhuy#av!1TPV$d-JGOb7$MJEapgU$x601g#YaB>C*fN*_D*dz=_ zC9(!zFaGBg_T=VchvqKai@$xP&HLN>4Ya*ETa915B!4A?^4s#Y4bzv8ZvHM~rt=Uu z30<9CtQx*oy4qQ?^V@e1)xY@;tH*V>w>{apqU>AzgMi@Br=xZMnm=5R(=0rTE_X2C z>(R@pwbi6D;l9!$h+hie!czfx`(g7`fzB~!8aS?U;OQ*XY-%;U+OFlyEyAo z=Fe^HymPza_0`ua&OeuPf96uhy4ZKG@=yM;_Hyed*FW=%`oMwB8JkiQ!#ycUDSP| z<>k-6Z;HmsN(C26Zr9xVzg@7-z4*qa+LL>kmpb+7wBy=>|Gamzhi8_# zwP{ZZ#pte2jZ{&c2J;Zq%c>r~3c@xoyujGJJNR4NQE;d7XY_0UP{e0&koeR>Ex@9y zlwR`1KOcB_;m;S}ns(hN>HV?cx99iBL_D+Aii=5yS!RIfVp{Pdo!4Rvd;9uMrjd~|p0+Roa4-+I35*9+Y*zIl7kBY8sV zb9K(~^48OzeG>jGsgIYsWy6lk>wjhKv6cyqr`Wz&$$7p-d%#NyA86z^g(-A&1*fIH zU1(o)@p}j&8$D$|s`jHuG<>xR)A4kw@FkG`mj307&p$eY5rZOilNj07wYo=%Uv1PS(R){Z$_+AARtjr}=&W1Rzc~27}-@01ppyFmznE0fUS99S{%0{y!95 zdt8$D{%(T=O_8f>rep}Dgv=1g5FQZ`<)VU@{rLU$y!eOb^}zT0`MhtR@ALUbC%#_a@%3;2 zFUkMw*3U#~1s+ov8?#C9#(e`gQd!xI%+@J;<5~ZVteIzma+M*R75zA>Up6&TfcRg> z8yl(+)L>20n8SOpkm5h~lm;L}FLGmxK>zJXtUWQcQgO=VLBIoD-+wzk{O1EQ;TVQV zQ$@(Wmcz~Cg+kK|_78VccvyX~ptMWT%IU6Y@>rv`m7#uJR6Oz9-jl!gdFJp%$;YR* zp8fQjtvAXF52aUS9u4pv60xD^>4#MrCwy_z4<4QP>9g;Sec-d@{_{an4lPkJ#jf+RxwL_{o#^e{4$GI<2g?$|9S3 z%2F#Kt4Wk&->&<}hlh@R^ZDyPy}SP3-+p)L_x+!Lot^&2f7kuK&Tsv?haY`@#P9H- zuh)P4!>*eDyms=N2k#Ic73m-1EhYFV=6z2B9uRS9Z3Fk7C+TdebgB%x8Zk} zkxVFA<@eHc7*}5cofHa)Xn2(L@*}k-)U4tLr+IA^u=RtRg*}iq_Sbn6HT*=h-zj%G!@h^Y8mD7Ie$N%oy z_{9f%zqtv0kFlGOJ@Vq%x5u^HfBEFZZ-@T3Zo`KAKmK^+?R6Vp`}CvNUMoremuE33 zb(pojV`ZU#YJii)t1Ws(Z_>!{xc(CYmnH~JckIlL<-0rS0o$0pN1+!}(VMEYm~m&d3Q!C~0gxgs$fBcUjaKu&RS4wqcv&X&@wc*f5 zuwA@6{RAYm7k3HbSVf{_a6h8a2Tu=X+&4j6-%6Z?-%|v zBojtWLKS}T!(n>E_%^@y_E!BE!|eN4;pfAj{PO9O^bd|le17cW5j=;xPiSyrU8-2@ zl}>ioFU7@%dy*U?wjh=k;}H>JVFX;&QF)2;S%{~UP<&;>m%o4e;r`dRN+bSBtq41L zw`Se02a~HgE7b_%s` zEUoXhWy6MFe6x@n9{l|IuJ6A1{Q6t#w|@G~r{R0kKiF_#k!}Zv%muzaJ!8X$0H0WS za-y8bt5MY{DUx?R^KPSNV#??(CxkInZ(?6q^S5`=xl}~9b@DXt9~nqSS$A_I7-N~U zJaIW@mxL--As7PGd4q|%1NmpWXDpo^vSdQo?j@4vjMY!J`|8HnVDwi;zvNU^Z4gLX zTVxtRzuD?^4QM}cvKyy7JfbzJmK5^BTBBAnjjph`ED&nw{E5!kt7^$H_8y{+sIVd) z&gP|O<=5ktS~_B7%BHAmoOKvDM(!8NKzi&w!TGyl4v3Y!!<1d@4;G%-&~bmme_DS& z^q;Q^K6w1jm+K>TeS1APyOT!O@^h2I<;^pN)Lr&wIt||voxOXXda%|D_xyHl03UsK z46|6VZJ_&Fy^6-8TzZB)JK*Z+&`r!<~-THr#&n`je3LTi1O& z^zfr^4mG@XcH43c0Z>oSqv5#ucgwkvD$18x(cs|oZ3Cf8nmX;uqJPmC_^M;l%SXME zOUP8fJsjIB+#;7m7i#DDl6!p%rW%mB`@9BujRsq!4omGrRw(7oFSL0%?o3(FO9DTm z>*l?#o+6XxLBHJknX5l*;|KDH((*E(%-BoG0%MdSG@$7;+M0(4FK7qMmZzK^R~%xk zVpzs98=|!XRzX@V9iE2aR`ttOS;!(dQG*%f#0d}=`fu7{D+@;@rSL7svl-kS-Ys`j z;<6GQZNXbC=$w!Nmd+DOy4LGyMT5&S+qKRYPttzLdT&$P*H^y!_NQ$>{P_C1GY7A{ z{bQ*~-+Z8K+=(xna!(k$GznpcV}xb+@iex-s?322SD_yC({R?nahJU(dHuD~ACi8( z_4Q9bpknbL%a|e({lWViKdhaiZ|sdjb$%C-UE}7yNecL^%Pd5Mf%E`pIsEfaHsxlr zl)}Zvg!f;+*8jo33t*M4rya;nani9}>)(I)@1sF-Gr+A_fA`SunKJuXK!)ggGH%6W z@M2rD_nrVhbw-$;THF52gHjHzEx%W?a;{5E6lO-Jz$ze%jh2b$fYnwGE*9tb5R`ON zB{4HnY3sXdHrzK_jitt#%x>3VI+c-zvpludfE+OKKD}U@h%@dDMklNhU@aVHbYU-; zk6=VIpRS?*JtM!FJe7|!zL=RCwe{Jb&K!llyw8KaSwH;Lu4DrGVE*2E7L@44Ld1MM zH!gI=ONPBza!IGIj~6I}dW0w?gPO8i0mYOx3@YvBVP!ji-0g7DE}<_Z+ua(?#VN?-__X`OB(=tI68GZH@@A*e|c`Ezo)J0_wZ?K-y4Lu zmKoo*MBF~#v0>fUS*8t|gFkH`3}PQEVdDTZ^W;Uu9yP>%w502L6_j$3%Wt|qof^lj z;yup<^2Qv=>q9W!A);IJ`JQ@4M!y5_Cye=m=qTYUOCJ-^w$5gRB?LD%xO#l>{#NaYvsO)GafiJ| zTXS-XsBf}8G5Ri7X+Q{IT<)9^X|W- zLTa>L$TeD*=7c6XQ4wUa8<%q-T#oMhzE{}jnI0h$!&A5q_qdM9tdw;2| zTzsOUL@nhd*3IZYTX@x@UxWHqIfE`BPG{E)Px6A;2KvxUXJ!0}miiMR+qH>tKNM(Q zYvqtd+WtnzKa;7gjkg7#2@k&b9W3@VM_wP%hW^@r?91N;lOgq;D;e&y{R4@At3ViAEjHms{?(Kt=wV^|NLY8th4=x;=jZ+sGj}y zi_fS1@1fN1w{Aa0Tvil}jE%ORnH-a1&v70wgASIO#wS!YD#h?=tK5aL;la*T$c*Wy z(IQ$D#{In&&^&cRR*MPYQ^kgAPP!nic)(r<)N}W#>#7;7I}Z0F3qS!GD?n4yukowC zrdPwfsA-Ud<6tYR_~jhjAm(Rhxp;?VPL(8grOIjrGt`D){tTW3;s)n(t1*L?{*l?2 z)(aMj;Ax*~vy$}>jZvBqrNf0uQ!dEoTrk({AB^}l%GhESE#CTzZe4Fzr?Yt)d#BCkh z+T=YV2rli6Dx~pwiK+gl3OaPiuQgw>BIWNnJ%k8r176^FxkUHl%D6zp@01V`e9OE= z4a>jo)b|L9%Q(o=OwP-~+EOediH^T(5S?xO;S*Z;k=EKg$a7{x&AyQv>hLpk%rLRc z`9nB5?B4SUGSxgf@M_oCo_N9|RE)H>nFbR5y)GpH9~G(4J!(L$gee4&F8TEIyyhR8 zI?CnViYbTS`qs=>B++VyQonla^S6A4`v(sW{kFd0(0}iK{L4>%xBvAKbN%~o{c_ra z2xkU`DT}oIOIV^VW{pz;vN)M+b`_qsvXES8(q6VryqNcb;y6L*=-bFDn8>TItc>n` zS9Hpy$ru!^E@Q-yp5Ef650f^;1SAj8Kcs_?Mb60BaeOa2dTDHNY?pyCU}JI#kp`3If?$M)XeF zb0~?78i81NkE``9Kts@Z%41wAAZ<254t#Eb3+UeS$nXO)NK0VZ@@m&^1| zuv4k^$INtHRGYGRe&g0eXm)dcNGB;rFGa`S*L*xMhZl;K{uJ&lO*K_{9?xydN7qI^ zQ}D@ke#zcA%swJ%u=eaIY109P&@%MBP8M0EALx;RGe8F_UYMVBOwvGd+rT*+XlaTU zT<4sG30gzC<#~_1VJ%i!u;V~k9%&pnUH0JCy~kEs3$BdyX4VOrv$Y-rY0 zqA84d4&Rq89k)1R9&I`DGd*Jp`D~?-r8@NWw?AL}{GSDsxpJ z*EV?krw{%|tjt-wFgx}Tz10p4i*jHEcp1$rIe$SMcRo;>b?;!AG*@Pz8S3=0zRkL? zcjNA|`Kcy-s472FSbbZZ$C$q9emWkBWZ|kjLE#o6w9u-&A*6I3HPzq&Z!oLRVzyVO zHaKD@ZGDKyY977Kw0&mYH7|5pE{t#xH`$qn+Lu;Z%=4y4W5WO%xZrMCTOmkLv~rD% z%dm6MWIxOe*R{gR;O0FrO00>5Aoo%wD3Mn}9>WFIV5aKQu%?7Xt;6k*=r>bwgBFty zWwrTM-|KK1mPoT&=!|CGX3gXj#>QlPb%~$Q)@1Pr9jiH?S|ak&^X}Veqyt$m8Y@b6 z$j1fhdx{0mzdzN74GdLXKeJDS_1x1wGtz4(!rONYyyKQebBy&kS+h&v zbPz`K_3)Tw%|;bqp8j4RCU+yCi(S26Nx|-4L(&fM%pv$qG{X44vVr}oED*v3G~acC zHTNC$-KYQIpRohB2pwYJlRvr$+tabLF_!eu_3wzJb#K*to}G2(M(8PZ-fs!Ve`>1P zpXjGPeDZ#KW^HC{+BC6phmbz348yCOWr^S!Rx32RS|_yw-0wi0tgotxVuuG4 ztrVovrdHCk0bU$Eg-uPRz*tljgZNpQVWX~(Yvi)Wow!$o1Kir_ysmc~q-|Vc_D19h z9oV^m$3D6zw<^Zi4?cO$%!!)UrzEntldpKC_LxOwmsItKYtEp&9}crEp`?iDN+>)e zTgjSp%{Z)+B!~-;1WSm%DrU%*Y5keOjQ**YgqZF_bn50qR1j9~)Pyb>#NTOSPGtqsivMyF_E~Tjh83z~HbFss0$&y3 z*9ecWzOM^|VUthW2Hl(EE^GdAf}M(P7M23=cxZv#?uCf|UWcX(5tVnJ*??CU+z=(z zRuP91;AFpsK=H1e1+4T(tE9JiSliztI1tHV#eHcrj;sP1SniyQ>!JYhV1)^CoRV>~?C?plT!DVv1C(Q314knJ7+)&xOu9b#*lR9#*4)npou_ zv#G?7>5Rb{$C@HY8MMRp)c&|11+5FpV{K8%?(P7gP?-Jj?DI#Rat_WoA~1H=W;gH2 z7@9_mCwuUu(JovR2Up13$ZHNOERq-=Sq4SlkAg@?sIT&Ex%5w_?RXMAEbbb*StDfy zx4_F?_%dduR26VAD3lVnM3%&s>tgJq#^>P!t_$}8u4(#u2>2aYIF0WEHg!01EWT{4 zZd@-StX0BsZ}Zg?YT4|^{M`?%``|^|$fo(WkvTEFRF6QdRY(HBQ>UiBzS2561U(=; zfCX1P8J8-FlG^cn9Rkq`cL1d(9_EJ^gumDM-}3@oMVS~9BT31?X(mm{`3`~`J2_e= zrl-*HBo{_~Lu)sU#_`cqh+$(jlPSWZNUJ+x8{Xt8C$eO;Q~FQ!(3G0WGy^C#)5*6m z=>p9MePIltOj%x05(u8Qfd5i%>{e9?w`>=0>!X!ouH4@4i~NGb=kiW0Hak@hCS6nA z4G^HWPk2py_~x^>i!O#E?vl=pYoB(B6aogHi6H6>_VP8;#VoPAlOiu}m$ z0%2C4Gd3z7(*37VJrLT(qxb}%DC5?ghBjLCyajdsCPo|>^4R7PZ-s614#6Lg{gQ3Q z7wsi#CGqcdUjtM3@_@yri#253usnXsL?*NEsprbQ= zj(V@LGv+(1$D23P8=1|@>Cw}p6x`icp>H;82CP8;i?hZ3CxxtZa7FC3O$o-#It z8nru_%IUQX1oaKnmEWdINZTZ+Oy*U&I_HHBgHv|OzBp(n6#qa-Q#F+~M)$i8W~3;; zYArTnd$8;~yR_+qMWU{YKQHvmxh6}#gTJ0}yHp5S9tPw$|Ld1A-0wZ!-hX@W+`vzl z^ZxKpI`bd}#H>B;=j2}g!;+ORcC&AfpQAanz^H_Da?o8Y40xxey@ilV8*A~+IYNVr zeR(#wkRDYcs>}$O@5!c_EKf(5TS$R&5^6=+?MzM@{5trpm;Hr=>VbIklyfAt+I>@7}tZy{XXW^0a`pcv2tMCInM$u}x z#%U#L{5etKj2M7W=+x`8O^Xw~RjPukX<{D@h(RcVe0vO*$YP{cbz@u@QeX*sJ1^MB zvDE-c6pM)C*2^)=_z?w%`V3)YhQHcMfE@3 z#MrUP!JjkQG^(7+-v+hsO&xsbn3DPKAjGs^%M5wok8H9!GIyQZcvRZp<^aRd!_k*g z!+n0FYA654M-ZN)#!2 zUK%eU(9gfL$?o>C!X>4zu*5ZbB1=Bf{Hk;ybZolVfRj#3CD`fnMpdIhiD(A7Wh$s4 z&Jo^8{fhMu^`x&Plzm!A)UWs{D4P#~6|?Xz=V)+CJM~!}>!wW^ee~>rMK^;N2NWku zY3_Ncwu)0>!7oEDtdfrk0kzRKOux(_?o6rA4Q)uCu=I1f9oA}22x>eBiZ3#Xa~7+) z`{psFrsu{fm8=3!2_H_y zn{$!^f4jC4OHN6@`br!I>@Zs}91iZH#ngFqjMhyGL?audFhq|f@tVjR0+`06t+WNm zb-QB4ef|L_gB-Mf0lNe>kLlH)<=*K|R{5f7NuZ;cs; zd6XjY!7)MjbJ=ce$qRH8WRpH{I%x5`2b@^ zCi{Bpe%e0yJ+qENf<``CEdSby-W;DqCF9_BDR_72p9osz?qXb1_?LhoP@oVKJi&EA zn;~4z%s{%4rbn6D;KGcy(iJ`9khC`$aE=p8fq!LXHLNe_7Hsi@vCqW*i8?lN(hWlj z4`axuX0OWE(z(%z1K;y*LNx4FvO2==oKdqA9c#8tXx?NsCwHIa-8IdGzFu06)k z&&$^+O$*LY2qh(G1*~avmt#A(O%gm)lbt~zNz1tb0UaJ<8*<_Aj|}4EI^g>msg_<> zQQ&hV65kwqWEQmGn6Z;s=f{uF(d2>dl&rC4d|AKhB7)MaaiVIEa6c{e|041v7jHy! z6fxsgl{7xKi$H0yO3z^rxL#(>dc+yVq;lZJEK=bpZQ}dr_r6od)nocuXe$dTp8`sa z`B>_`6CIy<53quMy(;cx25n+tsu5-LlVobuO6dWO!@IRky2*u%aJ3-TAggC;4Rtq{ zjXR5wnth(>S!~mo42uqkaW~>bbn%!a!IN(hM9QKwnRqt%aPJqB_G;eVD>J&fMge|W z6IU}LTGs4gEP6n6Mi|SZi*VW-%rhk#=`&3gti>Bh7;C(!k|2q2SqvdBTh*+l=PyNt zr8MAoh!F=1kEi9#BC6%wNLNs=UzNv+Ri+CKbO}!T$`!Zi(Z~>HvLd{+Nwh3*2Q(6} zE_&#yKjV^2`dv*)cYD>2v{B=KHYV8PmbS6mCrOANp@aH~AV#jwW+`DMP1m+y21)N8 z)1=wKOY0ws0`}kna0}4ugF4WI&z)XR zux}+*=ja0PXeJHf8K+is;_B@t0iJD~Lgs?(&NG%s2cK|_0a(XrIFPFl1fLg8&DV2q&QVn7U6V!Xa>!NSaEY(phCfqEN=vD)u;n>%xLZu<8~ELvS!l@Mxs}4Wo=L0FGe1U2#AI?WIafUkG2V*p(hs?DaeU1^ zCKODp_}(JjnaOQfobQmA>)!n2C*vO4MM>Ng%3 zCG`5THQ$G`7PU+vVJ7=G?Lfsh-#Hcg@TW?cf4C z4u_117`af0yM`Mlt?$Y@ZEMK(d~8wLl`J!p&>5iXOG9rC3+n|F@>qb4kvZ#$#Z=%u z2q9{>VhcCc!%g3WNlAt)p`nqHY|slXL>JDcxyh*U+{6zFr-ziCdvc?P7M!`XMoI4` z(JY-5V;P>%?nw)HB~+}O$6G@mq|c}M0K|-(d%RYGWHFddLTnsapF3>w8zY6`XZt5h z6%u&(EYd1VAe^?zQNlQszEEdub*Pmr%%d^zza#R}vQu*Apb|1bWxc5x2q(v)j4G7*FUT7^9$t_pJ|32$ z!B^*#$3U&D%gaG+{i*@8ZRlYJGNi3RA?PWLMwD0hic2y)r>xshWr({3a49Jucgzjz zlA!JJhv~>0o!sAi4-ALsatP&!s~1QjX#Bl5I0)xA?Jh6nWgzhQWjZ?Nyy^GL z7;cbYjr`ogYkm_25B8^N>R{Bkc7psb%{~oP&b+;bUqs|){9=>sDd??EIrG#LM{U+t z4VB7&yHR9$vVcEprL(BR7kNR%^j9-ZGl!QL$M+)RoQ&2(giSa~c)jFf9e-*}P8gtr zIeONnG2t5}HLNWuklHeHnbT`{le^nDbp+1S#NxdN-N2aB%O@@29(39Ilx552@22WBLqRJCIE&&>EuG;&0c&uOM0a&rUYu5Ju7UcPkm_JV(-Vuzm+YO%8FIu?LW zvZ$LZV{rTI4zXoEMLUz;i)n?}KMPcE$+FS>3VZ zV5j2Z(fd>~A9h+Gl5c3hMM6IqoDwggmH6EE37f2a(n95YYGq!1NK^VP=|!_fVJC=8 zMfc<5{;Fxt>A;;cwXcMd6kLXyU4LoM6D>rO*n2-Y=x&!r>o%IvU&`61wsk0W{Dy zWWldOe4Qc~&AiBC1@vneDbnXdWsnN1XK~1WmDbhVHmIr*piQMlNIVQJP2N5|^2!3J z6jKA57=yAmz-Q$!P7o&MWlWjoB6n}h0%WbZIF*D!M?+F6?20~ z(UdO#EIXq{8w>JAzH$gK(+-Qm-tt18Jy58OTAKAy8YQhe8EbX{*+KE~utfGHe>$rE z9>6D9agjLR!?^xlw~w{O5UxKg^70F0VEg|5q*lc}OMmpvsM^9#qnkxOu^J;BlqOR5rMawOUr}O? z#EPWCdqchw@irO?uhkSY9ugmYd#Q&@n=y{u@6G@Q0%GjH+NwdlEsrb;J)Gykj5{mp z<6s%BHElYOQw-rbTv$kX{|n|7YZl*I>a0bF^)^?&TS97R$5_j$$ijBa>PEgExPsKj zNQPuZO|7rsn&Rici+kK-&Q%0b_p(nLLQ`g ztF>YCS4SJ>MuT5;6tlC1+aHbPqe4Xw^9Ueo7>pE*+XSRi*q3G|b`wP7h)&%0&ISQ7 z`XcAJ8Z$L-yC^v~${h#*z4AJF)Z`e;Mc$T-yaMq!Fa^;w_F5c0V+us)9->At)|M(t z%!bStD-{KBB-66^#t(2GcR ziIyK(rn*asFML+@yF~9WpV^X(pzcf{{{mbQs@p70&u?f_0wx!zPH}KRQbce?@4Gi$ z=gj?@jhx0Y35I*8UxEy;^iK)Glgfv@2Nq21=JeQn!{&W3H{-|zo zrli*eoV)gC#J|CjcDA>3V;Ji0p(-pH^%^OPQSoYs**OuJ=^ZJ zvds2prcpMqg}!NdH@U?dcfMmTjuQQN8c#q?&~sbkzJf=VG!hU<9{ulip)MFLKDg?J zl}cYM=0zX1jnCn%c!9IR`LcqjL&vjEPXMdiEcnG{A|X(m72b4huoS}=Adk-pof_qB z-JmS~aPuAB_7GU@8p#(O@It`OSm(@~!JiuxsEd!!p|P^%dRj3LdfxYfqz<{JF31T# zAGnM_c)X~g5`(NeB@t0c_La7y0n#w_x{d#1tCaMHSekGG(#Sg;~^Z zTFK;uF=e~=TH18Qj8Kr^P)3#`wSu z%X!lXZ5~)K@ff#tg=JW&Rknv2Jzv`ugt17FJnobu3G(_oO|g>? z8<3ii@Gg&d6O>QtFy?Ua|7-&<1!e5fTLrIq9;3fF4zpKtVDfF&e)rNPUS4+0m-4b$4y=<6*qia~0PD|t@PTt8R(s-igm;BnfY*5}RzX5n_>b(I_-SHG?v(*jU*sDO-4+@h8F z=a?*takpj8=YclOVs1&fZSxC01?HrRHU)H2Nf3vJ560}!!+6L&(Y@Ome6xeG61OZL z)^i_7h-6>Je)@ZOeVajgmq59(M6ae)giH41MrMtU^ujk_u{Gn^neeRBqY8=nje`^&!7I@+DEfIipa}ctcBR1VJwGN zWM^M9Dk(yA@a6VG7#XLAk*>(`wJrB_fjAQXU|hVCD3o_r z!zz(sy-nl$NAKYmid}hDaE`z%A#>ySWBq*017xLtw5a{Uf>AXwRiKz{mR~*ND$UMq zVTxV7(Zf&OPPxjjv8&Edqp9Zw7A zt88;+f+Dzdl$i43VJX0(X6{Z&gzCv-6{mL7vsrj%Yu0`R2N$uG$OQ!nnHrbvc zERmW}fq@1_%_-tKYU>1EZu5-OcU0rP_7*%~^@$h-CTt#@yGb!KI#0mUGcHX}gv{be zJ<+CN1s0+sDo0-C-RiroWi_xzkNzS4Wa^DI_=QrZp~;zqqGy@CC1d@BV=6GnH8p3c z<}$*LCh&^Y;ARlK#fzProPMYXeW4pr<0G2)6oTvsbTn(XrZPntm&iHbnz%R&jw3fH zmY1x*PMfwr(grNKv~|uvL5}d0Vc)?mj1SdHn$@ImB@=Pn`uOAm0Qx3Xov>6)f_Q_I zf^KC#fqQG-&1S(8(VuC~{t3FP;}@E8;owG* z?x7Di6c4IuZ}5VmFt$T23P~=q*4-uXdobYiMjFd;rbnYtD~n!1^p-#&86aksGgukJ zVK8zG2~ijHSMv}R7;o_`e%Z17J6btxG`xujf{~I(PV~r~Bf^0sDI)f?UC>ql4ivb{ zT~37lv(vr46d3;MNo?WxO+^c~W6Omc%xd6KxphjCLK5K;lr3YIA1xYl86PVjle)=& z_1;kZIqB+}vtCp^y5+o2$UnT-d8_Dyf6;oIImnKX?!3(95;efXbOSzbp4;Fu^0sKr z$tRs7vv`$k?=cqcowMc)=n0o&6%y%CnJ2AJ#aUhik5ax|;_8jp$X&%s$@yP|F7i&~ zmN8(WqP)=bzDmj2dDK-IeM=EuX6>ZCB8b%1iWqC7#i<(c#{1uID@l??qxg$Y#lqmY zhttP2DJ}aVW{obmzVN-3(svr893$2=^xeh@SQp}Mdg;n)%o-Q;1Byc^l3}38X6~+q z&P=-=-^odj*aHTmJNt-=mKSHb3?n6Z=dJ>Z3Q%@C+G*Q;m<7d)`K5dmo1i~GVXc*8 zDr7mHuo%wf-uGuyM?+}2L9Eu*H)}?g0fiN$gRE8tPg(F1NpnxS6tcPpDIYymV7lPN zj+i14p4MV7D79r#q!*lEVQ#$e)pB~{t=eshU=6c2LLWRnqp$(Zoe~_(ALu|w9m3EN znrHJ?E^jkb*~-ZRu%_mm2qQO%LB=r|8OjT8Q_3Om1ro7HvFPDZdUvM2v^^I(NTR2s z^s=v#(tj@)Fdd}L#}4{*GHqoVY|;;#*nZSrY~=1tD`peZqb>hJlMyJ#l$ns)n5&Y zg4?vUDCa5b3z-n_G7)0RR%k2I5rrs4wo>Ndz4nLRURsxpA_(8@8s51$8a%~n=E%) z(r##A)giqgA*Cp|`a`wZg70F{lA4Rdv3ioWGs357{(#JuN%nMJJ6F20R#SZPVsFSc zzPlm&_hA{mr3~Dt{s^=ka?50xO5wfWu&~`qKfTR1v7H*PSjWtdZ zMZoZ6Lw0PW=C?Vcl5k>C+1@W?WEE+^XH7NO7c`Dc;oVbMAHSW-ODfzjDR}5^FlKhi z60p_8NQ^F^)w-Dozxe8uEy`(OGvHgmnTtNpjzknK@J|>LtA)9%qFIEfJ~ai}y+2Hm_}SSr`nANCtR*WQ2Y6GYMvJk*Q6GpEA|(8ybxMq>p{) zfVKR+?x-s_mg}z_%IsB+h>`c|S~#NVGn~5ff0c?<$dHpRbaW!!8&|>CODQ~-XN>{1 zInEn>O5cbwmIrO=%1uP}jh&cSelX%JW9PIf;W_Tp=@9;6-QVk)@9w}5jI5`ZOl~PU zz-T>C+afq+mG8}2a9CME5g3!qg{fva7uk%&Hm&jtZnTD)t<;o0&%4onMNjkhsCEh3f=Uugd|`v%?b`x z#^KM6p%nwXn(pPC^Fvxup3_dXG#%JFDn7VizS*~Zv8{PBFg44d9Ij`9?fX0~HhxfZ zGaFv&^aW}5aGyCP`?P)4oCx>N>YL|`%I|!zkt#5HiB4*SWprlF6&x(e&7W59FB9p& zYbhCb6p+or>OHJY)$baoOIDn{bqme~?uox9!*7f}%u}mOoQ(V5kDeb0Qx*b|<6{B?M-YJ#z^`~9R+|X_y9rhf(olwFm*Zrxb8I*f5L+((8fSj##A$hO# zo4=x3fzB$Yoi06kW4n+(t%?22#fZhaPE8MLvYjf5#fSoXdm9b?tLQiHdh}QIZN=hk z%zW9cK5oDmARo=(KXYQ4tz{SfN}AU&`&dbGaiEjY8%GIpKsVtKu}khT+3nIT-w6*8 z<9SjxBZpRwnuy5bi1w5oD~QHWE`1R%K#*J@ zT&JI&xD1I#@CIEaF#~Zv<5ZHTnJm}|FXX$(LDrEQWl31T@+#|{IVjNsdZ^ji`%i3S3B<5P+lSaji1N6V?qY-4!UnN!*J63#eob|& zN4Kh}AC|dF=IL}$bUKg{)fO=?#MqpAdwi07z#=JgswSpKES=Fx!W`bnl4_o~J+r1d z++8@(%uEb)5xsyHr*`Bqv~on3%4D0yW8^j|85#rT>p3UD^URz%!i7&)T*4h6XUTw! z|8LZPW_h{_H%ERnwPcSUd%IVzj^H8-$5trl8m}a%8Hcp`$!UWQH>5 z00(}-3mQDcy|H4;lJx%yj$Bn&=SRA^LH1~8kE`^;;Ue;K0HN;EX- zf;$SMoyQ5Oq4w$=LlO_L{Nc{0>8s=J(-=D||FH}{@6qrU_9g?hH$LZ9+Ks~ZOZncyP|wEp%-p9LB|f<_ zuNQDR1SOV|Q^TPZCk$I!32WqW`r5g!gI=&pq)9;fYd$NJR`h8yz)LiGHoF-vL28uf zeW$zJmO&d}DV}zo$Cp%;PJ5KfI-jRWF3h;q+{^4ViP+Nk3j-I*q$x^HBByi-J2fwj z?z}4%l!{x>`%Cxi7v98<)cBphDO16B#*@)SX?U~c&rrn~H5-=8jCz&Y257+Uz0*1w zcUXetZibilA{(!7=gH!nKB+jI4ioX_?H46@IwPX1wX0a(<14yJ$l%eJV@kGXtv5}E z2pcmy^>(=l9xP?IGWPN9@df!&r+b@x zCii4x!F5AcR5p0+P!@XPj+%V}@O~WRhmrno&XojOtJ>u0pGrnDrNmjj=1*PClmwR? z=v26litk;)V#=&DYl-7%ud8^pAyb zaz>Z2MZYW^uFolP0b}#Cb?w_V@xzfNQ&n*-f6l%#6PoeokwG9U#}Yo`oi4G$`CQ9}xR^fWPFSRU zc*JNic_H2&mW#yM(`hQL5#y-=?G6^LDY$v2Fj|Fp2 z*kymX0pWx`Sar{=iB;Eltb9gpv;EJ!gL2|^_w+W6thrEik^7lm0i%SJ*^jUldZJ|f zZf+!-?ks&G90RA-W$54+#w;?c6k4(xN3J}(CB8^oyPIAQEQ5lTk)PNWLi$>NOvcyrI zCw4J|AjlW<*-iN!Zov22)GxPQJgk~WZ*EP~yz$=1wj+^j%IA%OS8IeL@FWm`q_?(< z%<;)P)Jr~{O1NXnvwY~LGJg0`$MDmCj>!mjhaWL%a#6nJ&M0o~9{Zn>b-d>8xF;9H ze;thckdY*BU#sX};0NnTDSL|I=%n0@BP)NeOH7e-KXlJOS}d9Nh{5G^atSFuK0jvX zSN?gp;_D0Q09{5EouJf&w0I3Sw9OW2w5DW1ek32dxu!cY5_tUlDw zyfsh&Xg4iA9N_!HpZqciJUB|xqG&0>0aGH9kW9Xr?^|rC+XToxhigQVLL_5vKKZ6x zQxOx3K&j9dcf>RGV_vQ&Q8}#q!yiw)-J;1cDR;i_j+X|&=mUc;@+@`GbLv)Cv zFX)C-vTN?DmH4pDUzu(9?UAD!>CtR@OIJyE#OPm&onIUF_@_bvrL~sWjWW-3ulyfH z=i-;--Tv{`vr~uVR!>@%y0z@&X{KhP;94syPb*VW6qc6e2~t1=QMYwknffbJ@&K$z z$xx_J5foT6B}E`5L_;MHfQU*8n2@^P{rm&Id~x6R_j_HR>;3s$-7FvDL`Xa)XasHs z*u|E2o^5c%#da;chPwYYR9<&A!)zM;cg?;dzl`X3t$IwiYHR$g$(RgwX6f<>JFyxF zspyJ+!HmaoD0u}4=nmoiSmaJ&yh>MrKpedWfHfAg`pySDe#DBnozt2ZWMp@9{(zUG z2#2lJLEHlAN^mgEA<}iQ$2?c0D+(` zn41Pu@uRm5lS4fd0Odgtz&|cclLPox2>zwc<`F0X|IcNL0UXY#%y!(X#RZMcn?;Hc zmD25oI#`;w29*2+7sJF)8I;F;q~>4uNCPdxUDm=z0l@OLl{8{AlJ>@%gOrM;d}oyM zAIe*C|DJ5eK8o!Jv7AE56RG@Afp|jT&TRzz(#Voh9>>MT&p-3k)m4zt^_p3r+kA=x zzB7eyr?RHJij}L!Cp!;ztHH7_2!7)J+?5m|s5Pfnt1M}^OQF__aOlwl?ecKK9CP>E z;)SWpddX~YyqOTT<5j|P+pn|Y6lbn2d>P$iln#M%^<@bz2Mi7oc>v5^{WCf*nVcll z8l`4;%^mEGI%K!6{AL-UTls&<`gd)dI(-Iu53DY{VW^6(#u!}T3jppD*OKC z{XsgztY$kodg=(y1?{CNpAMXVvp~SFmhO!dtIKD`mvGCFk`P95Acd-#o(XV%Y&uf? z%m))oKz~f`m6A3M5quXkY*LuhEbhP9o|rkuDZIV}%Agd~r86c6Je71!m*>jGc6Ere zh*Z0y0$n3KJ0c3A#(HDVhIxn zr!T-kHv9Luad-2o*DtL)v!*ngf0nE6NWbW`d3tY%(_>|@pE>B`VbpOP=X%9krmsnH zUlb_xua?OvqYhBWDnn|@Uq3Fb1esJ_UCgemoJt!aWZaAfS#3_qoAM@YS^Xv@V7kls zbAXbL*9C`JmazUog-1+P8II~u85*l65&g3Ho-ln9%PX5%GmqT<#8CKIS^U3iPR8?` z^GzRn6SzfbQ|sDf0y?!W^0=en%B*S3P;}5CAvhTML26``Muf0-vY;Cw6sKT+B#T5u zK`Yb9O$#mWnt08q!yhAV0D&Dk%cQM!C~#%NWcp+UnjGTicEaQ4CizA|DhptIA?b@8F=syR$ zD&`0hrHAj31V&1N5&2O-pYgmoIkG&#Ei^&g<1QE1<(tCSF-oJ`XI`Ym!eJOUY5@jq#tMFf-cNt^neU08>4_w z3;2xoA4 zl*HOX=NVd~2!eu#GGgj#%(M8Fc)ryx?2-tX5^*@s|2-dBKq;_Z(2HGYak<*z3|B5T z0QE(fsjYVfXq2$satEmubXfuD(6I)c{3;;FS0suX$gY(#m~4u6uJi55`&|$@66Mxc zJeuDKZF6iH<_Amy>^8ZbkSfZA<7Wzj*>*URtpEvS%ifqU$*lqw#0X}uC#2Xt8m#ip z)M3y$LHs;OM2!p7Q$~_c6Gy53=EK&~NYe4Zu=gq%$6pu_)T4+4RLfG>xUC>?YU!gh zP@3!nl>NPtvSIjr+sHDmv?YSLWP8seAZ0`_@q}MV)NTB5vqb3_SL2Ws4K0O5j90i1S zs$w3JEDVm2mBw)+aI`w-(Hzoo(4OYOg%1F*u3SJB8^$8$q~3n_*!5b=>Hd?l6whYV zPWAD9qxlY3TAMdh040VEuVd!)8W20PSNtF7B&K@Vj`=FT0162vQM*J2dnw#h&ExID zh(qu7)xu-pHR$8o-kd3up_CBqUB+3Dz4hS-td{d2f=UHI?4?n0zsW3a&swP&-8bqC z7nTCk@Yw~RP1ETNRZR-fBd%P`&{fF5ZH{C44o7>gipX}F==GdqWm@=C+L>g`h!@KPwfT6b<`yIKQuj%Vo)hhc0v zSwF$5=uMn0-f5YJ0K$cKHUf`X9^jjSy8JrCI`Q!^^!zWP$nFP7m!DbuS`?_vDwC9EQwjK z3XXsU9Y8vdDc~B0!b6d1*nFv+4SD@(uJ_EP*YoE))ioUG z_K*njsMFLydYOMjE@7UL(<>pqT^gxz$8@Ofr4_&Rmkt{kljf|IWrA~<&2Dd`tHm4T zpQqCm&nR&c^-cX);ZAYiWN1yo(;kOfQS_(?c;dPdC9T&egPSk3k*D9A`vk;NDC9;} z^m9~FKp*9evG@>XnF9wcfa9Y*x*B_!B|_?xw6H~y{MIuhmIl`A#o#XZ@Zx3Qiytj< zNP3v=m>YrM?N5fL2!s1xl9C8q?r2HAm*D@m>Y|t*!|3@K$3%u^2r~Mh`C2jyO3G6_Db#s{8XIvv~tZ= zzxN}RP1vsd7cm#%wSz}YTVM$Z1qH47LA$md6lB8wjyWOVX!4dnw7tCD#a`^?gxISO z@Dqp})x0INGINL0r?00maY#wm8f3=5eF{KRBA^>BS#{zSTgrW6Oo+S=eQ$0MXD#?|}6at5t=%nVghQ$$3ykPND_ zs>4k?U6Py7uV+(bf%AMK-M{b8WCP+*ujH^9-DXX+ZNx1U2q9{4_-Vk*JDqLG2Jb{; zB=_%Oddoq{$A(9oozh$JXJzfm3qUG3EK6QIErQA#oV=q&QKcESDE|D4AdefKYoHQ4 z@A_u7=AUVNGK$0VCe6v@vEwAgvKp~LskONHkG$?`7q-cI%vOGI&urWEBBrO&!$Q0f zv_M$@Y#r*5^w28QKee=-QysFm?tLC_wGj2&N9y-n6RWVpF#a)UkY{3?IVmiKD@lsK z7jtR&yz~%vL@{=GbTpDCDr2qZOtpc*{xY-HDBC)3S~(;oF3XhS(1hD0blq`@>@5Vk zFdBJ0QB_2{Zo>5#HY7Ie0<7xuIa*#PjJ56;&ezfH3S%@fs6J_ux4o8Iu|2bkZ+Amk z7LOk-1v?>2z!!RumiB5P#p*20NBGnDV@6E@>Be4oKFTX0D8>IZBVHaw*Xol|UW%{i zK~-sC>SB5Odba%#U}#)f0?^29@|5j_VKRHV-I=ntU^_^M@M!1qe9_Q`W2~QB+w5nI zUa_o_7Bn!!IY|%Z(RaV0J#z3WA^}l1ZNHjLIvf6&`i0mme#Y>2ZChS>tlr3PTxKJ} zjiz*}Uc;c=1G$dHScEOxR<>d!a%yO|pcJxzr1K3w2ExyHC{?N9GKlb)waxI(ZkwIeTu#@wF}(d6w1KsDrd>1pL0jK3H(TZ z_};dwy8s(mS*N;O4f#0!vEA*nqrjdOosU z46%;S2zQtTcBwT6r8_xj)NAgK1nKnHJq3%vxD2D+mJL=V6zj(tMxMbJT0XlP0;iS= z0VIR?L=XE8S@K=>e!neopX~O9(t1cgxXDc)rtzS8J|t*mI+j*pgA}L^qx|7PR7Aif z5F9?9<|c`iu%B#)6SbCZd6j4ov9NI`BqENDieotBR7~OB}-V1_$}h*YZFFJO>t3n z4Wkue`d)=rraVczhziQdB`mG9U&&K46WZ*;j-3%~H39`Jyp-&BfEW*X=2)Q0f`kqy^|M7pdGTIfNUVQW*YdIS|4~AjI!1gcfz@U;lTFds|KCRCIscEFqzHNa1u@ z4n_A5Ax@yT{PO8mnv=UOP5nbTrm>R_RBFsB4wGd+6I_YhJR93#DCDDsvUZmM3w9_&K+M}mFM@#bHs?w$9ve^{Yc z9rs-ro9&tL>S{L4Dkqc!mjz!aBpI9^q=Z(TL;eE)uv`{%DpTGwQe5OW-_C*t9u$Hk zs=G-6d22C2bA=C^^wfrqsh(8TdjrYPkrKe0f&tfoqxX|$PhI_Cxr!bs>cdri2%waN z+ne@0yyOnc=$XSIwjVdokt6-1N{GRQ4wC8I*^(jNJI$*PNphkv!X+dK%*`MHc2i}5M+;=xUE@taw~70iWnQuD60}(gF-7ixCJel!_l{`$)EW8Q$=Tm-G8o0?0z1SL z>!=`wMlAO610ridK)qvI z-Sh=Zx|7k-U8b&T37|4+Jbl^PDACvqeNE31RloUvlk?Nw* zUH6KppANm(RFSA`jW&fr+kYQBo#xI)ZQ_DVoG*Iq8$D2_MV+m+(yia#RR26mOfO-) zy;eXcc|{QChX09fZyKrWJNkM22;RI*Hevp`#3KRuB#w-8_-Zb| zKvwAs!9zZ@vTA+ubQ_t4S9RoE-~{l{FbrBh13_?l^X)t%hB{THFp+>>y^|VaP!(>v zSr^d?bC(n$eGes! zr*V08Sr)S8K2Hh!nldkQyM?>1YLVWsHf`vBi#cduE_*enq-v<+FU4%G%^F!hsqE5g z8pv!8g{c$ZXq3@}R=5$oL-fQ-X)L4HSnx;V0xr}D<1NAds$TPD30Go4PvI?*;cA(u zV%hk;LX0EFyfH&Ex%bk5n?q}R*g7``SW{uGi*#bwg|==rDO4;7=Gg5Z_6h)iJVF;G zYKPy(9LCV|fY-=XGI$AqEHp;Nf~^HzgGh1lF$ZPcIjg6W!nZYZ7m0DxRvf7Xzw+Ku z^j29;S1WeqrS(XL5?n*T z98UK?b~jyy3@*T>VACDB>41?Lc*DX3#jfQ@kDu`|e_9{@U4LO+^2x-vUCh94rDN*@ z=!q&=FAU}qKzkfDu6Xu*6zgaIM-%Bh&FN}q;I;JUb2GN&v_<(k+YM9$-G4 zB3;>8$?&0hmvXTlof)cm0;FKX3u40DGu-jZ9@(KwPWJq#*|07yV3f3phc}JcOgZuD zXt_Avg?8&h=F8co27@49N2jL$Fe2*Hu2M@@1Ny|<@_qK^wMqIL$9rE*TcsuE7>vSd z407`*&a2kj?ah=mQ<6~9%F|WOc<3UYnS+bxOsjK2A8+#$T=r`NAfm@s%4jfKMk50> zou!?iBN&rJ{eo(dARsR(#6I$P%jG-rV8HURRo1UDz!Q6s#aYS{Q_%DP#$=G17sBIL zno&U*BD0WnUfP?Et9oa72;@vr{pU=YSs7|meHM)x`4=&gcBOgJw%m?Lq3#V!(cirT z=%$0bZ2OFNbIYsE7C@`$X1o70hw~3D>bt#y4GB}$zn#Zf5WzySCD$jDMTHmE`THNe zz9QzK?>ziFa z4ew&ssUc;jETkUFy>mnICM36k4-D*Z19ox57#-+j!q2xt zt(Md@_1+h?#J8Y-24s*a!0>RPe;5VbUl_o-O^=}zWxeLMWOstp{y=_NxOocixYrMZ-LM)z@&&>yZn3z+JGghgie74kmb2mB#!9GoZC@C zu%=U|YGlXV-T-u(uApT5=0;J(^_1`XiitcM!U472+|Ds6tTThM&};8L5}UBGWQfE0 zqP{Irs45lNluzV4h-amil#o3&@Ra9!E;}$Lqvbf$C}in{eyC<~UP+%P0O(CD@>6Xe zqnws!z_;O14DD<#Aqzb0o1HW>jrX*Jo=A`$>r{ga?YR&s!JDa*$%5tWZIYqpAv(o` zl`?~jx@Xv4^TNnK3;8b+>;Omf>9>}kQy;QFaK-^=n85@wy7^z}>){0YC`X8q`S~Ut zxFEdMATnE@edu`|!6CIc4+T_AasroCdMl@EaiMec(xkd0u9d+F4wYIG`Fxq^!#p2O zY}rs8546i(I##S{l~ipLc=|^kP(hCk*Od_Ziib)PdGV+~PP}TORN$%A_W(oh`tL0@Im5?Mk0Toa)=|X&a1?^<&{#2aiV})jiOA83UCFEOXhCXAF-Sp5zsa# z7iSG%v8$g@fc?taXO=vXY?^NRt$MFq8&H%OJ*WnF7;!!dLP?ku7_>R_>QHfB-Pr`_8#z+6ByDM(=*Mn_(cO zc#vmJ<7o*xM5oUO!*LVicDM2nXm-K$Vj9hlmqQiH!kGLd()7(Zyxbp{&DeBOBD<+Y*eptlMcpa7o*$U4TA6sNQa3_49Gr;db#5nT4NdRFYn zR6$<}{Z>cc666otsQ*-MhNj{-MQe3H+#E}qg_Rw>Zpj|7i@>ko-z`q_es@kgF#P1m z^=`j4(F??`o|#L2)RwT<&Db5j@ythe9(h3gJy_=sLR&Ai-S1-Nm-xsmCf3>C*WOd= z^wk_+#ntb=W`#)f>q>>|EskCqrm$2I!|t`bXWP$R7})Y_7X{q#53}Zjm3P7Ly?;`y zEpd2yCT-Y=@bGA!UOV%qS$7gylg4pFvwh(AKPExA(XD+~CSwc#ed-*Ic`j&DqIXwbx* z;>GdVB^H3qr{V?eG-{~0-MJ>ZMeR2=Z`46Zn*cX(87KHJA`2>6Ro-ZxoH4cR7?%tU zETn;^07vI+ms#gY90Y?(VgpBSP!;sjjR|kemoy&aCbW)y<##iBV15yR85z`{(Tp(4 zO;k|k1g}9nq7Q;u0*$6QK_1>noz}HU2FTeu8&}@vVGi~e6o!e>2}wrjFlKHk&@hoR z!J#ZJaaV6++DFnxeXw^Ea`l~y_!megJ6Bo*t=X^yic*9eO$I_Ih$3O7iODa8LtI$=1LBS&RYI{us_r~w;CWBu3}tR^HbWy8*P-F4F3A&;5@-g102a;9R#ZVqIw)y zfZJ>D_dk$nyyOms4a|8#m2^yB)l$oahl9LUa8Ua5M!)x$bZMi_=$4BiVbS%;u7gmt zqe2`b8Jn%izkE*B^+ett$d&-)a3CZU8c`DrExj|-1yPvt?TY>Ly6CH4TmCqx7ZJutfch5GYp^0=5uEy@aTZnrG+f51-2C#GM> zC0F`xHl~i%6Ga-By@$Z^1EY_Il5kqdg8WtQ88>q65>}(!g_^?n2j49@gE=ho8 zt(t|70D#VpvKdWE;M@7dNy1W)9!Ml{vPQK7QL6I>yT?`cu%ZxA>_J=+?)bRDAB|hZ zB?MJ@D@&(Mm02Go06(msTlJR%g7Q(#q`nHbUtdNJI+^4}{yJ7+A^>{VlCW7PQGR-$ z<;UG?QrRxM6}Nur`ge{0u?Q6FtMC8jWhf=Ix-WlRe-|NPNxP?@JYH36s_C*V%YKwV zuRHSPK?sg^RnawWu2m4C1sB);F@s8>nE1pOpZjGQ_GG-IHE?R=A|P<$2|ZZR3lLYH zR)O@axw~R`%Za*}N@00|dsoxKz$i%B(~>S`RIttG%_$CWJYga@tZqVA>vY-5YcsE1k$`a%Cs;0PoHP^coR^ia$4cotyg~4Sc2>-~ zw(AYD^SSS42bN*aI;y7|{ovDVBq~bMPUZjjpB6PtVult^X!QHY?&Gw&^3=(^g zD5PrzEUAQ&(_PIh2~a+^%1^?9h^`A#WO0xs1kSYqtsmpp|GVQdcq`)}j7t`8u8YztbzJBX(z8E6Z>tRu*&IebX1}s_MrSK}qdY0$JI9~?8h`cRJp+1nK(CTWP7_HNyUh!6tb9Og^XSj8rfKvR zxJ!y`RoTPJnm^Xo-n;T&^GoC^p8n_(+X*FM?|jUay=B%8n$1M6T$an5XXN4s8dCt% z{vu$)%HQ-=jaDzK*Nj4j80bikG~Gb4>4lnEl1tC6G8PFys}R7}E(|GqHfbChQ%OEP zBNgO56O|hE^a>li@R)yz=Wwdt{)q}zb?R;`Isa(4!HVcNo#`1E{XzssvCGCG|IO(i znk|TI6R+6qFqNbHllWFnwyucZIi;hQd)5F6YonRUJ}Mo;BFT>y57T`{4#-2k?~V-r z5Bps!-yt|Gs(+-2S_e$3(i_Lj=oNTD>0M}IdOncr#rc9ms#&yV>H-U#+l|N5l!4Y% zzk81qZT8(&{&aE{0k3%7^f)xjLwgCfC5Qj!&D9%K97mZPSk0Vs=#-_L+eS_}(EoY& zR}N@^;P8(~VHe*AI^P1o#~EUmggy9 zq6RQ`&mcHpM0;B9c$o3#&_|Tr>v_0(Q$c^PMXk~GEcWn1mq;-Cp`y|G9MM$gHq$M2 zhl0d%szGg;Lc^G>Qo4^4VAeQbgaa~#U1B_B&XRil%%b_nNFCk#l%W@w*?p!N-mm5Z ztx3UQ5LkOPR}QhJj@<+X=yZ%3AN;^%82+Ex97#q5NBWzAx##_ko|aE)MTWuKBhQd_ zS1wp@HueFi@`2sIJp#^zBH`|*f5lX+=I?M{;fg&p2S&nAu-qokS1CHqeVmL}6`O-b zo)Yj;@?F)3=FYX1>um27?9GjT`(DxjkD4Evm8p&RlQVyxf7){k|pt{DJjoz;0*zAL4GL}ZSIBkrULH3Qss*e_!-fTy>yb^B)|!;-|fN5YJt!e z`P)^zy1lT%ExIfy43jplj6z@JHmEf**v&Bq{;PzPk;e)PeZrZnP8Lp>lx zSZXPSj6a50*P9oNJ~D{)*F~349+qe3xWcxnbW-@o8GPW5XR^cj-sgmWq!k51oJ=3* zf#?$2LS8#cVa0wP&FLrpy9U780wDF_r15QxbgO}6Odab7FiG9!x4esoV1NB_JM>M-Aok-!=r5jS2pAgGOT6OrfS2}bfXEB-mKGDs~+PpRtg zC-B_7o#SS%hS%&^R%B}Pd?H@<^=J*-!`A=y<>$Wz$wT)f!lWazxPZCd6ydmmRxMtE z90mtu#AbgIjk(D{d4Gc3I@btoy?CjwXU;Uuc=BOmh3>egL@uivO?Z|AScRnsdil~w z+(Z%AuQ(ol<;5r;qbv0A;P@nC3AL<`L?^w@#ndJQPO6>v3d;v~jtuYo zcTG%FHn0&!-Zf)7!8jfs^kIsKI4b$LdZtm9!F^f- z(9d2jD88$f1=uDYXxK1S2gkop^guUO)Ytxz*J>aes+XHamw?E`1qGnB1k^R>GvB)kyQa9ZKA23UeiiI_>XlSy^PGDvzVZAV}hNh7+6RdB2JxoP~HxL6b$hqL&rW? zg)|c$PWh2I5|3*ud2W_^T4DU13*W@C8s#Fo|4>)SZ+BuHH~*Hl?+)pKW)^5O++7Fh z2SBe%%a<`#l^-3~C1W^V)j-KUM>HsOHi=uZZdM%Wxa4}XG1*w=cIwCx`)=q0HYjW) zIr3+EZS;PmN8pbSPXAi*+4?&R;a~fne*lP15mj89N02b%Zmt3Fh5u-SYs&!xhn0c|PIOdtA9@lK|g`m$P` zkp^KRXg$dwL1E+;)jug9ZmOTO&7Hgj>K_{!=KHClOU{ri>JVhk^`?oF1dTx)>5R|& zxuw@!9A={R$x&6naQ(v*G6X!mY!$ngy;B$bJQ4DxHS4rPpG=iFj_wGSY|}&x6$Y+BYhl8Y*fZi8n@4S>uX9ebpfZ#uW_sT)};xzgqZN;V^VduUZrxORw<3atY%ONs*O~_$>t`{v1(Z;1mRR z3QK`DB{eWL0;m95unOadq-=!mDmX%4Ry`65!?F2I`bV>I1+G+@ZXI68{fl zi4<`p#qn(yXE+t!wt!?K0fIOp`o@RUmnn-QgnG+@&&?<2#g-H98O!4kQfQle!Ir7V zzco#bp)H|+kg1qAYi&f)He>FJtPxKItjqmJp5StM4`FeWduRHt%f!Mkc@i zo%?}Z!}^TSueJ?!)H)s99=`dnGY;sTk7s`j-)ZJ-&7_r{s0-yze8Gg|v~2iO_x55ZfLx-Eu%qNG4Ol#`C5f2 z@#g`Q4x7~u7{9)tfA;O`>}##fm}5l;=KN||_zYbLw)2X_5-(%dokczW5 z7w$cJZIWOr6A<8`wCdoKktbQjr^0Ok0+xSDN6g<%a|mf4SGtJtE_AP(bqZJ%6tu2d zS<*h)xwZ+YlP_m{gd(93*fS=I(eCJtFfvhZv%v6U9UZ0z+~C!b&B?2Lk@I5(MV zWKghx&>vd!QJvI1rLnc%aOH$}#92&jR=))^l)3Kmc2?Ab4k6%2m3<6~{b;BkAB|X^ z9&qnj#qFgrChlAveZDBdz0eE6=pdEV7NqPqsm0~P7I?*Rm*c5=?7T8m)SlmJ;*(Oo zn$`h{<0-S{EyKy=k;8h9?CJeBG;qGNtccLgd?T3@4}#c7EHUboIQoRKO@=m>tb#!` zd1!N6L=sgXgCSI<*8+T*|@)7A8UnO z1BX|`Z}$PynMcR(hSem_7=XvjC;AO6EOw{@046C}Xszae@YNP5!H3yDjmB$_hZ4?fuv=>fsGXPCr88@zuVx->b|k?G~HtfAbl#RPHo=2jJ*h66MVd)%^t z;vy8$Zcpca6f3KzO>+6JlH?K)zJE2=J%JqEuI{FjIew==VNRxGBon|uUEtU$UP4jM zc3bK>MM+KJg;XyMBTMX12SFuu@|pwSTpAUl^oYl@E8Z`@^Lj8Tme+*0V=Audu9acBS6I5j+teW6!+e+$Hy#T*Ex^ns${jTz-fYTEep;Ycs~~! zvBYMDN>r6orex!OJt81{ntyS@f^Zvv_N+v18)>4H3jPMp=T@CmUO zVQj5CYgIVmZxK(QtSbSfJ^`VJbOR;%TtM$J080-y z_+YIs*6*oo+Y<}@mmN9x~`gk>T3P>N5V%l zQ^ykDSx!`#ezo*Bk|Bwgk_tC1fp_lMJaefzW*%PK+6)L@BY8kzHtVkCFtW`{3%HrJ z`Wq4;L}mvmabe}K`}Rw!NWZuY4IDcn7Je}_HX_CohE#D~Z3D+wAM8z=`9%uET>$}#*?dSrA)Qj73~>d2MfMdvvINWG!8^F(=J|->h?`O45>*SEa~hV zHb^T!x(%Fp_w^MCthiB<_xH2s#16Z=Z}BJRF4&N|aSY zpRau}zIvwQS|9LqLodgr=HQ!??JrV=VI%mKbZPnAX}LpE^z??C9>a45LmY}x*CKTr zg~Am7sBTZ`ng%|tty%eA=jEnV74-p&k!Ic<<8i)Oc%IP)WyG`|x;$sYo5k|m*&@~c zznH=z6zH3tD@doh=Sj1 z`UG21^m;3$6yWYFl0eoE5;+;h!&_uZyCN#L8O>E>B$xw6+3SaIn&IG8Mfz zKsnf5Q1o8Fk*%u5oyxUO^fB6A6+ZHqX@yVqV$1S~N5o~bnz!$Pw1R+NEy<0#kahoy zIfXyW98(3yE0}r26L=E8PSs%}ynh`>@F zfErlrwaVxnk5h)7|z;X@z#~OfPCL?b{09x=RuW#uI>Nc6@ql-+ap9 zi}s$6Yx_gD)=@!m#PQ)IC^-@aAM4qQ*#p#_w*k*9-~P!!%&VtY-S0gALq)qepCNrb zn?B5`^oza3B>js143h!(mAZ(;47(3@U`-mO#uu5L`lByyppubc>z9DiDsxG6BfGb_x_AJ%?|T zl4ne#ksQ0*%vvWFT4!^++&NW_iZOK+*!ntZ!FZeiN62?NJj&YF7{3Sp5mv-Kfl{+yDT88!RoE?l@PK_aVZ>I}M-)r|$kKbzHiS#KaQ%U&v7r@8$$Tdv~9?;snn@tbw&ohc# zvM-4XJxq=bQb=r-X~(AH?)qjb54z86w1F z0|KDZ-)KHMn5O&Pb!C0A4E!d%UX&j{EDPD%8lI}H*WX%nb@JofINNU2aC(*zM@_o_ zs5<=)j7nxXB}=0+P&znrZ(6h1E9~@J`9P)#^S@VKSY?C6ftbL}QL`lvm;|015(@(r zlKJ)(?ufMb6t3E8Zv@;xhE-_)0wPkkutGV9=*GD^aag4=>oBBbGk5hq?Kl&B`^!3XW~-&a!1UfAK2)ta1M_?B)N7rAQfx7>u~_MI+)kD{u<2H-9V0hkkDg)_tX-5K0H};ZMVcMRQLkdP|HhU1qY9e3=Pg`>W}|p_qm@w zzm4cpa%1|weC=`O>p%alcXv!R(e^#(kN3i?*dk~|j;Sgj1?rSy_<@iG@3eo@0^Em% z0W7IVAJw$(tDTmZhtogy^egLg92TOQouCsKBe0-EgPCuh;WgGYZm*@2W3-f3*v9S( zDWMJI0uN!@k-Jm%z0IgV zS~0yj;7Wq`hjBOhMC-~nSo*MjX~mhXS+U!?xQdKuM`=8?|0AD+FIG;=W3(55wWv3w zx2tjuE;Ld~hhCF+ICU)Bmi2AtGJwJcpQOot$a5uJkFwXDtj+tsJMU(i2yd%h9T)A+|U|5e4rS>w0Ds>aTijTsB;ZYZ~({q(yp zfBKZYF75SG*UGJ|Gi$#4J-j;kKXI(n8AKI+pn`wO7G99Yx&rmMV5Fc}e#lc96~BLZ zY`3TG5PmTKRMXXM*9L!2efvq=F@|+yH6eRts1L}@>4`d7_-#vX>O=l{6OW+sW_U-` zL54d#NFjh?m3O!cacC6hPpngBU7A4Y1T0b=yylWVZStC+{iW!Us}{5}D2lrah7e!xP1XYSon{}c})Zt;rz z{0@?-YvZC*nWc76pFYjhjD|3sM-p94b_#*Aa+AfhsOb$4Xep7x>KP zCTE)(30mIH=~V(7AQ>x|PS#byIv@)r!OJDApu`uufvLPAOz)nVFGOj>v~#Cvkz1Xj zF@1a=Y)A5xuKD>e1_=ESb~iY;4^_Wez;&qq|PB=EgBZiGHM7h558 zXEaKNzr1t)%g~KS7TAtk;o@xTBiLu3JYZk+*s%7lG-vn|=ub#Qm(i4?>`Ix|<^@Fc zZ}{}-)m=aBuXhXx-&j>Ul1YnEOO~WhGBmd2Kfky4)F;c54hJL?2 zVq)Al1)69Zx4Z|Bo*-rO0NT~oZkg?$PxY4v!$Z*wS=^!ba@V+<1aZTPPh>=TeKi|b z1=v|+{b=xA%H7rQps!O>q@I6wA2*e~4i9wp3Ll;)F`p=Rzu8*d#BtiE?|sQ*;5l2d z=>u*f9Ey5d+j?Glt=61q&<%B9M|T;5Geh}1bJ>d0zRna+Dv9H!>f!J3Bvms<6N3I- zBNWqr$MQbh;-R3FCeB1GFS+D7KXEvm2x5{F(O~>VBhh%AnZL|YSO=00x=Z@HP7kO` zmcYaT&577*){QuhbncvJda!b4DG!**ruQM!6`aqDSHlI|i8)FCwp)D;k&xE>ohok= zXw@ac3mT*v=RF)GB_`aBjVZ#AE>?7>HU9o}n;B8&6oMB zM_pT|wu|(Vb`^24cTtlEWWi#V3714_Zx5i7N}gu#={Yd%dc(JpS3j-R{P7sjCk)B4 zwrsSg77>afu|i}FG}?IhBbt%#vp5OhtSv53ryy4+JICB~2gWW*eBjAjobr(=E8#Pl zAaHrbAixf=Eeas&EXbe^6Z}?l2ygqJ;N4l>vcl?Iv?A(F1HUp|qS;?aZ<9<@Rl0-} zV>R~>ev#}C)O3t7^TpYY;CNeU*{ml8tQ7lA#RW;Bh`6q4s0ep*gpZa5f6KmT}WWbpd2W`L>z?|CLMo9;#pRPtAmZ@F2p1~Puq zY(E8L4XON-BbJ-8ZZ>WwQ}UB%9Wlat-Ba4CmWg~LRZW^6qt<~0!N&-uKE6^wi*E*O zb*uw{$hn}~1ChrZDF3brruF6WA(2zdeaY~THw$+p6VfJloZs%}pWC<8l7j!3yhj!c z<7Rb_enb?Rxq=d6B#z`#fSrrINh@Y=AW~l3u#s`~hh@pZMBBoc!f$8BEybU!5xQ$KF1}OKxulgaUX#qAbLpGJ&7Zp-czKEA zkODN}*|TI6>rvuXbj(TS^tLBoNe5$zaM>!**aOG`xZa$jvT~wT&rI@I^xv zNc97ad9C-5m06P4tvZyro^|HGi%3&iaY(O6tUoR&(Rhmx{WQAOD3kzOfr^~tM=pXf zR;d(HQ*isDp=b3JFFfc|x#%p03*NRBUbU1yKx948LP%0p1glg4Z$B_73IAD{X55aY zUw0dLPFOoJy6i=tERfy!A|mv!OT9z4;)La5)n{7>?9F`FMz;$|Db*2zD=&Z?vctew zyklwtK5?A6gH82JX?b1?38ja2D!pixy$J`V{$Mf_e6vTrLaIiQvKs)hsLgwxysi+` zTgS|2YUEHzrR}lWJDIXcR5~PH#Osxy4^=t2fByQaUoJoW$pHs+=E6(hKXT36aN%hi zd0pg5r0f0U+4En1Q@iH**^Lj@%nQX01-IqgFOS{)@~3a$hwv64fXX6uIi5Z|qA8yx z3I6zD&7Jd`zxg$)u;M>1Pac2y)7Ob}1V)y7+Xil#A%EQ0?B_QRIgPgb-xR)CV$rZ4spBkL;w{$kG=x+)E$?b9pDXgq zVw|0e>Q9+bzTn6j5=_vaeY1_Ype7wPOS8YMZwpK=esrtN2Qz^Rgr02cJ{2WDvfpsv z?QlXo4shqbo~I^hlx=V3k>r;Hmu8vNvUpi?`KvBrkW3Mhi3xgZQ3p=tBG{&E%gfU- z=&QG?SoaUOAFEFX6207~@PR`m2`Dc%u&yJ~jHW;OPYASQ1dc3xu4r1{k`U~YQBZQ^ z8ZY6%un#m5A%1o;U@<5GzuG3YEQA(au7G4beYN)p1K<-$r$C9l5u6(eX#C`Cr=Jg2 za{u)khl3lTZD0Nbym`+7w>jf&+{Hhastz0WK0GD7&3MQ^2cRY=p8xaHkwf?ok)c%j z;h%u_|C>19?DUDp=gmF;&(d|kL;e5%&zaXzHYc)9WoN~aO;%;EvdM}>5_j1%;fx|= zCdr6UAtPjFhmMrd*`shrPU!!>@Bep?>$)DUdfn^&e80x?^?JYF^{~>UkB_-Zue?Yf zsQ3;OfNONms@&*Xc^;!Bq0dSa66x;#TXN~IftCAIGM$5YcFKsz$Xobj)MvV!kl4ZI zU1J9g4lYo#8faew|7qT44!R!m?(?5(t-j0XIxqxyU1V*vD@gf0Gs6`xS!|*91??Wr zb^dbdI|c8u-+B*a+9sb)S|o|h0?)g++2g^ltM>i0^EQ^xes0$#KOQ*AAH3D(eRy!* zDgXRt$fq+*7cLiOwMZ481o6P&}WB;x1pzdzx7@jRr`ogfDtA;>Y#HXBpJ~{=Hob)1;D-+ps zxL*!!c2~@@Pt@~(Y0SePHU~*tN%*pG^yPOKCAv6A>#l@dJg4kntQ$62eZ6aC$v}M2 zx)LdBKl+MWfm}TQ_)En-QInL+VR6Mk)#QwJvisi4pX7{?KCavzq&pLA-*BCM_lU}1GFOMuPR=@6e#UY{4CP~3^ zmA$0FnA1xDhOiWe@b6 z55S(+?(_b-2d*W3?>Spw%%RG1_R;ICFK^%dI@gB(^peT?;_Ljt=1p6d-FKLSbwVXy zf$Cwv>C%eu92ZjU-h0=(uV#Y$*1^E#JEeWq@tXe8*d{{iqc}X?p$}zNa8Wa{!~DjjsO{ zUGcH4`>>mAcd;}PoGmSS{Ca!VW7)Rvj*8*Of?FSG2=VxPTQfMcPc7D?j;yYivDuS( zz;`D9f!?imK_cY$u9wIUl+>!Fs#V)JGS+2dG>i3w*1gIq;tu$Hzkl?|90(ko=D2gZ zfmBhdFfiKf{@Zirx$P6(L2+Z9wA<(MFUfK3JR!~eI>TRYq*y$VX`7cjH=dTBH$KuP z)ZCI%FjG~Rw?=TkSWtb*-}~F~gJC?3|Fq{s(mj=@k2e|*+L&$Gtn-4z6Y*^NY7B*E zPdKxRA~?*hpH$)6X?)N*Dv!8Q^WojF-Z`9A%RpYAPMz=sZT4&SUsNnY9l|zgSD!jN z^!wsW@7dNVFh=nB4@9IOf-u$Ru)qVR>}Pfx9a6qi z6Q8V!Ut3i{ap-X3cm9Q|G{}UC$Req-^*r97`r+vdcO+G@lGd-j=-4WduT+4PNUGD; zQ4Gsi#EBoMm*mBIYz}U}mu%|7r+Uh{dw#ffMTT+kfwc~5*|zxyD9C@_BUg5>tVi^| z|MehqqV@hx<+I?W3P0>Ui8Qgx-*XQCoG;NcU@z7wM6htuC8Z+ZG9W+V5yOi8h^w;a zXC9ExRzoPJpSH~NbKAuP%jp+KmT^}?5m%K8c8Q)J|^)d(jx@+w7#B2A> zK}GQ&O*u2(byYo&CYrZecJgzoF`Qz}_rL`kYZKp}1~~7Ic>cUr@mSAjOUR1j8$xE%Op%;e#Y^k>Ta*YywcMP!})_hOyR}V8Z zCXU(4{t5`sBsCxB)qi|+FavYCLYCWYty_4YG?QDN$ITK;^{ajbJF~=X?pOqErs;3zm`2GmZ+l+%ApJ;?@k|D(7BG9oV|X$lOt= zmdzh%X^Rv9p%VLxG7&*mE|;l?`_`j+HzZ^?i1(x{NT%Zq{udVSESyuqBsCYV3@m#|ub1CZAZQk-*YM@p9>Boz@)`Qh1OhRM&U*6w7jFSs` z@~eH(3lOWgt6|yT9&!05^p$->Xg7Q}C7(aBjOQwqwKf z=chXIbHA?GP36a3X>u9nPLJcv%L_)4405k|g9_f;s?6LQ z?TVj>8@ML#-}ks^apKIo!95+MW%QDL{GCrqt?&83>}%{I$^G35`2#W3!EY%4?AN<{ zUn=1{nVDUUtd7I>#^+1()`{TkMC0nkoLxcD;9=r~TdN-`}-+lqkVh9AanUk@s zQK=(Qn)+IT5?%GVb*!yV)m>u7`tRi3{QdbHPSQ@evgP#|FP(SK0S+SX3Q6c|iC&T8 z7YlNfdYY_fP*96|55+dN7;|_%!diT-_+I~{BJg6s-r)Cxb0xN&5}#kgJL58HGbP`< ztP|(!PFs$tTip2bZhZ6;)#}0u`ObwYZTUc{Jav9I55=(i#JrCJ1iRtOr8YMPR}z|_ z_W|jd)eD@~?;bGRUM}CO#>iGhopz{?Gaa?Qy{ppN%HP!a*7Qo_I?#H`M;>yZ4+uU`P^Fx}s}(FBo#JmAtR9}W0z=b}PufwvIS8nTzp~wGU6-8wbO(&TZc+(ty|57s z&WzP}2i{$2Y94lEz`R~I1h@FzkrpqF+rw-<8@@DUsmUN$I>>HztXxrLwdi|mqMrHX zKS&bay&V=?;m6|a?xEc;)$NB3GzL9cw`{}t;)X!05HSbi%2jN+!bw-z`J~>@_AvZathoJoZF${mRqKg>WXJ1~G`Dm?_L6MJK8M9Kl83+bdPKehlK4v- zh}A9`pT#~QrIn1{s!Fpmx#&0JK(;+C@ODIOfX(8wypoKEtT$7}WXhwd+8gxBN%pKH zGid!#@%=4DmpklUF`h{EG+@eNJmg0{=;ClZsUj7&f5msni}v23wYrDmS893g(eA)z zpU}xrvE2%P?6LY~zNCd2uNfYtdTwy;T_alZ``Vox(_3OwL8?_?0{hv~;lOo{U? zWfI{*oz)8io%)<(#@2LOR^~)j<`|(jFNCxP232658`bwxvgwk;LeDi$ygPF*1O7&o zK2`o5r1QvZKw>C1;rT7E`PawZy5ygvvQ@y|JQ|SOa~ynH+X9~|D=ZdknZH7>PZzB0v?cSX>@N09pFG!k z=Bd35R>`qnIe7VeQN`1+--#0oVIQNx@m!p}WRLQ0|I=UGlFO(E`+NP>YGK13+egP& z)(;Qu-}&;WOep5&jh?<{C&h1YyH2KrV`8ggSp0|AMC8lQoXf>OJ=ULLHlM0HU>j~I zFUo&>Qpcv~9i(X87u>pgqgpB-B|T;O^=023$F8YARqEBr-~Z?t1qH|tIkZdYmq>Mw zUAIm1iu8(-)GTb%I(v)YwOYQLnm+A+kGy!sB2WhewOY)P@CtaQTiu}9vf_)JTI<-- zp?m%ls%KT9%w7Q@B^E1rR$(i>jtw4p?-x0xFXgv}s#srtcc?V~(p4u@hTll|*4#OV^~Prxi7y%w zjJ;^TD0>ndk*Qs_EbkBB9HOq{6=S&)7a3wd%h{ zHQl(l)Auchg>xV_Q7cDcpxSZ^aAcD&;4JgCO$9n%Ir}t)riWGtQr%xZ*QXU;{jug% z*Dto}qElURqyCvON5i_+R?Z+cv4uC^dZ=F5m}9iVq&QkizADbpIiH&M08&>xRwk zcCg%+CUb&6W9^Ua?_mz^`QiD0EOz0u)2lM&bFL4|zQYh5uYrKTqHkp9T1Y_OpKn1g zGiAw|TTX+PW14v(mrTF9uXkH!MNKy>{R%i=sx{~kX#4g)^2btga==mg0KcNOq~%xZ zmqv}43Yk1!Z-c}!?^@>A!_BFQ2mNjmoLNn{u8QW-v5U7^HQsC9g5{}LZ)LUI+I0bB zh9D=iXwXGfn1cfO=GE2=+vms#2#hDwytQuNq_3G)bZh4RFDsP$bh7+AQsZBj*Gnx@ zix>TR%dx+z;s*??ovzDES^QWWGS+?UX`r#gA|io+EryJL(+7QQwPjWQ{4zvamYvaF z#vhxY+14+k;9bbF`b`ClO=xsRc1psD+Yes)=4XMUSIhFnCiarohaNLkD7cEgyELZ# zY00r$bH~dIbo0+j9F+zwWA`2PK1*n%SN4w{ezfMAUc3RWZM3ggeTLZy83;?3$Cr@v zXTjkCuAN!EzAr{#8d&k`YXuy{RL{j~J;L55@lJPW$}_94Zcm$Si%$o;4~TyUElU<- zjts@PTdOZ-#w850&aD{u{(~-rgvGV8ZaC=GKU!h#YwEW)4HR1i$BC|B2Ewu(77s0d zy&cWOP1ff3N5BGh~f%txqYnUA#EDRHxYcOP*ACUL^|9F7zB z1@}-(LP#Sb#^$LDgZH$Iu36QIA0W5)#_kAhckVHBHR{t|6K86 z_}jT!3A10fRfKLk>VNp2{`z_3To*ReZDL!AZzuJU4|7NABZF(=OXrGj)| zD7_;SL2K^BZC7J(Be1GENB=j|Z>FO`=UUkm{bANR8S-bdMsqhhhJ5m$xtj+1d2BvY zl0CTn{bkshrDEw6E2g;>8fK3(F7qF6g1A7U{z3?>rlkkV`&u zjVJj2Y)^gefrF|_Q25#J+wo&^yPk_*f7yYfBpgB2g@;U~;FR0b$jxmqkM~K>O6@e} zEqU&1#fM&@2v$ly1(%`rVme6w{kzBWZcqCU^-lXNhk&g0bfv(0^@}*d7di)6mhi4^cM%V%~h^ zwBQ|C&m0b~S8?LwW}H{52TFk+X=C)?fM){T6|y0iqNUw)IV)7>+sX8AaGhHFuu$`{ z{IIv8LK;=oYHznHZoU<}4Z<3KhcrQkyAw;gV+PJ&RSHx#xGl{FE1y}8xe?NQn zdUUult4>vP_46;xM(`21gil$@Ydv|!+}-*;zva}@^m6`?@Q0q2&`Wcn;d!CM8Q_Mw z(qcVPheR+pB)6g}b8+XI0_N9m1x)LQ8^Bkmi>1cM-+jA#n}}6CpID!IaEzFr&;UoL zm37`garve-;;W^@pxJwpJ*`uV%q%H^QYI{pk6^ZsBi+SZl8eo6G+ByyX=as2#tfX=QTSJ{kHhL zUOM|gs=|F`zO=W`VXEnKJsh59sCFaR5L=@4dZf@TAxL8M%cHniW!#t7CM5#w;~5#X z)tCgK?~9W5<|2CWZ8jgop4gky(IVw;H2hX~xF$6#1qSWtS^XBnl`9u^rb$LBAD=ob z2;z3HmhWFJzmCYfIb}Jf)duEng8uW6fhW5Ys&1fj`fTP72x>Qr3^ii#J>^r+N>%N^ z0oR%)nG4IaOr_CFSf*#|^G8er%r)D4D$#^<)4X&>rJzo*`=Ac&W_S3;ZnbpPwsgI<`H+%#xoU})YAW0P zS{6&-jT`UdaH=Ak8MW61Ypb1n=9(TCY!qe)R7x$E4h~M|4__<|P`{}~#V9W#!V~P` zP9Uw$d+EZ83k-w6(DunA-m)1*Ou4xS^5_Qarg&#sNo>|zQbGynjZFphtP8{C>k0vx z%P$?s*FOIde{~(Tq~K#9<~vr`F=E3yupR_vc7fBgQ{8$uf<$Ko>*DXHx9k*G*-Exv zf7*i5pBy~gRK2L@_MrU1Y&@yCV4OVpVd-^3(@@V3cTVD}wf@+B*Zh3$;^y|1N)gX1 zaMpp!Tsy`s$p6e7he?z0q%3zw;;+my5+pcGjJ?H&lL}AoO8+=ym^5H2m2q#` zU9lL4H@^^OvD@|iNnn{V&tcM!se`Ycvc>)G@*gtRX_}rHpA2ZZixMzHcxpso6fpsh z$4cIR5Qh3s@-|)1b6fAUyR%)kHaOFHBSxaP%hoo^Y;7vrp+oRyN@B&(@bo#WXB98m zoC<>|&#GQksMXT~j&hQHB-km|W64+}i94_ejk z`1-Mg(egY~ECy!q-d2~Y%@K;>DvVem^J3;|hVNz1*@e;7F@C${S(J~UfS@2JYGH@F zq_#CSQ}C?(m*PHOIlXJN7)Nw{ZvU(maTQb+=u7i`r#wFv7=qf>RE4tw=8C(qKI=mv zG9c?TvCD0YW5S<@lIchhB)wE)*Ym#}jzG2J9gKt=his``MZ<=`Q-F##b9PTI6 zeX}(kUR;s8!F5eV`CQ}DrcgUkq67E-`#nyDdpS$wjC*mMUr*i6wys;2e0&YxT#{I5 zF31V4=*pDa8`Xa!`^eo^Rk>B|AV7())ut(6YH7w%*J{bEV&L^CyR?{O!?_ow;Kug* z&cnOy&JPWt6ZE}i(rcX;MzUR@9Yi2jq7I*-#vZr>?@f)p?co6Z}sQF zVN-M6g%XEM=la1X_^S@DZpvNDxxP2cwF3CUl10Knu-43jikH6Ky4OQNQE&HLqb2(1 zE@veD!|J?=X3^4&;!3k#{GtcRdKffKYq9piqeZmTj5Ac}XhrED&hM))*>ql2zIWxi zJLLQK%2h)SVJ~a_gik(yY#sj{#ISA6QsCH=fClhv5ne6<#{d-!`b2u~shi;Fi zW74J*HDf9fn{1@B?(AW`pg)R|9zKzbkASXm;Ntd~~5w%Z5EXo+G;BHQzEsD%q40qS@)ed>sd+TGR z8hOeY2#Yea7VIve+5x;G*b0+$Yb3-G9YQu4wmkg2P0roI1sXfXtyH_z)rHU;6Opf* z5rPW+T0iWHY4V0YY>%ejhxI@nynY(IEZq>)CYOYi=GSKXvcOHJrL5vE@!8=%EiRsUj>;TY6gzVn|xWmm1|MhaAwXm=`&`@YAHFNN=LNJzie^yt_sZ z{!qXYqOyDH;e|}Uo*0mO3^9z0IG_piH5;%4{@iN+AaqxA3>Q_+W9pys0%pL+&cMV(yh6V;Y)5A6V*e{qA1*34%5BTxJZb_5)|e>)9J&w9!pQq{kQABRSv`69ZgN2uu_su;tXi3AQSOShlA7t{-@nUm8p zWUPcO*H&J=Viy;FXi}tS6eXR9pg92~$+OgofdjFD%uwtvLbL*t+8PkEu>7f4<%EP7qM zyO1g=nVI*ESb6^^dP@ryAwgZu)1?Cyt`&m1;9b{9kw&EQy%S@F8j&0vEM^yz&R_2A zfFQ9_Bec_`AMTWzY;A^^XX8AKu94H zM%tq%|MWnxbsTz)E27ztjuA$qpC%lb`JtS4{z*j=n!|J~Dw$tDM$o!gZv^5#!{~lK zdE|MiLmszs;F^hmMwARPnOW$?Er`Z1KMpEqpZ}Dcgr1A12^9Nm5l4GnU(BL{j*(k= zR~%n$(j2&EQEK%mp6NLnVw~6I6?kP7t6Z-8DAuq%kPscuTcgzD&=Nc+ViKvb##Ls9 zChVy)BGp~#tE8RUBcfCThCyHBQ=}i3uWbmRoDPD9nW27Nf0GaqL2%KxFiZ-S7oIvUDJ$fRtVqORZB21p^azO2?@kS-r_1(lw zs?X?);|o&&SU6=^5?mR^#g-kKAqc_lzb{ax&8-!A#*SH&5y>HDQ3gy>pqNFqNg}IO zjjTRD9IeOeKVA*cPXj?koN{bBZ_c{K^o&$oI2og$z=E%)M`WzL;(C?rLf-WO%YZ&) zYTHwd+$T&90p&;2`IGtcfv|z=J-kl4ZD)e1fssK2^-BXE0SzI_p9?+j6k-+=idwSp zxpUbt628cxnTBO|jsA?*3oVX#!q%hu-Xg6y zMJuDq$`ZtO`x)%R&MWXpC-N=|kpXNU3J0Jgmli!Tq*oL@%NNIF2a6s#0uBlQ28W1j zce1aJg+~#n!jcp2NuK+f<#O>ELk#4Eood- z;svQsFtA2gyfVqtAXEtIY2^7OP-iVZx*WXS8CjRM;^9!)!o}`q$zf_D05g1odSy3P zeMV#Mf&(How7`Sslr*p?0!ab{SLfX}3rk%)w0~U`HxEanX+g_cJm4V_(f60uFRtIZI8Uu8lb_2r_UG=dM&o3*I9pN-HEWJX%S=b0aVJ%5T9 z9pVxY(P9`ocZ$9UY}aFIyjpzCh7(B|%fBS;M55>Q;A`9MS;6wfG1}Q78zL?^unSyG z6p&#`?_5%$uGT=Ls;2h0pTv21bai>oa4se;!#R`#QE`wiRe8DCF7@aUtPS$-X4!~y zc;TO%1fMHoL^8JlgBj0M2tibcH)j*hPkZn}946;Y(lo7J-*TxRc+n_MxLLI^*&c5a zsdW!tBcU$HsxcB0VQJ|eAef_qX{3K4D zoE*=?1C*_CMXru_PLvToC)UF*(;>jDXZ0E`E)*aioAr=TwS8UhVaKSv3kchEIarwK z+7g+Qy3G?#Ukz~<4rgIWSy<`JXir!0A9wmQL>;}Qu03+Zq>)5}rB^zlL^OO21oROT zo|ln=6N>DV$4l;+d!pPiNTi~8Vhn-KjJ}L9MNpL202#l)RW453*51Uq`8ft=!qmq% zL?wL+xQJP#-~1WFU6J`W1XqHqtE=;;Dt2FGAB<-K{DYqvbpE_ zx!Hiu18}wXsa&i(64+y?^Y4^I`ESpFl zAYRpI(_H-0Y}u)f6oAcKw~v;h{&7XdX)s2a6f!3Q{AO_9Sxi&e?;lCAvjsZuX<6W5 zl3cxonoMf(MJrCIk@mmb!vb>x2Q*H=PN@(#oZ2u*igy|rLLa8Mj*zGhAeWy%Vi`gG`W1;`!G`o+3N^Lu-DS3s)>F| z^51e2C<>y_E=k)G=k#0BlPIDIMj$DEEBl;$m?+8V-^6cn4m9nRsXj zEmpy3z-U0FCDa}x6&mgUjfy&}mc>m!~ zu4DmRZXhf5>5hpmw<;Ir6z!4r4HjVf;y1$Riw@{_fGr160V9%PU{bW{-*LA&6hehG z2=>6s$u=yXuvfKVx|zl=jM?ax}oK`_lm6;Bo!>0PQbB8J%Vc2 zIhUB28&$dsoB~oifjW*6L2{bMM<>Badc1zBP$H+`NrpBTk`b?ysq4yQujN3jjI6<# z$$6OT<;z-#h0>qfz2#BJinDHyE{6z|>7(pUUG?gLY5BM94i`nt4QbNwBH?O{M@(B3 z2THxd5)G_7*rmO@ZAf|qeHA5vvV^nKLYEA2GTl<5312bitYas>=!j@PW$cQ)F8wnm zFilwY=(JXQBClG6iHruRAwP~)Up@Z{Tl`3S?#}D!)bOsvnjUMjLfKa4HO)^k9AYT) z;Uk*$2}^(5x3X5j&pxUQiVfi!0xBxvsra8-=_VCw@&n=Fmcco)H`{3}%|3Kk{zw^K z8hw~X;|)(Kg=r9QumyhYE#NS@d;_7Y-On3f?U(+gGRA ziw*raoH{htoCU{FZsCPDefdv3RgUan?dp%-H~{#Y>uQe>r?ROR!;s*lNn=93CL^!3 zSa?VizaIDXV8QmD?hZu8`iO`oON@pyOUR?Z`5U>Zsj>#bqN#=SkW)WVOxu;yMVo%3 zDrFiy*S#$vO5+E=>YD<87?B9Yx-j&Z;FH?`G9B}uxCp>}( zN}Iz1#9?3U`;ug}#sy|gE8WBN!T3>nq~GLxO-;N>oLZ!sH==!uMMa_#GgKmo{c6=S zIj29Dj9witOX@c19+j75&~ZIMv@zpLL_XAY*?-gz&MhF6Iaq}4_4zU&!mA`#{Q=#( zAW)%WqybwqoUBW6p8z0Fq9|fJ0h5R<#z{N1=~6Y6@VxQ;@djuUdp<*^{Na#}X(SDY zN+vP^U#goNPX=Lu855Z}4cqKfA(Cl0+bS@N~t44p7x|+sMvjb{tFlbXEFmRvNjAua~ zL6k_fD0)X7ieAsxI{-3C0XGQZC(09xRE?7MprsP?gW4mGyO}}+qG7Zt0u|z-H1al; z!UrdgyRFn3Y;t5B9GVKLrAX#jaghl**j4&w_gJVlGv=pJ0Iop2z>aWY=s~((morN&YSf=h5pEJS z3COEuf#_j@WtG2t-AvkCV8P=UDL!xngi39C8-UruqSdL{&rzLXML2bJXzKnFmZjgQ zv}+8Wy7@a+EmUKU76B1b^bYBZHj)Uqmf-e{ums`sP{l%3UZ=^)(7PoXm!*h}9W=Mf zskV89%Urm>28Qn})T6bJPQcix>RWuhk3!tVH zkoJZ$;ZbT37koaE1eX0$h0TqR&X&^lUReS78I|sD{6SmZK(hdIf@ZJq&wtQM6<1Ml!<4uG;9C=yVBz&XqK@wPX>6WS^i_e{{nfWjGt3`BG^0twP5`pfEWIn=*jl=$PFw~Mqg&07xo*+R7epV z*sUTh5eGP7DMFmMs7Ol`aEX6pSQ+l-8cZRmeWcXf?w(eJRyMa!yq(L}lDEn{*_ zWuC3_OxOtNkduO>ct5*I_J)1G$0Eka$fKOrLrr~OVkf)l<=rm^sG+Z{!#~db=83;B z4ea^@q$)(`-_6tp8~}aII#^+_vz<_sR|+_^>E}QUrwu^cNW+Jrr!UH7ysE`iyq>o5 z6W7|!NW;<9B^rICSCh*>%wH8OfK%^}PEuu?ZV21hz$mqMGlHPUH1F@x4Re%|lchj~ zwIwZ8>{s7ImJ#i({liR-hq@+3XRz!DKOEEZAK4A7JuW*25?=!~=~8VWfx1}0 z+D4Bk4Oi(EZ8#l*cyW&+Rmpz=&1CyNkkKh=!3hoaQfNT0%A86RT>KH8xG4SO%}^;3 z^~h*04oh7rDY}#U{B!WGPw|HubAM4d_&?|r=2Mb14vAHdj+sAIWXnT+>5mup-#u>j z!1TGE%T{0f!c4|MmQtgbl}fwTGggF3<~O+;d3ynfdpb&)>0czY#fo=fmFx zr}o^rcJcxr7}cS2tT*RGQm2NH(zHOvHeCuOL&s#d0~eTU3uWYcN*Bm5P92RGvu3X@ zVc6#$hsukUGf)vl7K}8q9~#_zF(f7sZyFo{XSN-`70MQI96UFV^uskv6JA*v7xWgF zv4Ys#*MRgK{S%iiJUdOZDW6&T;r@vl`xq{(wk(6;;`JnSK$ILfbZA_b+Uvu>`Xh(* z$K%b8++A)y(Yd#h3@H!(n!Azd>EB?udzFT$_vyELflZ+=)TNFdp{zXEQ(LM@H2h9U z{E^WR0vgf;7jh%g5)vP=GtL2)mjrS5I22E+CNSbEU+`%HU@Y&b_d@C_fnwU!8{wtA z%zC`AvFAOq`q%pvq;HCjze+|WyIMZ^#-@Gy_r=DSUZ&k=W1DUaYQ`oy?di&8c2qLR z$z7`b&@0@>@pzf&He?yo(L*}=su2#P0l}0X9|)(g^mG9m*yUU#T!o@b5SRnKg2X?i z4F!x9@Tp*XMdMY#4^H`yyZm$kD?b7(#OFCR9OH6**ip306ESTn@RxZ~HJ4K{^!ec^ z*guGs2f;z0C$p^MkhBcBf3la{N$f?S60rX;#;^#?mkE;Wm#}#L+}ptLWT2tGQX51_ zLhoCgx+2Hx+UJ-XWwNp@uTB>^=NTi^Q026LIIbJKC(Xzo;m7Caq1JxL2#gq&T)t*| zZWNOW;D_6yKsiB^bcza&2Kr?ICX88g$d6f<>V*eG;v+gKsG&iXB{vH0F%TiXuYDRk$BLcj{&gMeOv=w87{Mnt`sWh6a)l^+lm15zSlFU8bS_%8M+X%H6z z^NXE}&W%I9;M$YJwJ1jv$>^(*7g&Jzn^hqWQ?_P6Ku28ygd z=Ri=}^~UArvf!I#YIYcYc|_>dKM2xXrlSTC;1H85j3$iyDgMOrWQXx`1R52cn<-&a z(*aH&8Rc=X3etZfe=PVZq>mNbGl(r%^_Fx!;PiKzRJdH^eULNX`ZTuAX~^f*8_;{SUz~1I0fCf)Kh7rlv z77f;4pv=k)E>J+F2miq3y>2MI-`{V zXm*F@FwF%;-ye-b|LrR#F#vC|_DEX5+Nh-zVvs;?xBy_FAsFzwu*Af~{}LiVph13x z7a)j3V+i7I=T9RqPl806LO*VW7HlsU^Z@KEpTTmVUOC!voEWuE32}DmnwpyGf4Vtc z<3osuxPM`?cTB#dn-)>5^m`X`^S;ZHap_1ePra`$t&J6Jgzk%qG6&_|)sYKECBcNq zeSr&S3^PQ5ybyr|WJ2<3E&xcznN@OMziuP#yfP0`H)e|};LM!9C(*;`fqJRRMeG2K zNTIY0<4l^tz#~!!i!I1Oj^ZEz+YSMD{rK;BJpYp38Bj-q6Os^IKwjeX$MB-m-Y@cT zT8sVnH+b@|+&>7tn)mlUs_>x>ijcl!E_c-(lcRh0=nd`V%MZ23V%j>i&xid$u!D-8 zLy>Ywt34wq6=@KX0J#(OB9MX4_%GcumUS<&#GhtaS^L{;*%gt-OOq<+3B%gw+R4__zlAL>xCu)b8_ zMKj%9{7ZjqOpwn{d*Sscyjv{%JTZikjv5xzMHC$aCAnabO@m5SSObWv2qPqEP$xiS z03@iS`#H4%MQhS<0CNJuA+Q_S#V~4-G%hZ4W|36)7>HyE=ioJFk@j3aJ%=KTKsZFw zG%L~o1dZGFqUFhC>uoshXWTly_HZUO1zL6@85qm@SHQ z9by^XWw?6g1elRAj%s;EoDw#TzL+-66Jte*ge_)x7#(NKr|o^@X=(-yr~ME$brcH) zD}aF{BmwdqP`$v=LtxRJy2K;O%$U%A9^fmWKr#d~0~u~R0CVCay(-A0p`pZx(L8$O zFliZf=m-6SnCVwef#0_LbFqY7V5oZb19FK&er-{w*oKurp-edhR4{kNOaxMvi89C} zpMndKF+If9F`RUI*YQjDtj}(;*$jKY&Cxp)VcAdMi;{F*qz}Wc0XES2;y)-0?|IcH zg&WjdD6n8@8v<2YoLnSeb%5JO!RYHj`~&m?EFP_4hM2A>4M(Ry6>v8)ejIHW^b2MR z{p9qciH?T9Z3siZr;eik2gQS|0!^3&vhp0r z_K)bhaMdRIQ%GsxM|?q`5zZS00zxc6?_t0&+5cF@A75zF48xZW7n#L^|Inmsd;c(u ziUl5{g#yLO9)}XcUFuWP;&@O*))&B?;zgDAkh}aH=iVHC-tIAL7WSg=ybO}QEef!3 z&!rwksU@@Z2&p*oFJ0t!AURZMIg{B}!EN`HRs#yG9{^Jz{-5lpsH0)#y#i5)CtcL+ zMRs=cT5}*V2Agt+7Y+R5T_%;i4e;Ul=y;~tk6}lD<4;b%0T^o2Tt18d`rhq1h-~A} z*S^0{V8^lkUu(fG1H~_>=Ax$50jC*j7}Dv;!qmS^6fr3?DN+j!ZsS0ibZg7JNvF79 zmVLf9>Q^SkJa8EmI@(8QoeTD>231%lL&KNUClZT5d6TlJpa_MgIF5)YrYg*kCdlD* zL3R-%Ee2W|8sstr_BMDLQuTS&{pKek&8O>qf7I3c&UZ!`SL0WN4?-{f0h$Lg3&b(P z)%FR8Cyqd6^e;aSvs|x|xjCKxoj4S59I|69OmQ(1#%c+la)CdSOE*}^U8b+a2-lBo z9-Zqqy7|kAtw#}pb%X4zeZz&oI9q@HG)*5Lvd58`9KjS(0Uu> zM=9w<$VC)s%t3UNtllNVEildPx>}TD^|%2^_Q=dK)!@7Ao4{0kVb-8u{6N7?biZdm z`mN1>s)#?u-{4CL4&hFk^oL5oqo_9B-yBw%Yd=;Y{sq_pfzERNgZq-hzFpvsRGS)K z%x2%&Ca&MJ^)7z7XoItf*=jG178?nr!;1h;$M!dr*7ST8mvgD)Dusif&_4gU5huZn z&H@d9hu^(z+J8=+u|xaKN7I2I?+{d|KB-k*w;2+Il2O1 zRTBf}K<~m91Ti8Zic*mf;4OwUmtp47RNEa9U}K%wA;Vk2{N>dV0h1!o8F69+^k&ad zs>K2(&@Kof*9(S0Js9+S6l$RVL424`EAuWh`%rj_O6GDpW_k3G-yR#%87{|fl&2P| z%)WvmhqO9M=kiJpyL2Vq-|Y1ru}|3l>FJC@A42rJ02!db49rx4Mx@sESdj@@pmabK zpof+a8A}t&cvou+siw}x)vM!ltGldnBqSzO889dmWwoR7WWVH8`v;93 zsgE7;kK6`Lm3u9gQLo>$NVe<#SLc?aRFb8!+#M0h+hjtuMuB>kQGpCHaY2X$spBHY zuN9}B_OQcQIwXvrDY9xeJk{c&dRig*-uk!*47A8_;phODAr`0uXFf$0Ad)4Glh#0| zPabfEDR#`CC-rD;c!kp+-2ZjcLn4${Ev4!~5U>n)jRJsqk>Z6;K)pkc}=61ywpxo(57E;A}n15HTB;p%CLl+6{!WLbXt zw#nCvUtzp{V6vXIG@RDomfQ;1Ym-6<-Uf*=3xV%8t6sAKA_pfiO;CxEOUwPs7r}=M z7*-mt$#psdN}qVu#2~O8O8&H2(r{X>UGC@cmdoGP{09wH-CJRME(Iu>YO9X!&t={RfZA2e=XaKut$+wZ<<*@`^Y2Nd1^8?qK`$bdSv zBYDts9zZ|YL~m#RbT@tcA`!p~g6K^i6^3Cz;S>*+N5&YXL<8bdJ`8y6FfLlp*KE^l zU&&wiyO3+sc{aGMD>}+JY-5xl6RtdEd^UK-KJeplpf(q}eLWo`DV!oMi)8O~-hX)P zu8>^3e|Xg$#S%^Kd_n-ts(67wi2GI=>SxSbhr}aUuSLlq$Wm7z6ZB-X-;R zl2@Mf-ugvaAH$(ZZM}~fL01=nj*-^3!CxTlro!28!wUgqoqXNDnN!bZ@kd%CjYrS7 zCST5|ZtcJoWiUKs?j5#|JPWfaf_&Qlpy!T4iM?!roL%SW@!UNiJv|dV7r`!qfXtFv z5|_+hS!zU5MO5G^p%xB3cM3vS(*YAt<1(kRXT`{q|2=L4sVLaQ%EZ@j7{%l=6X&Nvp8;+Wfcax8tL)tPQjGV0E~K(4bH2B7n1 zSEj!z|1FQs6lw=#>o@L}D}uBJBi;0YkdC5z--|l!A0h4e1!8#^?|!iP0M|N(o76 z6cBy({hjli{lnQg{ISpHzOQ(_-}iMVsds#EOo_;Sxt}2a?d2mOlHbUbjE?LY3G?0H zdbt^Fc#SfU#6d~*%0f72(n9p!th}ExiEOI>Q229Od-;AuUf}7hTvOb&$kY$-cZ4z# zNDCcU?dMbEi_I3!<54MnrV4Hg_4see2BiP`!4)DuJCLG(gOukyM*0m<;9r;21kX|y zC*iy0_WtP(GrQ$G4aDDm*Y*&yk7oXn75^if>`LiM4cjtE3ES*CvH7*Jpi%E$b5+pJ zIo07lb|u^H9{Pb)Q+|Hre6uRaEK%)Z?cx0+ns)#D^JYtgMQtzrO_G?%%cgQiLxLww z;y+w@DSyUk_m2$9UHI%aDI=)F*?lJY%1Ar3W^C=wEi$r@8~HP;=QofcKEyhY?n|n* z3Zt@d<>=%1_UpPvYJbVmPiP66bk$Cb*VlW<-%ST`#%K%*O}x-Oxd_->XtDSDafA9l zSaa#^lTZ-E$lh18^*7n&qU1>EsNz-BugUZ4d!l>bH4H&trRC3Y?uuA6U(46-zb``A z2X=$A__I|a4_vrj-&jpjr>hreZuD#Na___Ey$EKD@}m23yOixANq8YKMcZE^jY12v z3o11&eu18l1;`vQSpg$EWVMi!LHtKHV}%aITeTZ|sgcos5 zXtX&AqWsuaw2MU*a}h zuYZvCLiN*lUIZ=P@V<2jAZ~a3+cm=iKgxr|u}ANh1cRN_t`cXjZcotHl-CdJkYu2% z+qThk)fja1*+UQ81?`stF$Wi_3-{EHw{*^Ks}$Gy_}Fi$Hk0XGBH}qpMIv$ z5aZ=}*BPeq=N-uf5ql(~{BkFkt(c4L5kJ*+5~6dh>TW<|!;gj+np8eW?k(?}+~Opq z#jZwhN#4jW>d&O4yGlk*RuO5utpdDIC98)IIb@@lt@~i*rOGwd_LS$Ts zWZ*lUn_nbWr+ojxLs?0xXxZ*OlO%0-8V7srcnrEgwU%W(WI8YRW< z{8uCgT@A@cd_ZcGM|D5b)aSb}A9>wF>7QK$h@;1ZW}Lq${6JEa-m1w9Tya#FQl9HJ ze^j_|L4LcjFVG1MIGGK;hYY$(RC^h5qt@$<4=Hey)+-eq8KwHY;q_yNNE&7do@TcC zF!j`%tBK?H-|cedt^||W@{?R6B-1O?r)M2%Bopa3ACjEFAGa!hA|gNne(w8x{p}lD{@LzL7k)At)aTD3 zbSw8sY2@v+1j&)jEH++a)J{p;|FYNHkf`mde?kh7BsGat6(5hSj>)2dC0`-&P?oN% zKP2`<(o@1|PFD~6nKpCRGStL|WhApJKvFeaz=yKFEw=6UVvm(qE7S@UAF$9WJ~8Es zNq&q}{Mc*5ORIS-d^gJaEsfvSF{$3wQjLvPjY*Lx>CU~*X7{mZ`*{l^0$VN4&$$#B?c;{OS#Wya$ zZL|Mg#p=!8`W&{#+GVC+q=Mh$s+T04DE-V;@ za{22bi}@>~LAmdPM1&w@rI347<5XBB*vlg?FZku5Bh< zKOpn^szG(@CY#E&elj(#+nR4z3a<5tSH!Abmnq*ay7|*wD(THkJc!>M6k#RU4qvu* z<0#BOzqK2C&Zsr z#r+qj#vUbva{c%iK!l$ zw=z33HuAumOgUV|Te?Q=VL_bmSelyj6TTJXE{T(_+F8FfyZ+~bY^1IVe0$_NbH%Mu zfl-y{TlZ>JItwmCpOpIM4xU~@Oi?@^{_<~|nO`(xYpTu#)KP>@fy0)D3wNe1r^@Hf zPB&|BE@hAFg)@vze7?+$Gf+%fo;AKNg>Kz5Dy}Q$t3c`N)(1tw7~- z_Z>6GRIx;|0^)xh;1_9iPVJoj*Ioa&POtvHy(GPCXwFhzCp#uApj^B}9N}>Jw`_Z`3TvAs7eV%R=-vmgv&fR& zo!&eksL}O@Y_@eE`5OiHfqR)xQV+)-y*>Yd^vPXg$cqfOUWpjCOOp*!?SC4mv%&TU z_D;2h^x8>PzCqc44LQJ%2kVHs?KuIe)8<}YY=@&l5p|*x zNB;IV&%2hC_V(jk@!aFcBLju8PeJxC0ii$~@QluaL-=jFWxO&}XQ#145qEPL6E-|xn!WjCx>%WI%1P`Zvoy%5QM^-96w=umw=dXRG|5dY)JCr(Pv#tS#0@1{U>z?8R~7BPr??Y zAW%n&)4%rrTLN7MHRHM`Kks#jc&ODk!-%YDF1UU_k&My*a-iBjzo7a865r{EW4 zw@99V>m=4cKB{scT|>fXl3pV&Y1O#tl%`4qhxC^xFjodDed`WJ0lmg{|Me@bWQf_d>po2F6#-_AM80{Z zFXipUQN1-WisqIscHAd(+;QGSwB+9`beOhDa)GO=06#E|r#d?=`wYv1tyR3gTBcUn zCBPHT^85`2^)wlY4v;p==#3Kg{s;FomhZ2et{D@KJ?|082g)=U30bc0^7Di;guGGP zJjj}w>fWo=bKW1`&M1f3&kAhP4jv=>d@??Rg5g*CUEyArM#BRue{Z9wd8B<^R6daE zV-MXQ6Q^JQq+b4qc$(bou4{0N)@GxBncFf=yA=)rS3{H%>l2><)tN(rDc{~5Vf7=j zhkT-<3*&EEZNj#Z%@%)OW#H=!hhvKv=Pa)e4Mhj~9qo!;f!~V956q)?F8wSgU|8AH z@j->Cr^XN{Uu47ma@m?DPX4-(jc?73^aY-m;I&!R5d`7F(qfw8T-;+-QS{Fj(MZxO z)n2+6ZV}+eYMm2@@8pJn?C*9ntZs1ZgW<(NrBRuw`GukIX3g=O5&@O z+w$JfpDB(;(L&^0^6@`@ZAi&E;ec##+^R{_(5zS7D&VVQ&+fOAP@h~KWj#OOW}K(X zjOw6JoyS7zm_S6x8Zy*y_QJw(kU9nN7Qx1wEl*YJvD1rxu#jpl2mMFJ77>81+_=Rf zq*I6%uesG~(p44RSlxTWsPv!vlDv(VX=)i z4@(uDEebZOaSH3Cok08}+ni~;a#zUQ1>~rfAJx|>;8(MmxaxB_LjB)q$~Ky-8qY)k z5(>nm3I})%^B%68_P-<{s2gP4*FHbH{;&c(6FG-oZA-DL#C37ty63D*N{Q}#`1x?S z`mLePN~g2*P1*+dva5uCOW*^9?9jA_I{@v>E`TgP=sATS ztktDu@!c0C9q^*Jz>;o~BVdO3kD!*+_tWO6B_zcsOyOEwWTZOuapfr)nF6U{Qf>JX zo7+f^DV)zf%W$0&-(4y4rj--;`_;CfDM6Q~SF#VLl`VIFWt5Zpvu=0fQjr)O?Pd0< z*9O=mA@8jAt3IWrl-_yPcPyeIg)_G7sfnxECW#?d=Sp|}ekM)5BXV}Hfda543ZKnBw|h5J zUHf|9tGIZFJ{k^Mm+b7P=<*SFVuxUB``7b1=ZDc{WsQ?!Gn|}1GNrB;;VJn)IcfyqM-=~U=CZ?vp zba?VjJDE`u7P;Z@8qYqu4*q5{dV080=)xVT{^=^?S&9m(Zi#z5;4~_&+39eKs3zvK z(G}g($sj+JFKO;Dg?A0qpY8 zMF73KaB1?Vi%=< zOY_XAZa{u}kU2tO^fAuV&$P@?YX&ag1{e(&J~5TwB)8|@NPONUqbNcSi2XjEm-*oq zz{e-7^+@*>TDd%k>yq<9%C<*L*!S+$$-q~t+;Xw*%Kj3!NG;*Sc)a(_wxRaxBtr2u z>F|d?3_D2BKApVAd{3sbNqj0JN3V67wVHUiXjKv=(Z`MiA$u8cgeVhQZe9O}n?l*> z;7%XWuB04rQA=H67Fd>V{pQ{RGD;G#k;dsCYtE+L5@9UhsN+T}^4R@KCc-8Ywh*4y z=t?VSi87Ua?k=@zidnT3C{YQXVE=BuzM<>a1J}Z<_$d+!tUgS%*vXUzCo;qVd?Nu2 z6#SwNqTdG<4|W}Cn$4wKlB+nqh#^}TtGEy-@(I!qsn<5&)Jt^(CGIs`?+zL85?+YT zUv}IS|B_`X6dJCBFPXHMg`aS8$6C(d^kR4N4S#taPW=GF#hzK-F>P@#=&Ma#EVFh% zf?_0>+Q=LEUo)YJH8>yCcOYQ~E!;O@47Ga@Dp}4(2@aNx{ ze!p&l*vt3$Us#2a90c3y??oQBbFEVOi5dzU70}#lWnsH*9WBY0_+v!4a*i`Pue>|- z1iF|pG0$6v_!uMJ(Q0*?%o}+63;RuA&e%Y3evrMgl%97<8qp@!?MqA{NKIvW|ScS$pqO)yk-s(0(3M)f>B80OcSVhz;X z9HoYQfhNr6IVSYk+@C)8(`WsbfGMeTUTkfI4_G?$wPa#r`DZ@2$)fDEsy8mG8&A$C z>if(;dh~q11PrpN%x3@XT>38CwVG**oK9m6bWU|WiE!l3*^K0-YCP5{^N9rG^%D+VYcWjcEy}Fj|$?e-} zT~gty`KpSqMo7~8*5P?N`*p5eP2Gq=Pb8!d$#A0<3Q)ZmE(64qp(HGuo{Mj zgjmvqC+CczMbVtfR4}<~-m`5h-y8QCEkGr$Jd5&YtmyIO`Pir)3WpfKU)YP`oDSa> zOL!x(XH5pJSwCkLIWk@ozEv%VaeSTxX@M3I3+ffo{TIde$MK^R3uWBGUghzH9UA)n zy1XtQz8l__iRj&UA~x~PKi6DVvt~~YGS~1xWqmfMaQq|BLhdR_;EBXoB|0$4(4|qN zvbs2y0HP@-=Nd#EGr~Tp12`25&C#lc9|B4VxUTZV%6T!PbXJpiWus6m7;!ncvm20c z=54dEy*Ysl`d-4&rOc?V>~`mA>6na!_%YC&RnYwjNuL6FWz5A0&dxqf7t#0Q51%Ba z!MRV5*fjM{jZ~I&UDvmGR1{{2L>sIV6BtMXNjY_OfKG3z1UKx=WDBAj%mIaex&s@M zOb5N?835(y4`ZN0<*i$l2AY2PpFuubw$t&x7m61y(*Q;K%cqZ(PqxNtF; z2JY)eSlrXbjcDqWg4u4$BJQC5owL^X*JCz579R6idwUY+03x@0PIl~cg_{g?*k|{_ zoGv@0!J5B(ZaX?%wou}2xOV2tbrVE4I%m+&%opDjtZxt8RebkQT#K3*R)VTWb)wcL z-BZ7=E$qsv^0#IVJv#C1Qu4gWKcQdV`P+H1*n#$*$|uFp6dJFIiYF|EWruU%i~ zKaD*ycR>Sn@|`air$KIgf@S)uL%CG$nq#+-1tl6U{6a2d(32S6mXeb1xKhk&dhz18 zg$yx_ZT|f4lCM+ydu7200~=505Q(z62l!udO^?pnVJDYB=hcvombJgywHbH`iP`g8 zHK9W3VI;tGk{RF?bZZo!YlXP2@8s!P-q7_ivFtVJ@?43DlAwqRrX0Z^XTT!gX9$^! zw~x}MQ|?n~vEIw)V$c-$0;dQr+fKxqm$>m-M7~rLZ$C&c_4Bf-BGU*nc5ro% z?=S#pDtlnrfUKH!EBT~N>KV|CpKt@GzjcjoZ39dt#e53W3OqFM3tC9L})EN7KPj;AiI zwr{<$JFp}eU-=#+#CXgophM51Gy({6dgHzeX%QR}GwN#zPa6cHOg&8Mr)K%&*9si$ zSo;+@75oLK%@A`aWjO>cSgFj+<1qha*__F&d#3){jKBBpS{PeXGl7WziTIsWrvg49 z&izTS`uipLQeQzJI0*+L-mze@uPKOJ$SZ17$zdEI(Z~-{J;0N<)sqTr#*XG6R!R_I zHfI_VC&gV_yz6?IVbwPGS_)x>BzbfMF`T|d6JAken+E-8aY_4#1Vgs|c6IsoBh zq&e(&h`?uwjqplLS=~Ba4cB>#=0bxJ8ZSkaA1j$zhr%Hu`W%*w7NO3W0o6t6{KstV zaza_+>SY>b;GYZiD&|enV-J=}#29DMR2_g&a2M(YHUNxn&6&?&{0>20q4Q!3g{Wc( z>iXb{!@Ue6%)z|om9BFTkuTp0s{2E#u`sn*0-(){L>g#pq_)fQlzhklW&BB~6jFWi z%SJbDqhS>U1nfIg?{`r7X6u8MP29~wu=k!bKl`B7*_CYHJ}D3+dq!ElF^9E$@WQMW zGw4)03v-CsGx=!#&bhG@v==|Q82#jkU5-W!bLB*m)Tb8i+`6=l*kUG` zu&?toZ^ej3T7&-KIM)Z3+H>rl**SpbdOBpWX@3J8F@<7oz#6j%o0M!HE#iYBCoKr| zII&@7KetG7_Ppw^$@*pm<_l1EafM#^cJ*zmHmY(bw+sdDlzW@_^(>4Pr|VM?Fw z3^=JL!l)Z&O$;n2T~v_@gPVrpwIl-*5QT@^N<)WT@rYj^&_R>Dy7!zuCFS^+WLmN1 zNjtE;GjQHb5zHoxx!n0pGtpBUvTA*Zo>vU@iC<2&!b0^d*?0!$#|gTD1{r3?!51cO z##T;($R~-Binu%sG`@108N?A#hI;VUp)6SblljSBgOb<{UK~WnF(s;^IQONUGs72A zL&5t1(?UxrfiCPu~_;Cy4r2ml_EnZ@`-s@s9Y*}S*S5ihyH&VU@ zIl1w)L8?wmZ(eJ%cgodtPCws=#;N7)fte?u3B$V-h8n>cofq?$2FjTE@P-h@#o*6x zKPl1pmfW<9(fbL?hL6aL0fJ9bE!k%F9m}wXy26l19gK3^w_JKxe7Ban*ml@@*zldF z8rm_Nj@Nuh_Gi42P~f3MidHIglvcxO*W|(cKr&E(_sR#;n7y;~wj_OJu~4;;inw2N zcxVk9fCp1fcT}oWHFmNWLWh%;2pCbpLaXK(Y}O~MC>07N9J+L7v93mMTt)!d0$hh@9~i`QTi`k-1qRp6*tpE*|O`zVX+_ofoBa4Fdjc^dEuU*4Cm}1g%Gk&RgsG57K>QE@-78o4RwjpfWma`)!Oio<#o$K4y@%S3fkh8(+WErEG0&!bu0&1##=vFv zn8;bP(O;|J|{<~-L&Zp{KU z|IR>c;-Yspff?LQn^^MvWm(a;GS1Zg9HP)$l~Mh^7@2#z@=#jgor4}_ZJNKA&VXg@ ztQl+?dGfqz*6Ct?$A6mCVv5Bv_cv!fXoa&8Z>(OFgWbykKl*g>9D(E z4TP1CP%AK;vByi3wnyc)-9yS~9dfNp|4Lae7-Ct`e1BWu&BaRDbIuy0Li?yMBWDNY z4(Thg_5A!KkCSzvboTZbpHZeQ6W?d7t@)lhlW84UVC5j@Iyi8Ntv+W-F)sSXv_+1# zXYkix#74p0giSHSqh-LMyIF>ZFtl>|TiTe4+x^=>&CZdh>DIy}dQ$@}Ee;N_4VBQ4 zt$lY%-rzJ&1L^5X1R(~i2~*lLT7o3Reeac!=1Nh+3;*6oz?F-R7deNX6*pw?VVVXT zMW<1__9d^OCwrsE!@w5t1}ux%rwSWmI&|pv$gkCmXaoO7n`j58!p44#&Ag_H4ugNX zOw$jHl2wAagvOQ8P@*#B3o~dY&nF8CDc7=kV>?TpR$@bA!PM}zc|J?R98zHiZ&mDD z#z2_vgImPn6V@?rVMgm@evKO%=s$ZSApNH-V=XcRzl&;!72cj zk?`**8~jGlAkVC@*D9;&JnG=}uh-%>Dh5-wfF=N-?`5nzgZl&aMP{}8LL4h8h%*y< zk!|zeDpr)}C?zSiL3)~r$ucgY*xkMwj=6oiC z4Hu~J2lqAAS&Ptl_xRQK1v*e}wAYWAGFbu6Ql1Mj_L+#!w}nIP_pCG`iKUZ-NnT2d z1>Tq(gE}nLm()C)WKEANnl^s!J?DD-H;=PECsMb;8s4!f6n<9yBUQEu)^lNWkS)$y zLnBw3LcNj!lQjNt*NUg@@3YhZ`Hm79>zadXzHELqu`ns^dX%jg*Na$TvG=XM+vMVf z!atD84%xpJ1Y57!YkBv9v+RP87Ts1dp5_Z{GL6BWL`6n;M0^dP)IA9FJC$gDw?%Fl zeL}0Xr_T2A>3~_P0ZdHHd>gAoYr@+MGPcM*M03!)JBCGxM3|IRA39ak>eMTqt=RHq zVCDUco(X1Z)aC%7vX$E~T!@>EdjWB7p)Aex$X)Q#Zq+h-qHGq&Y0_br5m{>9$N=u- zBtxkTI!HN65kiM8kunuR@qOM`D9QiY8h!R)*wNA~AsN^m+`79h4yoI3IJ@zt^a~nM zSB0kfLXls=F(|+U<|ky3v?y>F_w1|mMvy%UI_X#gP>kz%Dcex0VV$l&_2qtKar!)= zHP9Z^=vfH(|@~OSH7vyHnriUWdR-0PBpxt0>=G%3E8-G(SeffYlHE)d26s# z`dDgY?2Ms&f6U_t$_o@=5^zZA< zWF+XO*Pop2YSLY&6<7jWj(Sd_>}nxps-)|;Wgr_(#@whyJSTpVCVFjO`TC`CtfjBp zQrWYT5586U0;{GX{X7;j7r3-q&WE$G$*GL1W=}PYL1p{VP=;vC4`h{1kVB=Ly3%v$ zj-JV8)O*e4y~SbM<=t!!H`50@Ng5BcR&zuhr!RZN z3rA!ev&|zd^mcG6d0btzr^!vee#e94)aArfE12HUxPG$^uQarVyW>Utv*>?hZsd3! zKX7ejBALGQfN@xu2>8?TIg3qcn~Pb1B5WPxQ1_%be2=8nbKwLNJyl<{UPAwB-c7b? zVjWpll5Dt}J=b;h&W>`PC?Y}(r`rB%_9?zFaN5GDpRKldN_W`SmU{;jQ{I30WI`9f zSn;;6NO+nvzObz+n%dtVHD>2~Jd@B9eCB z^4z{#oj0uqgRn|h(XDCogaTBDrK#r-zd*fMD{yqoI>Q!L`=Y=bI%&X>RhnV3^CF@B zB*m#6iggRflDYUwIu_zqnvDf#OnLe3q2GQSeCEcwkS(wPG%i3rNI2PZcgz#gVXVZS zbALL_gTK8Ovw4SOqxZLq#g7jS)EhV7EQe3aL4DtY^;Yy*KvRkWH%rsAx&5_WElMC@ zC2eTDaK3+PAGEQsp@u>(ANV9ShdG5RTEpiz*tfzAuG$KPx(Sqg%2=~h(O-u{3SIJK zP|8v`nnGxJ^`v8$$4Z4B2X%3dg}7vw%LfC0dZXW+KTNOpfO4f``rbNK;S?}ejOOR# z9l=U>Xh{v8(XZ1moqF+pRrLE@y)7DhV4Ud|rTmIHGH3ymM#z~G$9yf-L8)Z`!>%)^Qt`@-uQC;yAeLmo z5_jmfq~h`ASF*b^k|D#d(e~w4Dxw5>DzSsC@;zhr0IMM^q_EDJ{fvK0*Kbp&TuA{^ ze0QYLMb_6ICiHJNR+PFH?|Bq!+tjw05EvJ-A^69qW!i-02xCCAW1>(9yN@N)?mD_L zBb*jgHKA|1)@;{>jkPeAm?6x!P&N4qTfZ&qG8!E=#nuA!SkKIlEwxiN&=^xp1I#oW zI=NSgN9JWYEp?0_-ifn~HqISA;_ozS$+2S1Y7h8FrrfFMTT{lP{L1(DmCh$U#zuom zJ4&xc=*S8YHUhb|P(sVin32)^O8wI+Vc0g%7?8+*D&U(S*Ab7B4dT9&A#E^*Y zGnPYPkLLx>R}vf5;)H44J2E1>rS8SyO+$Gfre50lr%ol;yh|8qscfK2?&G>h8D7iA z6(?DtRA|~b7589>O%qMR*V^U0KlYY&R^d^5k>4iGN@PrgQfU1DraDztwGvvWhfT|S z!{Zp^Cm%b#qxC5c9}%+;Tzxq5Ya3zgn#0Mur(zi$RMN&9+(yQVeubqg721~GI5G_3 zRZn=KZjJr;+i0JBXwlI$)dJdEMUcGpIKw`M@j1&5zx>-(kIl1@_{Y=b4Us;5M&>`@ zTXiHmrM|VhM{DCGMMAMsY=66)bJ_xEJvO>hUIpUQ!A5)wpXn8$T;L}UZ#SUslm z04=XRWX>ymO7JnXn41Vc-hGL5PfEhohg+n#JdJJ$eE#EA;e<*fq4cLay%Mj)!tnfF z$O7RCT#AEK{_!oy&dY8cI&ni3luCR#t63)MoYvEVtMv_#l9&ZrCw8#U|Q!Azj9**`PTsJT!GB!8W1UNpp{A``OsUfhDz4Ca6c{s&Up zGDTJ@e+bGe23KOQ(G}G>gmsr{*Ime6P@^pGtP}jYIxn>J`x90dr|ZKk#z~o^p-^ z;gF@9qWGG#cXqO0mbwcuerp#d;elpy82o#~nRj&t4rSFI3%PtN4I9-0lqR}yr-B3c zskiZw77&1r)ZI_@U$WmfcrPGFWS4Lk1%Lu=OD%f3OZrf3!D%RMbDax4WbcXt^moRyq@eurIA~f6cE+UqAU#hG9%hUocg@X?AlI6PRpOg2^Uz zcLgYBjur~e7`Q9KCg+lM#JIFLGltT=NMg807U@$p;~`p#`#TuSv{t0uHaDg^G#U-b ziv`-;U3UMYDu+_FNQjS5KpCZ|Q)CCqD(1&SkTr+BY4;(sG1euc{y^@I5uBn_)L@$Z zW8NnbjB_o`?`)dpKDAsOv5g?&g_HYP*|tVCQ?z4gVFg{zfP9t-_Q+#h4e>E+e^}u{ zouJ;-AoHR5-;W${FTT2L3$h735Vn!MbP+1q-b#5SmR^C=3V3(lVl~x;b1c22oa%`^ z*aPJb8a6a-gIHA#fB#Tcg81o^W26B%#u%pTX=$=j9($}+c>6c(*WEmzUJD0vdde{` zzoh*NO^4rCp--C}MXI2ecd?A;nsCOzMTIk_5(Ui(W~u!%gSrg<$LFE0Ii^sTl$lYz z`O7Lpn}jPXG`)yvo7YYmTIOQglHQ>Mn2V>7#_Lh(jK$udWh`E~SEaAjtoXbpTj;B#~`vtxW`S9>sJgWqPTSf7cuoLuX zx0SbWhE}*&DA}6CC;$_iJCo46%F+gai}VHEwH62wH2-d@wv9+?San^?W=u=DW#_8w zUs|cK2mi^Nete{nNsShBlRKYo3IG|H0+qGJLY&gYc08;_pf~^MTWsV2 z{X(bfijR&*i>#d3f##(`ZchxH*Ewel63Y>TOieQ2Hl zR|-tA;Y&hb)BQ~=>5ETx&??R0(=1}M6D05EY8yw0=Y^Rt0_6rkRi{J=Wi+r_qpw~t z*rZzI1bMDuw>lHyuN@lji2i=xFpducu8<`YGHDU7 zn~y-Sbw&)9@4f08@Yn{m!KUVB44b&$Z>j3vPsv@cc9T!A^+lRtGaXiDP*bxmSxXHop-se``csr($9fB717>4b<>yDoLZBI@zI%{y4Hvt1}X z13b7*$<6P)R#a@Q29qJYW!zF9+h8KL^8+PyE)?3Yk!P$ZABZF0nM$SjdQvLUt2c01G8O* zE1PReZBn(0o(O9~fe?bo`n0G21*$dweASrCbZ^WY{H${{_l`1H#q#>Sm|3&72U=@A zDsD!O*rqA;aPn|X_#)=<##X+i_X6Bsg=ZdSCSv;DCUHbK==GR!`(doRUC6WpRELjm zvxL5Uo~G;QEVvOi#<}}^V?kM`UK*Y-O7rpbqY0M0v$4O;Ql)u46S~D!A1uKNLD^TG zUGYh3`OkkB0Ag39EfNb#|3jT7rn>h{LB0rikS65;EZJ}su|b8^0E>nTX6>@ zhtSnPxxhv#f88iL*2vp!PXdami2zq0#)ynPRLtvMc!8$LB0!Dz{OcPNEt|1M%gG}d zeo{&ruX=tJIj_k|{B)W6xgK-!JrJkje(qFL8Jip6*SG@MJ~OlK_$`EAT$~%0oS2{I ztnh1O1aoig=z{b?5;F^vxP>MpOk6ZPl1!DMPw}8uvP=V(-DKmf!f$q!v21ZZ?p; zVtL}6z3m5d(Q0|EOFRG$%rmch9c(}PiU-_Sl4|H8d$|G=G zNu{GO5eG|;(%+jklNrG&FDfXZ6T4zj+MRYtW4r6FWu!sff0o^GusuP^p>dkWy-je- z;OaZd%^#B)kBYHpM()r0ft}SOX>iyBkHu(HSH$2eog*p>)ybyU+cj@$c^O^`t*y)N z>sG#ly@yyS2bVt>iV?`Vh0K@(v{OeUOfH(cOLHeD^A> zIOpwK?H93LF^<8FxQ_`JG*U(%W&F1WAqIlsx!E}&mpK}o7WJujZL-~*RSVya$Hql) zz4eSPi`$5t{yI2~`CB-5Xpi{s= zacetpc$uK>5%}ompTF}R3H`_5N>oeDq8>;|_INYLCjRAW4zXhGH9!6PeN*I?z7qV+ z&fcgSh{W^u+OXQ@$EB_Akr2rz>=sPKUUq zZ9+}Jm2ZHVUw}*OBKq~{Y3ZAVCD>0w3ub)SLWZ@xIN3U+9}g#88<^Nu);RkDRU7QT zExsXE55>JUc!9VcucxWEW^F)0_`@2?#^M`nBiU3;gt_V0%zI!#RW{J0k7B!%pDlg; zi2AKW*M08nc&mx++1VaZH&0@?0tm9Wg8k*!WP}Yv>Fk|XIR9BfX}G}XAACQUhGO*j3e`5oM z%Kw=6IK8vqc%d~%%fSsP-fbU3>jUlR6+^g(^f_d^&da#nGjS}?IvGw}C$Nvky{j1D;N4*aMJpoW5Dh?tSx*MWxwf^!?5Z zU?moISksd|!O~BVFZ0vqtdxBc8bzv%lAXH49*t^3tkgFpC}3l{5^zq{Gu%%8os@1i$^e zr+D!Gj6r=o1wC|neWSeb$JwK6^$)|{6utx*Xb1zF*u`BPVU=$l4hzZ^V>&pNPp2FN zvG7jq7%BJ3Z{sQ!gow&PJCE_@o+JafX2?L5arI@~6drGgshc(6Gz_MFj1Q*!tJ$8S zyUXncO|MqIc)ub7wT#AqYq}_DsL@^P0pfe>(xyelAlKmvqUJNLS&Y`%Q#i|U=&RVE zqKw&&4!K>Nu3YLENNhkGwT5fMiD@S-C+&v8}gDtRnHryLGx#Kiz+&*p%#*9@p zh4AJ)$1EF0o8RBZ)IfXU<2OZZ%9tBqi{T}e?oCrq1hw~6kAX<#|Ua&l7|yE&l7 z-F5L%Dxvp4$#;rRRwoUzVISyon{xhzLNEK4oTg4mA#j0<|-Bavviw&3Xe0dI`tsdAKZxA>;s;C70NEm-wxfG zY%8Dp*6XOSI=ScDRPbIu#Ij2+zyt=BS=I$AQ#BHR$@uxwnu;S8)v2$4Ov?qDfm&y7 z#Z!-k#z?9q!PwyEqXN7rl6b7U)CX8kFo@x{(hwWfr3S9OSQ3SnMW zYcisG6g$c{5=4ZdAw+J0KtQy3!7~}^t7F~oa&mYhSSFJn{mz~>79734uk9RN*+1?I zI5Jrnt^n=6kaW2cOT6~JazE!ESso3@qqED-@9aQOtzN%c&lug-I>DWm0Q4JN5*Eyk zByx00*q2<24HmRiRS`01KFntB$hq5=)BI(c0Fo zI}25NV$=~_w*ZZklyTMCQEa03o@+8fvzGZ7lM`n9So`%iL&R9gCfOOz-LQ;{lriDG zW*&=L<8H4$z^rfjS@>e8w1ZB+cp(-2jE&?Os@2luq=Nt`@_%F@%VJ^LRRs^O)jlo0 z1p21iSDYfLUCL{5+<6S)`5~6AibRMABrW;O-H+L;?n$b+KZ1sNTSwH|%H-$4GejS7 zFB0N32U_OhJQOYR&Y;LVW4?8TWeK>n;C~p{_d%2?i^p|~xCMhAZBwE$qz7azvl>5g zEfAb1t7P5dL36N{L?D7E7ATF0qme~J@FUL-PqW?nEA9Lp(ZRa$es3LPg*is66~xeU zMHq%I{yuSWkP>%7llq#ji$i%$L6d=Y+fgj{r+J6%JiZiQZU}bXtv#zz!aw>uasVg% zcvL3yOv9EtuCAw|slMv0(qf)ay?^5ff)(aC-M~kPJy)u1j z8(M7`Ybk(aO zapN{%U+u&&bUjdP+YPNhC?BgXV^FaG$+&sHOj!)jb`^->76I-7GH5c-Oef|~D^K_| zuzI)473KXh7ZA%qApv4Dx3llg{jTE360ymBI#KNG{o;%+1COe(^^aPfQ(ed){wpW}OuAo3KHivPIG{wkYoNNw#XT zCq!9_1PoN|v&v-)KS#SQ3Y3Y*SAPvRZPRNo%O-b3@FUQ*$Tve~VQZUWuqHnE_kU#X zC*|Oukmf=)_1VQI&*;`vi~J~ornEW75G%(Y7OL}XPVxPka2rp@G)N%=b|uQ$Lfhjk zUs6GfVPHUpy*R2KWxm;?6CKdK%>c+d0I+28O3U7Nj%tb1nd5l+DTD1uvU~exEh&K~ zc2}TACH5KMc!^G%caVn)X5f+8&f`&jA{=u`AJ=QL<=udH^ zrBwa|tpBn+uqYavU#0k+)675AC3#OEaD9$!e$Xm?U3b$MDY;=36tpk(9?0W>fSU*)=-OqD113swIn0+Fm5L}j8pQMCvK6b<2mgQe^2kw7& zni;E4aLX{Q#hsLR%U6CW^=EZ8V7bSMsYgn4ip)(EUusz6FLe+fL4_Rsfu?rmNq3>u zaDAQ#TP9rj#8Ni`@nejCvH_S>lA7)hg#R@;Z63P&>PfkwLiQW{iGzk32N1bjX0$?Nt*mwKz2M5S)!pWss^0t`^m)?Njt}a%q#eu_j&I z*B#yBL590@4_!40IQ@8D8^FQ%(95T>p8wGW~F-xTUmFnGEP z(NeztVRAXxyX%Eng4TM81e0)r;PF@9)LSNJ0UnOAa-TgfWji*ip zca-`ch=pB4m*u?V@|lk?RYqBqwK=yZeS|F+c>JuyOMHtZEB;=o#Y{2;Mo@>dnkgS| z(wp2}x~D^JsHW!hDt?(kUrV8n!SoPEb!p469*Lv#f;Si|Euq>E^N<@lKewA$8$Fe3 zW3S0p2RR~XCZ8r!DJR$70gLyixG_EDt&_5x-4?+A*^2R0IYp@|9z0bCP40-9pems< zE3Kn==a!_vZMVrd?5{ZI1eJKMESKnpIQWN$JND&_f#Sw9?MFLd#}e(p%IvepmSP&F zrI}yt^8#q;E3YB3$d zUr;ySZHTY&uBtB_4IX0z3S#dueDE>}1Bi#zPc@OI3P5>49z_ULpEzfB4rP$Yu5bPJ zyx>zCJ^Y#1ET$~V5ME6D;xK~{bFVVZh{?AKZcw60--yogWBQum!W8vztZG4W*7Pmy zHF`VR6pP>QpKbF+)mz-9{>7I3^#$8VINSfxbQM5tbxk|CrNwE`KnTGlSfN01hvF^; zf?I(WcXta;DK5p`T4>SWTA)CI;uNPOz=4WoxwGvQvr(swFXMo@_*AoT8Ohi~sOHo)^V{;n9uvzXj=y`|=q`#4N z#CzxsOKgMm#wQJqMZ9VciIg9L&uXkbwi>^M(q4A^{*=`~?Jj6MIlO9n_lN3N+ge6o zWP)x;r52XLE&-DQFT4E)Nm(T-Y~f*`Wi;ah&9n0KirqtO{LJzRRqUE3mWp{XtR)CrBn|}W4q=DZizUlJ+#x&D?^)*-F3oe!PX&? zjd!YWB4S$nvLD*;?j59DuISHuLOUOC%}2nnI@T}t6=muxU4|_kWCz3C_pekv#Lt#} zCp-DswT<5^4xh*y41s+SEa6t4e!LpSe3dpxQq8ZdJy^LJN0VS%kQoropby6o_`>#P zP-t-q6s%0=ZcMZv%Z7>cfVxk!IBI`W*Z8OMg-qy^X1khEBaY!h|w2c7@6(Cp{Us0i3|`@-s!S}!z_JH8C-71rDG z+p2HHJy0w!VqqCqR5c4(x^0DpR-KOGP4lQWiN#_Tn&IR6B%$yz85#OlId#f4i^b{g zT+e^sfxHM{Q%1s_JRb|p4W|E4CUQ@xCqvJhfy`PomXPvr#P+8PNZZvyGXZmvpJ7cu z^ScTzFJZmSC}rEUC}#kfma@DRG3&XenBIt$;j-bF;gy^!GZvK?I@wgE&C_4yi`LuW zf-%+$g#WF%;qJDfLwu}0yk78&`xwz=E0?PC$depnv7eXqige@SX?jW2V_$T8C32jX zRDQ1uXjmQ@EKPK!Jn=hV{`hCmemjZr)F6AONLt+gHU7d>ExSkL@!OlZT%zUKeO|sP z36UCOB#ltqYtWpO)`-Fg{S zq|)@D(Z7!UvhQ*Xl|pR|zaYxfKLdkQNu$<3vaOKl`{Do>ct%Bl=jO4%W^I*NUo$2_ z#(X~k7o`2nz(xP&^Xt|m)I1aa+Qawv8Xo`L7t7kiP@``tK7C_8EGuLreaC<3t)=YO zT=)#g`{YBw-LqD)@A3%k^Q09T?xflDa}3U2K}?e;>~?RI6SNE!lh&d*zLrv1>(zae zbd9GeO6XhcxVVk^?4DXeBIc3v&S z@ma9{zJiIWK8JFrTLlvj$DnhW>bc_6dB-WCTvyhrh17@%F>S}z*5}%RU8FCbm<@)K zlx){yDqOTuWI7&-C2%C zylpm06MyTnEmZE6Y+}3n1xMxfXhmk+Ig1(?%U-YVueV~F*&Wv&zxBKfL;^?r4H=K8 zf05SCi5#X=yA0$cING2l{dMy;Lo0OwP33^jO&LBt&8`!(GJL98BcozUWi4mO6hAN0nTgX?sPt|esYcvsf;u^) zr_Gf(y^9s%!7%$hUv{z_cs z94WRw0$N#ak-^h7_42~{wIc=wCf>EJo$gyTP#<=uLVZn8@`1#)aqq0om&E>nJh4?no@d%eW69%A*!thJ7; zzKA1B^OM|f6G(+JxTAn#7{0#m85qweG41JmyQcB^p&;Xhg#L{*n-RpHg2#o?fhpsA z$o%PQVf~YcGV@WRuzi)YagU5fJ$*lEh*ao!AV%AKPR2Iz3H>+bM@oS@} zvG9KbVqU14w+`IIC=>tT;Tx_vXrh3#*&4)YJIuG+Dob%rvMZvC$~hd&yVa#N8&&I; zoU3CENYuux#j$IiFP=3Cv`mj;Yr$F%$>&uWdCs?t;#S|Mh<`li68P??1zA=|T%L0> z!EvZpO;vBmsWJ(d$8CR}sx!S3OtJXaOl0*!SqECz_`}b^;^0DB{`gCiSQ!2r^KWRT z)$vYQcAnKkxIJW5o%-zC&hPJ}X{2640nn37#Y*~$2HtEaQl+uS%EYOz-udQ;@|&H0 zf6oFHX-(#QEc7h>l9>Ev*(kJ+_*d`qmENsL&|)JfLa` zmz}HhoJqHg5+g4~1LqJInPFIWg>nkIVZqt56X~&HifoflW@Yuu^qcc<=i2}3J}Y&F z{AG4Ut^8L(OrP~fC-RTJQx>aQmUH0#gs?-GZ;Q^+D^p%0$i-r7<+iY;J@gA?ILED2 zK+LIWxSpHZTexvu*Zg>5q|KM4;FYbbwGP2q5mwp&Z-jx=segVYb_H7|VwAyyl%%}qIDu2Hk z!(0;DLsTHW*p1V;i@&SRv~z2hwgmJFHwU_QLG(BrC+DD1s;Zm~K8$%uSkVDStv}qm zb6f#C;WtUxBWvW2=q0Q^Ty$NY<6v%U>(Z z@3Gux5G&TAt==ReLWHK1qB-=epnZKxPPhB&!UZ(ESci~Fu z>T}>uATSX6{A}@4uz3B`;HT9?4C7za+J#MYzX)#)ANr~V>ELuRHC+ZaqJ6axcA$WudkGF=L;f#~_%w_g$O+XS_gptdz(~M(k;8MU4IGi4`oh*T{a!p{9 zFF(Yqdmdz4hMbJlw!Jr_qp0uVHLFPTYfzO4XP)~gH0{FBS@wF=mb7M=l_s8$riEl8 z!$U~z`?@6qa-mOuB&p0?YW4*N7t#8WJi>miQ6$pw)$B^LU7l0j&zdEYOrrvD%}@`+UEvI5n=Uy=gAv#?7EcTQ$zoNlFxijiwGH;Lj1Av{dDe zKBwTKo@4X6BKDhBwH{@u&Me!*rHZ0+A_FF-tK-#GMKTK0JWmY-D$m-N-AFw92v>XC zYi)H{uSJ?Je@DF#ysygX;>GFiD&A;}Yi(~G)z-+Z+-f%PW4NnPeAqW)O}6f9uA{vo#fIERfO2_x*xbzbs2}rD11KdX7(a6nZttq+sXye+-%s~^voY$l^4n<+ z70<6qhSjUJ<8}ILUOC5_ZqB1ahs?dUyECs})6Gu3d~Y>jj6QRi9cX91*zFjbn## zVOD=FP3XU@$t*W|F=*_^D^&eEtXM~$MWW83 z@#e@IRVd>aM)=Nj6&nhJa+U{+_KBcC7rI{WS(I^k`DY_8q^sxcXLwxbcP8{ZeV^d0 z8?X^>9X(=UbznGE!o9{tj>h}^##7U=G|Z^96Siws@@9SY*sIux;VnnzmW;4B#~5|9 zgiu91wS$LI;TW1RnWJl_hwA=-+4#c1Q*D_Aw`%hC#}7(mUy<%ezIBwp%NkaLyYUSi zW##Z%Su$^qknpE(xd9dO!O5bj(Z-~JNk(>ULCU$~xBF9R3A2g!QNo38Tt-H@)a!Fb zU$_~0I=B22$93kD|DhG3q5F5P5o1oIfzK+N9%wwZ0CD(&p$N zP<&T5Hj2MB-7e_ka#vZT5=VL{V8>B!_h7IAHK{6bHfh+ojTGvxIC^n%8p*er1F+^D zhpoSIIrAaz@Y>fIq`iIvNV2VxKwhs`8|H*~lZVyNEu;^Uc&^v0q!=HRoH#i~;^|%? zX?dYW+@IQyjl;H8p&OdCscoaEOs8i2H+H{SKE&2RcpIzUfHsBcTltS|T1jXkgF(nN zgOr0TCt$s8bKRefq<&GQo4U;MIL=I=Z$B$U9N3^*t`{wS=j5hB34Xe+HFKl>piUw+WE0aj8LlAFVZj zUAv_eG_Uwymrg$pRZP#!I}se?rU|Yd0+XdH2{(aasS7eVRyn5i?QG|(g*A?=D(9oF z9oI(yx_5jfx_{F{+K)SV!G!^oO*>0u0}`D8sh{&{fHhwpt*H_3O_4A?-1(vL7_9PFAj1B(J)-nnr*zWq??#R!^aa)t8%g{`1 zA}=OsQ@k^NA$>3QUldtspyYLqKh;6wF0TlD+m$#!N`>(v2QPi*3AwO|AlBt-tal6j zI++~`WQ1j9F=e7#hL3>Ursd4)o=(r%Flnp1{9i0choV-Xm~|}<0WZ&|Hk988S3{S! zIcb?eGWVBH-GLuX7L1oiY_%uZByxw_7(F`DPV!;Y?t5bZAs4A`nR8vtsW*q0CS|3jC<_li;f6 zSt_%&#u6eEW?J^j$GjIw%g(IGB_F7-yyN{Fw3%rh8OX&d`s7FZYl{TT=XdWDD8mLF z$_)J8NPnNV?u1x+9P}P+-`<#-%lqX0t9~7A=aMc$`S_*ttjHbFj4{U^4;<;nYY3zj6^*m(XOAFmKndhA8%^7H#a z4ns4@;-E3Ni7`2UGf_K)*Lm`fa>2`ItUl)bMhbsw{9kwvt0%BZ^CET6Z`#WdGVD@L zRyb&vm-mAtoL%it9J26MEt0i!%VAr<*l)_#^))V4*r2MeM^B>%k+$x;8dz1oQA10^ zV$(Co$TMW1BJz&Nj7xRjZCy^zVG<(*`gHN53~79rkw>I*d87U9j+yfiJaPRmwIs7h ztgV$cL*nzI(>8z(M$|~2s4~3`6;ASg=(J6Y5kI!b)GrR%@``O{PTBLCtD*S;ZH0SX zy!YrX(Fz2cvDMu~qFj{Ky5GmJT?AKZ+~@pxY-hQRc54;}V;u&U9h`T3whSGyJGpgQ zR7RUD4RRGidR)65^GplOSd)(1oP-XDPf+iF+0Ap;Y!3PurI^oG&(F^vGoE;up!PPdivFHbP8Ztc#9H`5!MZ?1(RTDu zM84YCiA?o2QSag37_EY0t0vZ`bQ3&!pRHM$a|?<4;+Qh`=tcZ9Q=|8+)%s!ygKiLM zW@+k9cHIi@L(&}E2+nf`MM}p%f~neRMpmU-mCY&YZ%vUeznxx*FgoA}RHYxZeUa6t zX=PlA^maiQX=}rct5;LDA*&yoNVrVWYr?Q|^LJndp#hr?J^^{bD|^XXy4COJ!j9maRsLaP77nGjTeRsB*g%e?wgk=)E-) z*xWAC+ZNd;iCFVfJjhHS24;_9YslTuX<#-4}u zBg-eFv5^_tUZ~N4Rg+qOC0-xu^SiN1aIn$(uKJI?{G0GjI6{MIIJ{7)y1y<1+Hv7` z*uxQ1&np?Csgg3D#?=Mm%&n$K4n60~3ESNEtVlq$R%tdP%(&y_mj|9}&txA}n`Aj$ zCeb>f56>*sRwt9}lr-SePsou2=)eM7q5E z8-H-k*O&Y(9f#{1u(I!zO{o2dpdX1!T#zj*`RWXwt;)su!pKvPo3nU6$~3OVGee}7 zZdMgOn4LTOO5Ue1vy5KeMfdi-{aQ(!;dUIy#bJiCW$?byfimBOSxuCg7@l-!1mnI8)g>q2zXJ)EzYkQ&n-e)(&p$^7MgbGrabd^`Ge+9F9y8sumfNT0 zfS1`}+CO)nRrS-kJm;Is?{Y@wd~NvYUq0l)&!&{Arhl}5ldwtl>}6=NSCmhoLDqJv zEWz(4W{!v?RpA}ID7{}zvMEc?tAFOMT+3Ia=8F%enxRo0CgTx7wP> zPGop6#;3<3H~ys&Ik4zuxUb-k2|g;zR0Gg0HO(LQIUFu`gQz!pTO&KH1owqHg86*~ zQ`AFRpcu}VP*Ri)Qt7a_*09FZpR1B9@$YUI9!nO0i3lP8t)6;Zrj%+`7dc~i*ORPo zKl6ga!^1$JyEPNE=3{cpDv9QQ91PC?z<6Tgo!eQK+BYKj)#f=Y%ok###FEa_>h+u@ zb70_|Gs0Mu1|49db{5OgVKGghiZzx~;lo>kIv~ioKD_;_k40eGa3RUZo1lAPqE!P| zP54N`maj5n;%g2|6=?nvB@yoo0=d)04zQFz(=`g!#otS(nxAr{KWi#Q{CI_N z<~!10A9qrDfFOPy>Kv`{ za~jkb-O&LiysQ_5)eLxutM-yTx4b6Lrb41SN`p%@g|01nRI<6$CNJGX(VQgOj! zkzt2kU9RhjhTySmCI_4JAO&WzTRG=Mh;M~~uUIS~1yHKcAmLhd8cW1Pxp0@aTVo}j z2q7{Tkw!WT68IzcR%qS@{E^JHGJ+!|z_VNFY2aizbQR|I%~ ziCJ8G6N~HAbj7o!8-^^RHJHjEpaX#4C_33wz5&ExBfN;eEH5ug@u4%7vP1`z82d6L zj-Br#&Q}sl>)=JgXi?rtAS-}iOvz*xGBl>9G|Zt_ygPns-S}qlH;&)M@M#<>|*o<{CpBitR zR;f*_-gxy(r+&9NoQHU`OmsQ;2}1-+UWtaptXN}Lc&3zfHactiXz)lu>wi> zp7|@fUh%@k9MzUv+*m^MkkPlNm#dJL`DA>=_AP0JmOIq2_%I(c)nsb_ zK)J8c#i;WyX3ETFBQYGZAWyAKeCh2sQuFl%FQuPEWpN;wH{#ONxjAXs*-Gnq#PdaE z$Ler>%`y;VxqPMtnYywCOOsA(qrD7uL~ndw5$iR%1@h2Qt8?ex9Az8UD&z|TutRNv z=F1Tr`~!%QOv4+s;st%f5NDmZ)zHb6_Dzt?ct62!4A~fRmf*gs!KLk^jLZkvDM}yVDK@6*g;|uJt5FNOT=2R&n=JAd{i1dlR!_K^`EW~kOrk*L$ge}du0GkBv8fBX{W>6=Yuva<-jBUSc&b!VjeUj^Cofxml zoYk1;wARIY@9!Z5i6SDD;Sv1&f{C>EM(czPv`ynuB2kdt9z4ntT?alp2Xa!6XGb{H zZK7;AbRR7iJ#4i*_AwL#cm<=GhI)SmSt%jydHzDAAOIq6&yvz5Wjm=?HKB z;iWqD@Cf5+F^eRhFM2zyDfrttN?wMVn3F5>wT?d7O;*&|4KN4j_gE4e`vO)UjoAQs z(^=Ua0TqXuCsc+8MrOu210$PB$h(mXhRxHD_+dfWga+^aw~Op(oG;c zm1-cna}4~uo;Fqz>xG|gRFy1r*3cL0-V){Acuh7ixs!oyg%19{-Z9=~{rEf4Hl)7n z-#}&NYg}eouB3tIpi((TlHli;gyof{RnP#7)L{Pi`~z)^b#20_jz4qrY`|E8GbJws zL~K7;`}`2C2RoSVs9cQ0!`OW`+xhGpqa4BRT53-Ok>a>ISmN%i3DP@9H#t~Jc0!ro z$`wAwrcBkocW-G7;v{=bMWdCpJY198H(s&Wr=>-G`1EQVe~**7>kS+8tRG1F5AA&^ zX$`x@0n;+-CP5K@&2$&C;Q~ZL%Y<4;pN5)cX`l9#3Rp=oI#=!?iYzbL0mG_W>J9yzpPnQ%obZ z4wIBIc=J7{1GfQkup@r18mDDz@73qVkwmyn2f|o@CA)~qHtt~bkCaN3=pOHcV7|G9 z5onwNM5N9o)pa?YjBv@eAa5TfD=T~=UcoeCm4LF2M>+jvaU%d3V+kw`a4mLP-!Ocg zILRxWMP=VK8VzqnDrag37Dqzkqz5|=x>GuT>yY#1Nbr^_qONinu&H?*t=FD0V}KT$ z5DD0k!@1~GHsNfbf%foNh>eJiDw*GQYKkJW(hVQN4xA$KHk=V>$E|kXAcQ$o4&7o? zmVhwkg8YH4$gIcs-p`9as94RL3C|I7Y?J&#<1kqYKf=9viJ-om^Jnq5Pl{yQPOb*_ zbS&>W^m2Rhsd@1iL{MebQ(kB?WL={rQmXz@N634DKIG_>IRuu*q#XOsc~+x2%5H?e z;lnpJ<~Zu^c8ZJznH=-yCS@3o)^TT4jf{NCZ!wbCkbcSHst)%6nUC^{JZH+#qR?!) zqxH!{q8_vZ%=lO&hr_e>aM84l%rQHZ?tj_-P`(x3*>=c)k=PHB2E=E=IQh zq^UG`%l?c=rbgUJbton29ON#N%0p+T_VsDPYGTKpJp!P*WS^iUN+&zr7&m&LlhU-1 zK~7@>k!mhWkRQ-`yY)pqb+_;`cT4(9P<~Djyf1YjN|ya#$*6`t=u4N0`pVT0LcavS zZk+}rH2StGi$z|k{*|60OEKYmN_J5!o;`4i+#J|(ml{r(78l=p`KhWHromzlB{UX= z=i=DBjT=6Vuz;y(2pf`gl_Z-*aX?f~9#D#8EU^*^l68{I%$k%oDS29$0?Gn>x^?L@ z=HqQSTfoKOUQIlo;v{M)QlnQcl8vYFfJe!!5xe>qFVoDjak1YnvC0RgkKYy>NcA!k zJBhkTm*63n>O_JUqm-78ZvA@L&Bk8De{Nf>XwKATg{)8kiJ+~oRhpxo@Kd%@{-%wA zVdm6LBJt<&{I;kC@+F!UY|RZG)XMX0%sU zthQlu;glbgtro2|5x3OI6cx9+Whzy<+Bj`JGYu zLT6eI!4^+8d>SQL@G4s501u0JpHzx$_!S1Wj*2P1V=1v<+e2g{MW$p!B`M0sGKsy^ zm*5&3vtn6wHPWVhKEEg_&npRowUCeZtqsgN4hP-LRB#*Cw^8SaZguwYI&Zp@fV{A{D-+e})XT=3_Vp!@f|~ra{RDCD4uUG~@LLW`~t4 zQ-=J;-w5jqv?Gos=tPKsamufNGFt#q+kxYo*r(`>vj_YX%vt3)TyH%kRb_|Le;DDS zk|~wM@)_Hh-BQh}T=}Vx*gYpwL8J#Rc?eiKiftfqs+1`w9suvIs;)Uqd;X^;&Mt}O zvW8Urv0|c#AGsNa{n7GnmcSW^ae4n*Q6Dk9~|Ib7jA>i4$UC9NvV;I zrPW+hw&QG$8RMts#}XS#NLfcNiDJ8FrfzfM!xV@4JwutIe9PZ2Hw!|ycHC{Eq`pPi z%k}K|vQUvTPem(aio%9xBPG(4p+-z~T)gX6nO9GFp0`-_Kcz$3noB6eG=Ke@@Mb`( zSn1>j@H>@9)uO#lq&NB*E#5kZOd}-;h_IiKdK;+|s?T!_31R6!L`rQfYLmzzJG8*M z`uYP33cmsRp2n>%DmNKLNe&5TFA&4<%dhj>kw6(fw=tHgV(Vj@RAvETfSV;FP7-!` zDotO536pLGet@6Yaa^NNLS+H#$onD7pXwPNpgd#iK1=f5h?6YY*CWpINpZuM{5Zo4 zGW`%V@9u(a=4(@n9tt=o+1NhaR{vAwyz)Spvsx{(rj~)S$Y^`H4MrJj{Ztb0?iXTz zp0wm}=*!!DlQ}1{SKH`dIj4UjbCNPNSQeo3$8IuIgmrcgd(XUx48K^H5uIa`i>8+hX3Oz#l=c^)Z5hc(IMch)gT%;i?)I`gRsx<*sPl>nu7iDK$7;;ha2gMCYRRMsWrs50)9Z@qZfs8EN9Gh+`W?eBuG1sJYW&@nMEul4jj8!yEW9U6;KScu zqC@M}?uEG;m(*m#?o4s)Wp;RBqQCjs`jnX@BlRK_XWV$Tr)>64C#4Bs3N|Q@p*hDr zMk7`5)XSRz)Nk5Cy8x^?IMid&;d3#(ZX$^_pbD83rk|c=u1hD?1h-W)!j8;&Pn1Ve z>X3BSwZEkHMsPk%(FRRm#kV8BHepoDpts)VukjQq3Cof4+Z~gsv653}PP808_$$$5 zmeT$)bih}J45G5{HV_R=WFD=9a>X@`e&YDy;Eq9%QQ8XCR=F=pS6S@Mg=48Fhg7E9 z;N`3q3nce&%rb#$W55_aRW$q(a#gStbdDMjK{L=a!tA$Q;LcGqOP=R>fa57Tq!Z=c zG<$i%cD`bXa%Lz_Jj?sY^%a~k+2yZ>$h-QDClYGw@agx4+D&%aNMamEZPsbX5R$SF z#V~AwexS$6&(5*%rhFB?xLB|RBW;q)Qj z7q)i>Cv{)aZG21N#P!MM}kaFrLERF5O2F zfl^~576)0+UyF?f4jA(F$SNF>K&)#YVgzD}cNJfD{==Y9N~EbEvqC`*$HuOF3I1Ws zP~!0zjmgsWDqy}%2xURtSJmO91~LoW%1O=E#M14DxD5tM#m!1{E@WC;0x~*HO-0r@ zp!_d^M@o2ejN4;$ng-8~Rmx!GqvuIrTmdm2(cc&}tt|>b=>?;W%uyX$&Zi!fIhF5? z2nU*)zi>(?QF{m{Dd&?jI_pLW(oM19{pKezRtpo;4syzAl%6U|^Z_O%KmzvYwGLDTz8fq$bhj7{7f!^PZAAm|$O4 zQi29fCnFsZv7T3)iDk#oNln2o>S((eq|4cymSNk{QS|=1P&R+gG|lV?7Q)V)53y~T z3rxqF#1#pXHD}iYuv2EeaZ1T?=5*8D#C`d9zGjGNSo@n_1&5-Q)nUZAg@c+?2pt#JC<-Ut7QY2y3g8zXj4zHoRg>fx zcz_I&JxI%^#y$e%4O7R4U*`vM)L026%627G#n|{RzY4};Mxj7x&ept$93m7ZO;Zot zL$(hJ87~p}{juZHj-tTwG&CiKoCuEVx!2L z7z(uT1J$ouWrKSr9NeGCI9czB$gaJ^Z1HkG&t)R0$Yyac1$*A=C=)Fr|cllWWsXHxl|X7eQ^Gmm_~F#B=; zjM;qBUH%Wt}5EMBNq&Uig|O)Fl|LW=m644B-9?_)ATtR6$=7$;sBpOXt?ZAxFB3 zMKU@MZFhY$BJvch8sg!0#}H1EvpV(h{-u7_Z7p3gE$uWmI>cQ0uPYdwJhb&6C#xj- z$0no7Po4s1%mty$k0B^oh)imy&0lZN%(2kxnl%TyPRgt1K zvom?KAzM8-PR8!$Pxcx>bRCWZ!!cxW?KmTvJpKu(6T`e~JJdVpn| z+)V&eEd<4t5z?2Et=%Lq=mH*)rO6iO=l;i!%80-K@(-RB8TYV50tRGYaUv?&4}1$g z*l+_9aSh^r^li~%QbupKqDfMzWBSi;YG9;9tQwwBmhiI3@i*>EF2s>EG$fnCm5IjEK+PTCO8fWxwMuggx{TlQ6@B% znNL6)i7Ta3)Yv;isc8X~wQ}=dkwb(D>K6CSZk&ZToj)!E@G&p|SdxH;%YwUI{2ZyEpX;2pe^v^7Ss8*z6|^1r+@__f^lP4L^Kt<~f^&G1J6&d~ig z=7%$}CUjoZwY$J-L1*lg&ne@iAvKa-ASX z7xdc7{cfCi#je8}(Q%D<1kf#u#Y(P3uWUU601}%3u?xwLv}=JC?4E}MyayRuJa?G& zc;LqUl;n;5-QR5b{?9qd9oXQn-lEI-cBv%98eXUc z9tHirM*j~&clT;4=<>gL*a#Jk7NGwZbO^rD;>$@o^2We(3n7?V1;3RHrtj}~x^a!J z^BNSm?mQVMCm|^4PVOxDI<<#BY8Lh4BVY`4mjbm zI3>Y-)z3tmAl1#n=18@P(uhb`GnF2H(ic!!=YjzBgbM5_D8=Vn02)8lC= zypsg_b$qer>vL>Os{8f3ibnv^kXLYE_-c%D$+;TR1s3;LVrleE=>E;ZIi0M)LItt~dVb1F#VJ}=l!@@Gd5{kmGm=wYS&>4RJ$J!_LIC~x?354 zx`9n1eceNUb2@xNDAv4M(BTf`tLj5pVXUZeAwX(9C-jT&lif)03BqvW80nWJB+t(A ze(rT(tfDvDIKvU~=kOJn{{Z+#0nZD)i+mXVd2d>guZFIuNeq3CO)!Dw!|A7_$Z-LK(j zLl_FOh2fpJ6T9(Y;leBt*aMgVm;gaU4-;Qs+T60UL)3?owum2qlAjURA>N3u0upEj z#NZ!34+kcn->kqGHUMF4B;eKXyHEkbG~qw-R9M#pC!`i9SRIY0FnEGr4`hJ84{BcU z7k<}&V)uY9NgEF1h-n~SVdQ(du^KxrlFbJqz6MUd+}ew^zl`uaA@NSbCh;czgbk2l zJbBr?=06_16a5Il?m6Kbe>m&27%*&*3ic8k^9G0|NWSYQc8~r{BE4oAMJ6`&piyvl zF1gYGQv;n~VgSPMv9Ttt-4NN+*Z63;ys@z9`>3xf!SD`gyc4x4H&QuLsn|no(vj$nei|#bN5KA- zg)J$iRSbSk7*2?MoW))EUCJqAACuDY9_{xI-@!O5QjC2*0n8ZUJbm=lq1h+ku3qe( zc+t=Wwm7jQyDn4Dm>I}zPjDv&UX77)m;m-xj4?=!uaAj-Y^6c!>&nn0Krv$IC*OT9 zri^7I75QrZF6`yv2zYo5gkomBW|V?iMu9AoxibY@REZ7Gi=sc%@A4(mz$5yC&rKfz zTRx|fZohaT9I|9MMx z@b!cGiB}Cn-o-J3KaqIHU{C#|AKSIUZ?x(OSpO4`5po^Fcrvhemkhp#@?9rwU~BEH zF_K6%NFQR;Z=K*nV)w5l*3sJxbQhsOa@!B&LnU4(@Lj*XOOovV&v{7R)V(~h0Q>Y` zC;KK?N-SpQpWR-Q(+IxlK<}C_F!+5hTEC9tTu6}|ja0hxt z&;aVk7=|x_jY)8PS8|O$aL#V}H?H_6pUg?4LGiy27_Bnm6OoXhQ;D^23}$EoA`E%Kz47{zqH{zpLEQ?x_@^joLNE6FFKcg6qViF@=3>1zHuV;Gkf z0rXuRk0~Q}LD>Hd@3drCP+}mHwwx_Xr61F7y$A zN?t(^4?cl#8KR|L61)9Fj-$MK8Yc=#p zjC|gt@U`Hht!u1@tDyULO#UE_33^l7Oov(#6U7zDum97>T{wLoKH9yk!r+OA#5E95 zprYGq;@#MM7++m)ay$OjMj(83BHSa?=8M@^R)W?XzlK95%8t)Q< zu9>@}uRTO_<6hn3#eDI61PoN`q?A_I0~33}-SnIIj3L*XAj=5#X>X8i(D|w44deY; z7zPI1f~=b-bF82^X8G7`x!8k5iQ1h{{a$wn1#fO zTJU<#-S#yp@!HVJuFJ_;%WG@>esPr)#$OF|pQVlASTMYL2fAL@s$+k@BlGj?p6r|` zGCTUc6Z9^L0g}kaQ$Y>8`<`xrPy_ag=378`Q5496ttVlM=%pIdcjMlb9UFw&HZhyv zFCj{XfB}NdrZ?o_DCjWh{1Ffi zvOLAbz#s{~`_M&qYrlIj(i~8^`!^i@Zr%z+6=~f%VgGU>4~jo6Zi%_Y#C3c zR!RC03fYqHq|x>Weup;9f)2<4DMUVemK?r@O{!LBs(b9POjRKt;HUoD?)8_#AECRB zYYD60oSe9+E5bW2Rl2Ll!cj;m84VH0FqNk?_&pLX-YN+VIB6ZK%u>;p< z(CMlI1~TM&kqPrNmS%c*Z)(1gj=5xXtkji)zK%oC*c5-j_=i+6J0lszB3nJGxS38Y zDp!UfN{TDf78voR&+DAGeXk)~<8+*B>6tNcv$~mAyl&%f+e3yk$L|Z9{TF8FdsH%C zb02cQO0pT*<1t*b)xWo)@*N0DV0;8LC!vAU9lYW+eTBG;_HpTs@@0hq?db5SzSd0S z#J_QN;BeJl6rj+IlYq(bC3is3c<5#ac9XsfN89x^o-b)L4e2#-MJzT-(ASzo7#HI6 zIRjU2_GblfEidMM>@;(udEHY=#8qY^&Am~pPM)u-ZW)D+>Wkk5d8n#CPO%DjX}iqA zSRpbObYS+1x=68pG9Szruv^NEsY(ouIeFQpTfVg_58yY3M2`Fr)NlB|Op|@C-^u^d z1`f5yoZc+KrT23_{^-XNg1qLS$m)Sji_!W) z)l-c1SerPyiYGk~N)|(sK;l!SOjd;~);#wG-Fq9}na$@4;45*JZ`CRT(j37e$ukjn zr}&V;f!A7VmeHpmIllh;8*lLEcBBvaabQUUd@&`!!0&goz0sE)LrUVBJN>p*m)ML~ zWL6BvU*AfsybAg?j`f-E{{Z7a9KWn%8}1L>kql_@q3#AO1VIOJ5DwuMDT@|pQ=>`; zL~|;?9{~m;R8gyA7^cLhYWhnm-fIOIo}kO<48Y}^sW9Gh%Z46e6&w;ox8l7U2)u#s zE`OQW!eX%?_5IhpEfkD{h*!Tq-hrvMpeM`7&01TATQTj{RjE{?S78?POBi5}W|nEK zHCix7=trpj;73C(UXEq!=NNp(RO6E=VZ%y~;t>xmSfgppajWid{AL0YV|O7Z)Dbo=Wbi>ZV=`X4q=3S^AC0)XcT_reZd4+ zAoPL=Ac6?7L>9@2P<;8sx9sYgzEh$yoPj(iE1Zs?{{V9%p_UKCWux&+m(Du% zGPfMcpQAwm`}}_SDj8;qxm1?iPFfTDhF>{nlNoQ58ENXqG3tAd-6NrwQg~>O!E^;A{6a6N ziv&^CgsgrcD*kCm{8E&MkdoU^EeZbaWz}?PUB+?uGx&k!=Ja>IxGgs!87bVmM(vu?~l0s@iE*xf&Iuoy2K~EKp`-hkGy{2 zn1T}tGl-UDsBixOK=q8IhEh9-fw_PT4)ZZLWMU9DwmJHsym06{`{3)zJk^JWSA@)#|`+0_o6x(VstXZfc2HXoUi$%OXm@KM?EE` zTzuu<%`X0FaPyaX%iHlwkK;1a_{?+0;}7@3Bd0?yPdRKo%?xR5zF+*(`FZ?O_55j5}dATeNq37L-J1TDxs!hRcu@$2UU4b?W`>E z3ae!&<4%*qb=~I!UP$ut?!m|1$K1rks?;fG%sLt1S%%~oA1_zRVOGKZ`oQrAm-k`! zjCJT^`o?ag{loi%{m_2s!`+_a+<$XrM=HciQ-+Bul%A$jZ$=OvpWRnYr+b^CjK@*Ze0H8bpY}8RjCYt}h7;U-vOeQ44f?@g{{VQ^ zkbgoVIK|1I{!7$PI?nZhgcIX|Tk8}+8BeUuYW~$buMQ{_Mm=XL#6q}Ni0hDGFhK+mcL+arDAElYH^%TY6ap<;WJ%Sb zW|nJpb!h74t#8nI#nNc&p#}n|ANB$J+;@Zfp$%s%E4g+&YM*J29|&-LVqA=m!-K<# zbt}1-Dg4XQ4f7&?(*|W0X_G@@S@ZrMtOYGcV^xC=jnV@`pGby{;QUL} zdWnTIC=av;?wAL8HIfHNSpl9R;e^@>WQao%+#rHy?wD~8ar=fCVKDcZp7Iz%jgIk; zydZ$T+%UpE=!5q-?glJaJCAUKyu;=`;e>Z65FY%)`;h>GED(Ls{mRrB4J}xF;yCLR z^k_YP;f5dFEj2Z+cu|;j+WT(L9TqWTYxEq?7oW&Rz*T`O=d9)XO4RGZf8N{He>6@! zqS;tm7bSWT1Gyp^wGWeya{>*F11Xw)VJ|}ppVP?0RfQa2%s6#`)tt|?>Vl4*W*se? zN0$Z*^?;$y@Cg%sjn~a#w@z?AI{yI8Ogl`?LVP{u7<-R!DqvM*^e~98@UiRA&8&IO zAU(uFL}fTI#xaC${$XR%Y)pxf$e1ui+n57D-675~HXJ}=5jR0FAtSqTW6gSfJFzi2 z?k}Ek2x2>w&n1Nyc3=YrZa5PI1`jUcPjN8A3?d)8VGzUj2XOBYe&|Jl5ezYevHA&a za1`ch0LiS&{{WGusEqhVSe!LxSVnv{$I=tV!yEYDyXbrB7y$^dnnxZae^YPpq@vZ8hh9$%G|8TTNL2*F~=a8 za&r-~w;*78?wWhUJr)HxKLZ%`QDttVG+J~|X&GlbL?X~jfUGmbQ(_PX7daqv%mwUB z^^0Dl3l7xI);@wY7u!kaX~snO8w2qf$>$?5Lk@e-+#>cKqqr{wO70A=<{_fepP_~r zSMLMd3qU4D3d>Dk&iOsqnCTib2=Sp1!qCQsGG`FNV=Q>&VsqWScLDKv z_YpkA%)x^Y4($HmMT#JqfJ}GfcNk^bgNl%`n!?3J4ovMU6L6~&v@?RDYmnfmn&R7b z39YZHiLJAu39PIV$|j>Y*k-8oNv(CrK`p!=8;N>3!;DMndG{Hl`CahB8){} z!vI`tiDpSzSX^zDj&Ul+Hp-q-44k&Lh&7{&t(XS~PmG0Es5*LJJpl&)D`0!On3XPLQxo;JGOYmBXb z3jY9g9l{78f(RhQAG;rLe)`(q3?_PrzK{lj-577gv8_YTA~MFrD%c>yU2kwb7o=@< zTW&oBdZ?qoab-i6@*)wXp=%|JwgL1q+Ag-M1{iS-dWPK{HCa!Qxs_j|(_dPVk>NkH zE-?iZT1yX#E&!hJn8e107{n3*AVb}<^gom&W*BO-B*nRWLEVU95a)q24}MpX52R>8 znLWTn&oa1%D2g+Qm`Uy(!g>fyIos(DdyHWW5Jie27zc3|j4twc#A+`fsQ`?K-ayN> zb_K0i$2U}$k_EZJl@7MF(gfv5|PXuc0PeX~uCZucMPKmng_G z^0~~_JCy)Uey5`<&1RdcD@{^zaW2{KH1qO>c$nf?NDI`#+1-^@T^x+JdG0;t7=O6?!|M-un1&wiJI8Q>2q1&^ zt954!Hk?GUN}oBk@JC2lTapCXVP9S#lpR4goT7}8=3u)}?6r!9rA2bdTr@;qi$eOjF*`S_Q8XUI4Q z5L!xev0w?heOep43PlmJ;Y2!B79s&UNM;7aKjjg@cGT@k1@*qX7vrzFnYlTV#LQLFOh%{ z!1ROGV>s@z#sLwG?LAHipoKHF4A(#LUSGfVx8-Js!kRj{4%1E>012W+1<@yEP~o;$ zJ3mu$H^G20J2h%NSNaK|(DF8kP1Bv zcOSeTy&rH&?jJ7%VhZhL^e`(yv=}zASVg6e!XmYTqQOfKg^#Qh-G<6KoHCzSy5(!M zc{V5|>OblwirX+r^qPuB<5>$as4VC)o~tR@V^rBvFv*z3ST12#tP`Jva|WV-yMi`& zC#1JWlWk>fQZNj4)V=@G+dfWmI*Yosf-m>dX)M?rm zbY&A)XU}wh{{U$*`hBR%HgkKHk9AHFkBeKBaTk-RLeoT-E0vl$N|mX2m7u^u5P3vc zl}COnnu{_E81B-?KQR%3A~#${ho)lzJSJsm8z;PX1?vNM`bKEN9QWhA&se>~A9$bK zJ^G35CD)H+X5IX!y4^bBDmc|_528OU2 zhbm%RK+ea{SZJhD4)Di2rFJu;CejQ*2tvRZ6&Z&d;u@BgW1Yeqw64C;YIMq(KWM0r z&2bp&oh=NkIKk>8E>Op+!a(>83J7jg#tcMg(2>M2mYR;uDD+(Q+0@|5^+-mhkhUNF z%J}_6H&NqhuCIDi{b*q=)M)rhwwPeO)M*C(l$b+%)~KzX!s;zI~WVJq$p=*0QHk z%Cd<>t^Pv=hnJNfn-fUy=nT`Z$l^1$D>{Woh+lL60B3h) zPMCops=s{lXY8^(;}sZwkXTAE&O}7Ghh8SbfjmVc%nl>H{{R_2n`NnMU4l@yGcsfF zD{L^!5Jv|PcIRMPs1#}_&4>q>^Ai;_w*f>o>Pyu4JG#v_vt6k*k~blG!1`wpXCtSq z@#-o$ama^u(m9p7l(dv(=y92;*et15^geYq@6>e=?#>V5<(mhO3guhJt>9vu)jM4Vam9)C2T6GyK?O-BmJ1X~0 zN;#yq-QaM`>L%7?CzUubAK9KVAmkAgMe;C#)*hRsih9eEK9c?AcOe*bJs3fyyghj| zS_7dY$n%NhU}=-Nk5R|c0lfosIUk%Mx|lr7EZ9!5gL#Y@8_U#sg(HYb2T(ow$_wiPAu9? z(kA2}Zmog(gEWIUQ4q1(Au4_P_Xh4K?`Q7j7<-T09mZp?asJ>t`)fp7Q>0UU3DFTb z{{UQ=_T?}52pv@pRik!}l=#Y`v_T}48o9o*qd45WiDAW*xMAt!VqJuP+1nq)Z9V@0I`Xaj z!|s`m^wDUoxsO4_H``_Ga$L?@b!b}fJcKQ1BRC$C?#J-0yQSFX^x7SLpV#Xs)+Xv7 zcc}9px&^;`_MXetQb_@;FzfpZO>b94@ZUbG_mB7d9u7h1VM`-8S@Gex1|XyoIzVhH zdKf8v#vMzPZ^|lV-yaM|c1_!Gatte`T|%A9yJ=zTHlDl2eBf;0V>24HMnjXF7~Pq# z^jz~Qve!C9*-fV)Mz2`j-cfF6av8ib7^?mu<|Qb!&ZWwSVg|9?A2*pa2wQ4%kBDx zv$C%mTkPk+v!h~byDwGY>nLhp%RLX!#TKQj(!~r%ze5f(BSRQ+Bje#YjpiZA`a#;1 zHiJ^zxc!`M8x;Pr{=M^oPXVo=W0p&IXDbAjQ8-x|+UlF=GD!ycKE} zc_0&w(WtqZa8RBYMnlhXv>!0f!gB~>RPh~16T#%H8rlMdA{VuC;~9i7R13)RpKP>? zI%5D&vmkndfUHr6qX}k0zfVI6v*F5#Vz42OV!8$x-O_JSV&rjy8H6CjAU@u((Qk-= zZWCBI;H7@**HDEu)8l&V!Jns@V>Z|4G3 z{40;Sh--14h6nj(CgJx4$8m@6WPaoskGOF(U8wDSC+xbD)z_naMD4%qjm5ZX8;=z- zRL`|Ar&NBAETR7ZYMZJ&?^#{-hDHnw8de+6z+m~*Ljs8YGe4xnl5IW`{ z_$|Oj;24SUS_n1p8fqx5-lM*w)qSBT67R_O8IQVV1kA(+U0HY2z5(ZEJmp%@66D!n zmT8?$j9o{{=ct0j487TecMkj|dK5gjSgA+~)02s{cEFs&uGZB+8Qk3cB`KsDVv5KY z8%W5Hq<6cqb+4r)?-aKwn4}zN|T7z=^M6!z-tC5pDFd`L0k!xiZ6I;^xN9a>LO;xBnGqvbVO5+>dbH}WsU7+!MF5es>Vo`oz2%4QU zZM6uDrWGijcm)1)92l~;F&OdldPks>uEVrv1jNzm%TjYqpAyQgE2h;Pqa0-UPXk_b&&b_?-l8CO zQgO7ADD!z!rfRb-Euos5kfSGGapXi>m6fuG$*~=*D}lr{p9cg#rXwq432=U8l?;MG zi}uU3+J-wdOO-y3AV+0m$c3CDa%HtB5Ac)7mm}b`dqXJXGXDUabR4OQ%aNG222Ofp zMI4B`7QxW)ViZ1P4E|6-pR55$$1BVcTs>UNy=V+BxRwmZK5X`Pfg1bo1S@4rGSr2hV%-k{z{jsRc(80IvXZJ_E&M;u^ z&u}2*WErH@T6H=XI!nJ*ovGMV2B);_)S~sNs^k4k(`xv9==EUZW^fM3T+j+A|?5z>bK*eo;nLOygG6O@hLQGGPWt(F4EX- zt%0cZ5j595YUI}EARi+P@s-8Y|;fHWNB4gO4w}nV7WJ)-k|Q zlRn$8w@~MWI1rLd$t29>jLVNfIelZVvcWZV)L%x*>_7ILaDIn8PRs38`yXh~Xt&P0 z#xQ-FYP%Cy+F)B%r5vJlaI;UYtHh$f-mB1$yh@qj-#DAT;QRTBrfU0YkAm7=cY*kZ zVqa2UQwB>EFeB~`;rpC-7$Ezjym!%{LA;l-zDn1YX=~n3Y3ppzgynS9Dc*jjc5%|9 zwfj7_zb!ON{iS_byb22Z#2MMI^6P4v0sjEybwba~!fkG&kYOkY=?hprBD#ePyMTxW z=J-!TD@#v?#fgW(a@>w)Ed(e5{XJ&OPTmZAuCd)o;xcg-jRhB>_?xJk ztq%Oer$(&YFgy<^n(H@ehHJ4(D-T?84!(_7WD(A*ATyE%L>-BHc5T|V)R2Q~0m`?U znN|CSs1&<6HUa*#m1q25jo9J*jv>`C(l^I<$x+Xrm+R766@!8{9lXS}wSOZw={yEy zZ675K2)#2GOwa?A;%&NXw z@rtrT^mORLU7^)8R-{+E;BKNmi(97GRG+hQEJ5T5Jgi%rP&zn57u`=Q4yjtU{x+2h z*So1wxhokoy1UlbrO`>KgMu7Q4{K5Oe%PTB^TE|Bf13!}Ax^CcvqxhQzv%_Gv$s|` zfuTT5#LbD$IfUgk0Hb4zJ-y?0ew$t6s47icU#bvtKTcz4FBB=wObv*Ant1gZkFUbs zhyDy|#?!-jh}k$E@rXHq@L)#xzata0{{ZxMKgLhMW7767olmsJ)oB2JH9Bw9taR16 z=vxi?$L2a}kTBe_^%}KHt@s^EtDkO1>CDtHu}6u(Q!v~N zqiI)Mzg2%QV7|KSt#>Vp@ond6_lT{L0=7p;FQl;fgxrdKyM!J`xP{z07#bmqH97{x zFNvws?%&L^@L9Z!&}%AE%)7BPd^)_+^xh_&9J;uQ^qs6YfG+hQ9P<^_G!0pXw>btB zxLO3?SZqKhNAJ(w%pwE9g?+?R(i=Z*SI#GAYLM*G)mEp~P;>PVs2XeODRn@72=XJ^ zCa$(t?4(7$F@|BibtKM>~ z4(KWfxwOD$3_oyQr|~KIko0K%o&(jm z)D9Z9Ic54EF%wm$4yFV5GY*?XDMRtR30V!vFk=8giG`1=)YnpuU4V(B(N{_g06UDX z#3^Dcsp=SHN>fMnttvV_M>s>kA4%J(NbNlX)2auT+w(WnM859>Rs}9w9-9xL2kx1% z_dxXy@P6PO+53Z2**dztYB>6iW`DCwCzKsP#QtbDz z+~oWBp5X-3=}Xs2we}~>7oz=4Yp#2>y4pYkic_Hanc1T`)z>TSZBtvS)(tj}vxTTW z8qae(H9$qxQ~=-rXJ*owI;1|y$(k^Ds@9q_)hrW6tMFBAhF*V#r>%abc9R?}2;RYG zY5qMOYwu$O{{T}pt=f&Npn-T841;#xq^ip;ePwptYYrH`Hn*u5=54QF32y!Y+3|i- z+L7&k#j{y+ji9|)L=&`ieLE*Xr4h+3cC8fpR*-3n2IR%L_P4|6U~2GS8A)l?VTlXt z?E`Qy6=v%(U+Wq0*p!c z_JO9`R@&?Z66J0&Hzt93xtrUZ6VK5BrW| z7B*l4IT<*N6o7NjthFo3p>Pfx1EjsYE3K*28pc_H9Edf4*~_1;x_c8o>T)A4Q1Uq7 z^&dkvRK8)dxII81gEcGI3973*>20orXQ@3zr?mSlJA#Zk0=4-aMhM5DTz+vH?InTt z*JAigew{NbylU=z3ugT~<*EfumTDPou7$i>rY>{4<8AbW|X(CVns_N$ko&BmbI zsuqc>yIHI3f)9q=(f*}o%R;)9A+SfGg+32M%r~~gT(Rj2HqtsCAX*$)1J@L3H9BFr z>+puqMt=}7J7=+2_`CIVF5tQR1E?RDF>7qM%6M#gdcx1*1G$2#zrP$bAxnCU7y|Mq zpp{eDHFl1n3tC;PsXcwnx{Y;qq8;erfQeoDt4HxK%LejO?F~)hDe1w2$45>P+tyFUqRMS3rx{$*nIxb}|asC8%A@}E4-ud&dm&LdN6Rby|c{ub!c*QAuM zC^3~ho_#$;YOC=R1gz9ptj^>JmLa0yo!lvj+FgJZ_<9LX(~{4sm)kRcy%63 zF`w31u%-wiKiXEdT!%YjY4tYJ%n0g->j-iTvdo&nAbUn!lRR`Rqv8>F_)pNlj>uv_ z2LwXRoc9zlk@r?eQ_}`&M;PQY{#~_(?UVK6aF(7KIDmXIaU9$Ob zmdgZqj&Rbemm%W%h#-L$WoF*se&CrfLEH>_##5hZUFQmRxauX!{?V$NMd||vU8Jys}0F1O9@R>YIIlJ5%=#!FfxKX z;EFnt0qAC$kK*2neKRy}aJqyuM^DeGNutvr@SnwEV!ot{5G_+j+8wV$-otq-m{xlS0OJwWvyVQ%~(By)?x>i$Aoiaj~cNhe`;xu03%t6tx~Nh>Y8g z(ZMrUttY{%*9tk~iQ0GDTiKwgf($CY6@NiB*Z%+z=;-zE(rHthuCmkZ#O%eaAknYX zlbPART4|xHmC@1htWJ$~Y9928Bb&)y|ZzF|;Dtw*1vFIGl9<26Mk zdO8N*EZV>sA4 zLYh%<`NQG{yLyS@X=_kG%S*d5@XAkI<__3;3ntr;ZD${hMX{~ZD`wQoRu4n%`OWra zVX>RTIW_V~@_^D+j?xa`&}topxl@7>&&!`&c^`O-%hpx-232bZTdOOKw>UpRnW@oe zDAnnxvrHKX1H{QC}+keF+9>^t9MC*9+<`xznYHzP|qeQ5Xxt{DGFl{EiR$%5-V1 zzV*tMz{uy5$bld2i(*ul6k%VM2N=x#sIkD?jFKmcY}|Sug!*yP4TrL|TA#AtStg76 zZ6}hZQ+|>ALiIXrVv*wP8B1Hqht@4A%oVxBHe>OV6y?Uz%mYtSxtaj)5 zSW9%L!~l?bm>)=%3=2~S>N-mMMbf*mRlPTQ!U3+p%GL1^OVxX4Yy1W$+Z$0*gGJ~# z9RbEM{!vDn>UMm1@lg4YK4Jdw*1#UURik*?-7P=JE>Z5Cf5@3uu=qrHRv{r<{idr& zbFK<7l-r=aHJt7WQ2H>2syr>Bz+w7It?d0Svr3q`84_uf)F)gH@%j=4`SO82x6N z{V3GbM&uZAH1#Kj2rTdxZ({{*h@|+d2CkjxIY`L(Ai_taKCy`4#uFf;O^^&kZ-j^y z@s11zqT|b~2Dmo}q!=4VNX{VfHo?fqp71O!IGph=tAOTT)U>>L%jMg^B$1h?vaz|j znq$$WEO>cY=;ASlxKBvH^vv}IV1dUC3F9%VygF7sqF89$>5(ht(>sJ$4o?MRRdHrT zG}>{I>k;=M%d^+_&VHW|Tsj&<1tn!8{-Ylv1lx}h4VJ;b$D%}`$1{-g2%3WCAgn7+A zzJsUMAWJdBH$xk;dr2=Gp*?1q&3&g!sN675kq~Vyn7X>$uT)};AsxYn3^g6g%KAjT zIN<*Pn3mONg{b_W*Sjr<67N9&0P8*AA|=(b5y6T70P8wXXw|zYv00KoS{C1`4~}Hw+!5wzW{X1R&nSck9Eq3GFXKXbRC^t0C{A30JJusHlE5=LhnXp34Vb8jCdKRcRpo0~or$?IWE|%k+AUAt*Y7h7(iR zi^lCvfqy$FAMUX&sV%94qkzi8p%Bc?=tONUqcB}qo|A(cNLx~hUcde19-qtysFk`a zqlQNrRtJJ6Io&k+O=+sj7sCmeq1SeE>FR7XgbCTYDpI9#tjxi*PXD|;d?o; zJ9X&>tq?;$v=?5MwwvQq)@pk{w6%m$`*sItRmnm~JWk)YH`I*ihXfy4{ioJ0LW*bh zg7?k3-Ltd+J}+s!OL=`=jWjhJvpY`Cx5?&{N-LvFNw-sR+PUby^FpYh_d5Z}njptv zDu<|@ousXiC|1v#38P+=Ru9lh(}h4FneH0OJO;6m3HY}8k4d9MO4m(LL>M0oL|v$% zN3ei*iI3eFVDWOoEv{LI(O|}N(lKFygEt+fY&KJ&yf=Sbxu%kDhYUg-CIS~X*8u7Lm@2&#YJE(BQ6IU z54W+1ai@H3ZU@xyEbR`;DNfp~cMY+RUvJFAuKvkt>2dMU2i0)G8}v)3xym?B7!32} zmDW3eX$>0O>uWN>IQC(p}XV z2;(9k*Bb(OR_KAU%A2SIkVmS*`i6BIOMFD)E#kVWIc#EfWmOurYg6iSshpn-4E`*2 zovEhPohG}4>WG6C$jwkUQ~}0g) zdUdI)9xDFQhd<^ff~!`YO%97<2c^9;<@p$zZqm_qjXxfkzlCY^&m70n_MO^GL0(FO zF`%N?QNQH3>N*(7Qz~^{NP^YPx#DRkuGF^1ac7jTSz~Dw^6j}7+Xpe~v38$vFKg`B zcL%FKobjt_tsF1}A43|8tfs~4KVM0|vuq8~95?$)@6vn#7ej;em8WDQBIeV!rzClS z6Ia>#-6|E&Fwo@g zJa?V*;+TbFlf)#DV^hX@!g{pyb1nyqC6z7@J=7nbX&z~{4p(>)SY=xX1@x@O}f z7#Tn(nQB**uXv4SYif*Yh_a+`zH*No*J&7NPO8L9vs-i-m(ziIWTR~*Vl!@X8A#(I zCYg@bC0bX0f!nL0;Kdv_T=OfeBkUoUp_+i``g;b}9Spj?Nz^jqFj||s8Eu+hvpQv1 zL#NjYi6XLaCPQj!e1p_V(d^Re2?d|vEe@Whx31Wly)xgYVe5kn-Qn8h2pv47)Hi^n zIvyAU!I{xA{7r&*Jw&Rled}4`+#SA#RioSEa2Vq;OcRL8d`gc#VhvWAk;y|ZrMw+T z%KjS!FZ)_s4nNLStPM+k&h+v=zR;Z@)hNkcP9?gUlT)SC6y4QWZW6>ezOM{2! z3!H5#2$Wku!?h3S$8w*~sFtH*#6F;oK^~xv4BCaGRjd1HK-B5^VrG}LXfcGau<8XqQq zXz!r4wyG05TSc|4)-`%^{IKa>f7)uEotEp}vk*C=hqFvh_jw{*juf?X+*xsmom__Xh8n+{Q zt`we!*u?Bb47TpGa~}(-Q4XV8ovWv2TA5XeZl%XjH8<2MI*H@n1*De^h}B+MknA(< zotLd~fGXRzUtJn)X$8)tI(UAlxDj-nq&#Yl&bTs$dV{L%u@2I_6*%&h>MOpjKJ>Bc z+iiT2kU4M8Hkzsq;91p)+&%rilHSsL?KOsKwyU;zJdvJa_}A9R)sUwu-BgKYy7k`q zT2mXF$wxsG`$gH$p|O#5T2ReHw^m;?jj!yBYqILn{CG56-!qQ8J#jwGPQgi~w|s}H zA2s@Uh=7V~%9i1q))C^Pf&m3o`{Z#y>OGX&EqGTH4AW`kfhp48_G`GJ%+r2+(YiO~ z8?$>-+I1;5W3>Z<0*?=CtGyKD(C6d|!7;aCY9Ln$0HR`0TwYKkEf;o&U54$@XA5dk~YV_KW z3n+XvpjPSUK`&qb0Ba0^8&N_gFl#4akM=*Z>J+G6R?kBhU)aHKKs8il$n`7NA64h_ zjb-XJ!H=eP7B9nFm6dA1T8=KS zmCxc|NS|ibuH0t4kFH~lKu=x_@w+4js|79qxbxtNQ+9=HTx@!cEDygC^x8dUmeGdO zIV`OnYM#%#lDwgo>7P^sWTp&Tirx6Od_&f3VmhvPiO`8(n3U0}Qg~M2%B#8B zvJGV9L``T?M#qUkbH+N#m}77aHj)XR8=-^kP45V`i0PTmL@%SZr{o@ysjCB|DC>a^ z#b|A$k1+@^)q@ZyW6pX`Nr8cZObg5oH$#H)gkWO`;usnM$Z2hDxm?X%3GSC>=M1CZUn%`1xX@W0Y<2lK62d^;`;I{%%@YQ+Q*zmqV3^wo47N@r7o!WY`$bl^x| zOD?FPAw1XKRjbSHJMoP9iE3O`Eaw@_)(skN%C}JBF0t2DRf|rkJe1%xPSWhROVbVq zPk7ptZ5{mEOi4fk%kAZGdJ26i>#$_{{ZUOC;Ay`ST9uB zXF@!z9+{Qbp>0<0gAj#%L!XYrJXgT;n0=?xYP8DU1sKNueaeL(5? zO-y?*L1pm6xKYgizUb2n@BLWCMVn1Wpx=TrI zDL=4&ryh0wT|}q&wFSfS7QYbT0hm8<`a|h4 z82!QCVGy3<3^;^!o{^#M^&Q94xDf)vVRzy(CQ14TaB|aYF^+R)W;FTgF)?OafM%82dEIJCZfB{f;%o$GaYVBWCVLuzW|CoZSc)>&3UF;Ye|1vhw@ z%mK=51yALP;M`qthEfRY9;QR4p_zdjob(+30F>FQT~6LEOtuCOe?k1;GdYTm0nHgsp zm!^W9T}4hXx3V5p+suzF%e!j*Ee^%4twM`>7svXTD_b?INNq|Tm(ch?;8xInr&xb_!^QB);6P_sNeDHEz;bTS}-<-Q|%j5sZC+xtH~jKTk(A} z%oXW%I(yd-Q)L+WiD|7Xa0c4SAAUmv1J;&-$W_Vw@ddq`ry6x)6CvNCj&LP{wDCZ7 z9==@99W^*R9+v=*GrOVvW&N7TM^L+;+nHzBMHK*dVUMcD8U}OL+XYqou?I83?G)Ha zTWcVGMTh%K8uO=Yvz)MvKx(pZU#aWFJ`aUp&GljFJ$GZv^vt8PJ4Z$bJ)7ELfga3w z{R>7OoefvJHs6 z7-s~m*!6&ZBxu*GQvF}zM)wi4`qTtw#Y6dtMY>A0X~&HDW&ER3Qu-U^<_4zQYQgcS z&OI1)i}r-LF5UHpKADwOpwfgN3*@x1G~OZ~bs`;qZh?}Er~=Q=AM*lTRqM*`0IV8b z+0))SR7$FkNk?jSMIEO|6*YEjWb#bSUuNH@d#GC|ei$A@2rklUZO~=GUy7sDeLY}Q z-GVmoV`;TXsRzz|s;zCw!-T^RZ&_m?{$)5Z>oqy%yJH3^_<@hO0;fK6a<>Fx8+$mP zG~yoxA34E?QKPZf83}_gzTKpr4-(5z{{S-a8T8zqRK^;hAFd!}v3&Ch)AZ#IB8y7o zjlynEU?UTlUV-g5wA*QckntQ+uZ|`fWj8F(S-*&BQlv&|js$mX6_2}xjb98VYsiEy zVcC%hj2LH;Hm?Q+0GX(vw`p#4`WdV`l^TnSq@z*M#9TvYu~2Oo>FYH6Fn|jOP-RwB z!paDXk+FT8w@hA>nKf9u&CFb8h9F?w9rGRU7~8L zao~-}-b}Oq09~5EsGg(W+5+AifxK}3^367>dq+aMk&iN+Z3^Jvo(S|X!k29@9->s2 zn*b}j)5y(I;_Ak1PD2krtfyV2VEtEzQwEp8)afzc2mPQBrQ@`8?yF@yxX)2LI-buL zZ&gFiB@Xr7N5q-I$CT0Pku+CS?%e@XgYAji8aA?xhgU(#Q()u?t-6cp)Pq{P?$~^c zd-8;1Wa`Ze*u=~%U4FIgy)#M)fA(8jNYf1HZ97%%v!U`_pY(6mY5PX9Y9Vc2EUfiY z4BRkAWgzFmU(yyuw@kRclfJ(o-l~0wiK^4B^<*oI;EqSAKH@H>up21qcO`?WH?02v zr}n_sBDEUPfpP)x+wQ+nG@8wB^d1$Ld<>1oNa$r+tMuBPR)MXl2|`m3y&KaU=4e+s zCDkUjq~$c4#Mx^90QNbWUf0kXG_PvCIRS3|JwC@gm72X8rkk`zYjd`%laLScx1_*= z`U;U7Nv-te2c=8|^nwVQy(`gTmPY+S@*-Q=y3^SGqTcjdE3I=9?rV5VaR`kKy@9F) z3vB_R)%FIJ{{WB_Ka{|VXTK2#<5^dof>JuV%{csGX^8p6(<AewvG~MaQ3t4l)JlQn)=~WHG?egc z6H5IEm0K$y@+E8d)&z3wI!*Qi#wJOG*|t(N!}-9Au!GVe$!Kjmo1o|nT?U5B%5Q#) z?JU&0UCU>a0DQD5V`G6H;ufaak%j}zL8PP>J6z)f+EBW*HhhdT#8HH=rYGzRbUBt` z>3&q#u}sJc&&Z9a?B+D!Szk~(vc=MNeu~;^VReHq0$btR!GgLL)#(`2yUyQ5hd^8! z#kE+49<$MbpK9z^W+#127<%(5x3mvW4aXVx61QtKWdgS2&t82*dTexlp|KMBg{Xy8 zRyR+vjb5oyUfu$R`sQ1#?5Zw%cea-X&Aw{N8dYCt>F(YuRp&AFLXC0gY;+CgeI@nL zqh!v&*d%lwtL^0zQ$o_!s@q+K!!KRFa;gUNU|q`_U!+|nDTUswZ1Xr>q9K15QNK}Q zDGG!VR1QQM?Ro@NN`r4Ze+V3sWzBVtcX&4(xE^ck^p)MOI(;?bhsZ*eT~jg_VuK~_P~fh%`vk%eWB>dD}% zdP>-S(KiAKHD`>DNnd<(h=p|`r^>M05!>R&T#sA`O^r{lAD@&KXafE;v*Skh9dY>x zm%7yF!=jzSwr+8rLZ58GsO+2TL?!AzHGaTw!}R|ENPfUg!Enp)vkpNF2VbF|^*t>$ zY0%kyL4$$moZN7ZJBKyAANC-9O%%+9Q7+o^KA$FEgJoM&Y$U-Qpj@(`M|I@?DHU7x3y z`I8=tQ&gnxKp@rXlJ;G|ugCSDW_quv78wOd@*wn=S=biYPFb`U?+fUU*Zl#D+D~qf zpV{lQ#gO_F$RCshBbFW|9|f!C50s;{dmhF-UO5Np3)NbNz(M|djJHLtt;24v&@Cs77x(CdrHy|@XG~*v_G=^9oAEj7wBck0X36Y83cMn(`s6a z^1IjIX<%kT$AP!$FcCEL0a91_$|&ruHC1EBk()HyYUbsrZNc#a&Ca zIk68o@&-Mz@|`p46kt$|ik(8Wz{w6`Ma_z=^s+hE0R2nGW|q5fK2kbR&_ z7RBgBL`$q07-$j7y6|Aw!oF9jA4yuFatDO}0OVzKIKvML#oFG61l1Z(!0N^}k5a*g zLmc}Um5}4*en5*}y_|FcHt!g4B3K)Gj9NIA>Ge1x5p1UKKn5jjsId~VRLzT(o85Wq z9f4v7)rGjn80iLbM6Q$odCJOyM68^ot(0T~n1_O+5}buy+qEb)f_H)*%VNk)LdI%1`BN}P60eiG+KqU-2P*FK!(hUA1dPubm+WIW*cO+^~k(>_yj=h>jVcpLdf z!zn#P?BDulgRmy?G=k*~PF*<9xH6qCn#&H*R6*ijYyLLOTeODM_?!+;v^CTab!baM zD`f1AD#JWUufu`OL8Nlbw?QnH}-F|MTpl^LCHRCSGXX2OZ5@b+Pp#o2D43Gx~-Nf z40~hi=w{B&()O}2bkkTjHZcB}aq6do8s~ixUx6Ji)3=jUPJhZ(s_iN?M^$wRsa7a6 zy#tSC>G@)I?_^q+Q(gL(LN>K0ct4lSCWlzBr0o(aHm=9sHlL%9EFU=H*6iI@?;5d` zEzb4z2hY30ZTO3RloUA!xJ<#Ox`6)x!?f(r^1qgSk58^89jm1%852;P(*A~P8oR1= zBU7h4Zmqx8cz5KTgmn`~Y7Bx*rp3)8k>p}C?0qo?DsnXEY@=00x_fwA5TX3z_I8_9 zqp;R1sr~mBo{cRht4oOBwA3DEqF&s~y=BMFUV6N=emQ6J%YneK%h^xHW~BZ$m!7WD z-{)y}^OQwXel`GZiRxqJoJV02h#Ck1y+a4YaG-}cI zvjyeHv}ZPM!&LZs$t2)Kwb|cVs;d!^9j2H{bxc7>{c4oDVr;=+2$Wn-xd_ z#&Q1uA}VSD+rT&=N(I_oSw>W~elUm3Pq)8}!{zz0h%~wbrm3(Wt~$ljX>}#RW@W;` zuF~o$+(KT0u6X1Fz?W%tc4aw2M$_bFi~X9g+m8~ffxzkk1WKvWgthoDh7Hh(c+K%>Nz>5WT1H#>VeI{Trocf!rCX3syiU%# zyJ!WFocKqQzM@<9hh)tNa8j^O0FH)u*PpUfDYt1QLE*sb7Trs(xOi9YR#I1n7$cw1 zav|)UUG`f;1ir1mLI~&FaRAj_t6IRW(p>=b$&5kA8@VvitJ7Xa6tGk8=QG+ajtk@HHINCkn z?C#6eYitQ&ywsK_kQ{(xUkP08uOu23Ay$7M|Eq=nOt8BXGA||~S z;@fVicDKB)>qQrghC5DWwP;a#;NURygT`PvJ4DSP2d^_~@Z@ai5%gXt0NIG`r{wZX z$t)Ueq2F{>B`oM>Y8Dg8mI2|fAi}(#mTt}_-K57gzZ^#{8#o!8b_2kPz*CvbatT?f zqW=I8XK9Xv0}Y2D%T~x-0MV7Y?q5icXYAV^#yBJx26vn(igSm;!(B`VA`+s?@}^#x z@Gd1t0w!pD@S*6w>q_`G^;o&-K67jyez9o61)pl^LLb8$P zDbebUR1Q$#faYDNxsv*iD~u7;O=g^zq><>eU)uE3vi+y=FG+pnnQgdx%?Afq*SqN4~OtRhw(CQ8XIbjW-ZM=tE$s^#{n!K7&*%zQI~K#d?I|x6k3VdMkP` ziP`tJXWrPQveXiOUscbiq|)^a2%1#~ku(~LA5VHEwYbA6m0MHxXKARpEB+P!WqgVE z9Q?yGLm(g!6!6_BU)>rgh)hy4Bjpr~{xsQ7`On*QZ9;c+~|p)Xn6*MBl2T zQnqa-=V(hg5l8%@}zYcnWQ5Y zXB`>3x3Tw?Ybq*920v%qaO`V%OG|o!W%B)H4@t-jI*%jdX13~qKRDt3qH0E|ds3f< zBNdWls_n%|E@G@Y+e+Co|((RTg%XZbBn z*_94*C2D$!Tth0AiCjro=?9R2`9%YjfPNW|!yn0Ik<4MnM6~i+SVzq)KZ;nx<}uF& zqn?isP4FS*yVZ{|1XYXB4)Mu8Q*krGsFM|_cPP1=3oOevV$vhqcsPc->Otu+{GOh3 z$5N|-j;%P_qcPNN1~{vbaC*WS6&r&Ut!l{l#}Kb)*;|4zb2rqU5F5eZ!E#uL*ndAm zG_})X3m&@)l`NQU50tX4A+LW<04JPBtu}B2u3@6`6M>nBR|5f{t5H)uej)?$C#dv- zt$8&eTGyZ_@Wfqn3awjLcU8=wc3qS^w)Mj)Zzh6~dAO3UyFi${d4e)MM5d&_#q&Z2 zV}H~sD&a*(;6mIitFw{yc{$XO$u(DKwVG`@7p0TMa>tbb^DC>g2abZwu2&VfastV9E{HsNR3hw`Q-lqDe{)u^wycO<|Wy@@H*x$k4>iR>Ycx2 zo+s3k7@gV7+A46O)hnI{LM1=i9>BeFM`==<4$kH=eXJc(M?8%m+5ejjH$8yv5&>xgwUGHGoV3VHBf&)j-> zMrKbH87@=^;QL0={B^#^BZ4~1dqR}ey=azE)qwbz9x`FmYLV4lJgu#ca~Aq^B^2)< z(p%_rkMovj{BI_*l7ao3%u2PTDc6;+RbL5f{FaWOH`ktJ`g_w$s!XW2Zrgd-rGOwG z&Ii|>4NMxoQnuV77`u#{3ND^bu)tQGhPwk?2Plm!s9Kt12CeE;{Z2 zbN+Ik&bVmX9s@o-nGYZ7m^U_?!Wp2H4eRYGxooAX9Gv9EYJjOiTHrlvjB$>C<|B4D zXlR|=Hnnb^%o;WQmv;3c{W5}m_MBt-N&N(Sf3unn(@Zc?;94Ttew$xG$~FU!HDMI? zsBy}5{Uhmfb_v2)Qt$78y$J4zUrD8_yq(!c<)DoW=%KI4g zYYl{Ls_%fGESOUEqTVk~KCwIlO}6lHw?0Nxdr&2c3N{DVGR-Nnt3G9NC)#hZ6@c0@ zb2s*~X^Q+Dh7f5isnN4hBohTew(?2hZl{(Y^@^I5w$4#t6*DGE9%9>8?t&Dkf-#;1 zaZX#T4&W2z1+4X+kyIK8AnXyF0?Zw zqbl`T$od&Y)C*gKj5Jlels^fUae>hBFL`dQw=-gD5|K%M6yQyov>~y(Ade#*T^(75 zI_;W)eZrD9Fx)f1mEZB|8#W;Ll=TqUN$5O;@Bt0VKLt!isp&ak)d}jc#pNAHA{`9{ z!NWYep|r=bgKsM9(T7nj4l1$AIX@3PH_{t{uGZYFHjsG+U!hDbuWpodAm!-vBh(1@ z>4v78I-EYn`l<&0Q>Z?N z)J^YIcM+B1x6jMZ1L+f2qdTyquHa9UH6j~SHDqyOjN|G*+)4$^JVUXEz{}+plC_`N z{6MP%g=6*dGO_;vk7|3%G&crnNu80} zc2#brO*XHb(P}H*rPNJMnT}Ml%o*?9?*jEPMBGLoVY#A30#_>oq^h(h0(@r?fR7$n z+ziXHlg1^yjG1UXWu{pio=% zWp^K6Nl4T#UucSM#ch=w13X4QwOFZM6}~SqEu{l0_316X&=hWH+I*$M25w#IawkjB z?rx1OUd%4d4$o2NETdVJT!a3GB|4pykl0W%rd4%AdJy37W%qV{HdDwP79$vdzD0$- z@y2HQ0qRn0u~_*S?)L0{cLJl@I$jUI6HNBgxtWXq01{|#)w)^Z)uXT%t$@Ik(B3^P z&0BG~mIgMvHr7=*maT!)EdHiD_6COgm8~cM^aDQ9guSTMGN;;WbP4Q4YHwy86N#uc zE7bVk!)89WM`}{z2m_LT5c8ECC_q^QKHvwpOvJyng?1oOSPoA@0P7Q8TF1j3=ciBv z`7O{Kq6Xs*$;zT$S{iEZvEH!bF* zHdMtyQ@4YkUJOlDO1HYOE%7oS9v(-S{{TGwL}a*W?9>m*aM=K8;IxqC0A&zEZ?@Sz}WRu zkWcCsC)qUBejw$)$|d@`)S;DxJpu*a^-`w>GcijgmoU{61`Vo_J?J?rHwKAA_pX zSfz^}ht4nAk;o#Zuf#_7K2TfXJA4ET40#EtyG)vNw2v+i2c)|<>2;)z1`nFB=wrTu z_akE#3J14SAHY>MVfPGA8rv?YWp*9I`FM`}5r@V&_KmC2(WojK#Q|IDIv>nTGPCq2 z61`@isON2L#~)4%XY6kWt+nBo-wluVflc&kvKH(k^YWj<-;qD2W7Vr_ZbGk4cs^J# zg|(l6PftS{tJ7l@U_plMI@w4YH4N3-zslJE07D;BQrJPwXKRD(aTHRoLwq52{TM)n zme1k21jI_kqv8ns5$I!hXCscen<#qOw-r0qV@*z|oyl_Kh)vC;B)*>0)A@bjLr%7% zy;JsXiP>2OMPIVc-m(3jT4PCro)Y5vP- z;jC;onw*)s&@r8dCL8T1q5~Dtlcpoyjio&^oXVJ}tc3|1Qctmr^aMOS3<9HkW2v4V zpeu~A^P6ujW9qf6&(K5SU`H>zF{`@_V%VUGMyE_yXblZ+TR4S8VQxBu8Gyh!mWuaB zT{%JtX<}Q{uhvs|3ao3gYiPBOawEOw%;1P`p*rUr!fM(N#IY?S#2k)>8gEx0E5qV- z#$$~}QSr?CN-e4maf6R(Wd#=QQ!xXORa&o@A2BO6fa54fSw*N4x7+2JZPcBCMa${Y zqgA~uLbe0Y%ZLG7kUtDdP=~^?7(TN4oNOhw@sa5-vrJK3w*%{$ZlP5!<$#qkguuz` zk68Lm)z}W#UB1RyTUNbr3g%oW$l!)040C^rf{*PlWlEio!!P?ouHmuQm7D7-T$S_^ z-8HIexUPJ}WODYBSamQRtI!$YoxySpEm4*f^%B?l82u%c0N5msu}P_zZ%}YQI8|8k z+Z&L4q6ORnfX$L7``z+(uRsi8!<8e+$j9poSQ8&FJVmr&n1=)5Fj-%YFkEm%bzmGY z#Af)>j?*24Hz`u3qiI|XPsLYF{%ijL+&|t_+;3JMObFylbOrTYn}=2zw@i9C^&ay< zucOARsQHlm%PPQ9rGSe3)&chO6H`d>^#1@lj53eLAh#O>ZLo3=LVwuL6rY1*RnURd zd&|*kbRQ#Zv3li9RQ?U6T}P4N{bG_Vp|-eUSv?Qs>ooT&(|R4QIybNTh}t8thq{Bn z&n}+c;sd7Im93QHDn~#*zDL?v{BlpPsFqpBBOMHDT-N+ry+^OOhAjIkbv_s2e>&U# zBI@W3kJ^q8x&Hu}UGzORE>*|o50MhhE~UFOS;MdJ+sT9}jxwL-vuVd3-N5x(Uw~Oo z)?Q|>LgT`AB3dw-%EhTWGqo2q0G4`7>E~f05fw5cIgIUyp+-asAn!5Rj5fFh!p5b_ zzYHSdn6VZqU8D(Bl>(Dvp5lJt$K5dC%q}MSfQd?#QJ3|FkEw*6#%xS4>kYT=Er#{< zo9RH>9IABB!mQZ}dACWZ?F}0XEN_DaWtvn~xF+tqmIkwHba5!Et81}0ISimc z#X#!4C-B`@XqRfz%}#MuLnWfW_Hvrni}dI9Q#HM#Q&Vab@fYAN&|-KD^;w60p4ow| zvX@XptZi18Sx<-^HjSz}sU0Jp)Txc5?G_v$@<{qCbsB3Jvn{Npy>MU@A!o)0*=~r7 zS(KpQj;cYLI&~^^M7=~7QUMC0B6e-s$Kuyd0Y*BL8k<_3n|bFwN3oR_%a-_g!ih$! zRb>=0t*ldx-5<J`{LN3Vc$z!6_rO>fRf1P-7}v^uw=HQt5Af!EAIPPmFc zXS*z*#p>3$8ma!EwfrHa3$Lo*sl=dEi^}niMu?yGX97WbCUed}DmaWufkoC{HnTj;& zWlLp;eY|tNvIigQk8uhePMv}9@(MEZ<;Us-WYyZW1+W@92lXn_q{f69DK@0LGC}!T~CXs z1A1fyb>(v}zd|)G!Dy-Sef?&avpZu$V*J;kTm1>(OX_`pXH`lf6XCLZ4>2!G{0ms@ z6z>W;WUg2I$eXAo#{@EvK9OFFX=NlTZ|9yzAMX=b$dw`SGl92`Wma}!(z{r~mI>k? zLz9vD%k;>spB-Rhc7v@31K%pV{<;WmK0v~3xsI-vwuJ&EA`M6ES_ z5kaeSFzH|;8-z7p`fDsTtMUxITADJsVa7)yS5}7oF?^R9-RMMSwY0=&oJ zOEih3QMIYahe=c1KZwI>!>!O;;~eS!OBd7LKWFQlUCJ*R^%Hd!Yb*H&0Lr^r7Kd<` zsKhnut*YO^O5phs0_tjCe8N(z6a@_DKU|sMX^K)YVHjiTBd2GrjJV5WA5k}wIT;hc zTT~EPhgjoMD+e>|x7LA9-J>y0c39lvHJ1)>vFT-XFk9K7`Y=eZMGTre{9U-mv z=ZIVao?T^LF$59_qptD(3ye9=>v+do2Vj2Sh@vKd5o%FV_+<8OjWs7fw#|@lj z8r-FdL4hi;XMlgm@d~p7#{kT#>?b3y(sAIqCbP&fskyLtfzUEB-;5Frsns2}T5+GR z)@h$otKhmmdasmmdb$ykI61_9CBU+st;1p^bS2d=DDhOGRUx9>Sru@>esL<)meJW~ z#Jw^lns>1E8JqOVq=5N?onL^+IrI0G_}iP6Vb&nMayWq3!UO9oYJ(ujZhnw!G^Vn4 zThvCag={cK5nmNqJRyQ|A)vdeF(1nuHtL5+)>d6t>LW5$wBU;|9?e>@V5jj9A|Xve z*;C;Jx|`avK9Px2?a1{LYGp=O`43ed#(2yMa;wSp5NXwKM&6@`M)MIkTF|4nI6waY zcr#clC=@XC^^U2LU>Q3$w*)t&)FWg&DfTkg_$<4B{{VW1{{UH9Icim^L&;jcB+sti zqw<3K_te7F$1I%vK^{liRYtVFmHalaoBTJ1l{{S2z>VKFCUZgIkO>njPZE#hOrbMw2rpKwu^kph>^gfu3 z?27gP?g2*fe^K?G7MJZRnYw}-+>Xf@wuvx=?ar}y$wf6{M!H}OCJ0B`>QtUB#5dYc-WIjs8oL9f%D++SZ7 zENa)ylgxRKaRVr2AgSnkiz6?n#9dy7wqurGg}$SSQ>If0{{ZA=`b|fgl`$HCmw-+t zm$dk(gkv@I4fKO@%~cJy+FcB_PDqvr=d7|_>O{9ZlZfWL0WH+nKL0;nAS0LhgZ%S2;a118I=jcqf=N%=Kw7 z0pomq_-4rvR=bZe)HVSuz=^5VSm?m8^CoOyW}%b{_);=)HHP4HYC4Id)wl% z7V&_5p{@SWTDn-g!>;WXy6&cU%HSfij)1lVRM1_zw0{i=DyxCIKDYZPPPW29Lx$s` zm^9iAEiCPdh_tWEoSqtx8unXW?x8quN-O z*s4|YhAMr=e>gPOTr6fb1_xnNw3wp1FBO8!0*-n#VWbvb`1sD$@;x)3Sd8Ytf~5Q^ z2LM8s>20i&VwG?}!4W%0QLWSK0wd$atU zs~N$Msnu*YOvUC|$ZMgYD&lA=A1ep;u<- z4Ul2frTTP!1>1uUKPloW)Lb#Z{+U*o+?TDbKyYhi>W2rFnvq$&AzDfoM;#pqWBP-~ z=L+lU)TcF-E3?ml0nevcSlqT_VkjWvrUyuTTQWkN{w{ES&){n zEZ8BBpQke09MH*|Psn}q(rQ;uYTS10%MYebB3q;>r6RS|Ru^LWfrF2HOLg6qK(y^` zHbRVYdCO$Lnz~<3inL!+xZCR%)~R}4w4>ObpbQ9yOqK(~J`efNvuf-t2~p+h4^jF` z`!c(3-Illoq~n4;W%V_+mMv9-ET`5Q?Y$1mRH%GuX3h*dcu?SX>A(53EPrJM+RtbL3+2@t|tzJd@b~g_G>K9?L1Y- z(1_;B>$rp2|V;u?G<${>G20Z z-<~pNoZN-nrCOzGHEZm8F!u+T`fXF`?ockM?a1@@g>MX`5)b)BCd({M+ct|EG*@V~Bfz=F1BKzf zvh5}0YN#z(>0KCX{!HC*)wUa8~gX*RwsB5?89Sm`4T8M4v zMm_qE^8#+eFH$}rWz=cIzef33OBMFBU>Mc#-4C2Q2}XkKEs8J)lot)5w%EN7thg&y z<+o-PJ1rrTp~!*jw@Mr!bG-~|)A`hKnAV!k(lRD(TdN8zsNwO{h;ArJ!k$BV#;762 z9GvmeHSfIOF*yg`7Olbci){haX2d-`L`zkab@Y^toZ#fHC1knC_&R&aZA5(Rv&j3( zokBRTQZte0!Urs=`#1BgxgSyO^!(v#L3U*a$euqV zFRQLt9*xpm&TOLRqT%MeAIy1(nww6OwdfVy_%Evqzx|1tSF0A-SwX=&3Kc%1JZIV+ z6Rmpu-KTGo_5T2PG{ik_3b(|pIuR1*wQV67f>Zwhm)F)c1TX&pleysaTF=+gQrB3Q zJJqQQ4Na0(e%bVTr78R4^j6AlCxD!%YEnem>V?-@;LthX6n(%uhVu&2ZM~twHh|g3l2nQ zA7j;W`2Cfi&OHzR05A1}KBRTeS6^SKmUeEfJ6}dJkNi{}7(}+Tww_VOK{3(yqGUJB zzP{t$7G24Lve?z#tkZ+?T3CK^#hQ-TdoHO!s*i2w@v_Jwt+Mq zv!!IVpqBy2A}tn_z$3`SJwSuf2s0FUcM-~x3=B*0lh?c9@Z4oT&3=%D+_-i19p2C$ z3c%e2YRoaQm_+#CneGq>3|f|NVq%6cGa0h5zH?|kWX=4*lr}htLUyuQs9H6c_9kV)$sRZH7r7AuTL)KN}}8}?N|x*bb+^;BzJ*mlPM z0AT{?blt3r!+bUm%u#Db9vJShCpOgtsp|A>tmuq}_tODvA2vTd3`!Cd{%E7{h@?S1u ziw6EzJk3S@o#J+S9W7xwYe4DhC;tG43m6BnJ`z{1J>^yC^vtY$WL<=^3<1;-dgfhy zry?8lnaYltlX5;?{tdYwHDSW~eAg1-xN z>xp+~cBbIP9>BL$%kFc`UeFb2NKo|>RkBD6{J%`buS~j4GM<=b^p9O>v8!j{OK$^l z`a~NTx+5CFB$g#xa}Q5xCK$SLvz^=t?8CK(h2soEBuV&uGv`KNQg^R85$(|~rJH4l zpB=6~U^)^y=4^4ZJ0Fabl0LI@3NLl=t|wtXPBZk0_CK@gfJdZ-HjYR+Dna!fAl3F& z2H-4B1*|O@{5Z({NW`@3Yt$(|J0?P?&Q4d;`F*P`mm&NfuC{7l~kuzS76k*qi>+j zSW7e_`c?L2_WK+eO^B;?c-zS<8&N~O1UWUqMygpkw&3?zY9S6rLMj0acl$;wDf8;ty-3|2R>sGx_fI(&rxb$i%9a%8J-3D ztF$#MRM@i8I-|j2Et`Q{13t|A5rv4|7)?QCHI2UqBzYN8-EnNEhE>O-c}qru?M4V) z%lb;{)Uhr`?ne@#VI{g}2i8%lZJLXVZy^eL4_WpjZCb05>T3#+-kz}Pbf(=iBML{r z-fTS#)#>{`Nvx;`@LZ<{%h1ib!LQPMHQ1+cAAzAAnwjKS$Dho@Ui(+#PyhspLg|{< zP42v?Fs|obN$4ZjNktC90iJOV9UTbif!98w7r}1 ztUV$PQCg}&w}4xd12U3|3l3%K->`g{excA>%+~pnJS{DHb>NP&&lMeR`iXedDlH{P zlaVjdYE3q`j)Td%5f@of-=M0t4lvbusrH*3mqC@tWeqB&ZW@%cWAca4%G_WRnDjcj zwJTZRq+=>dFL zap=<9okl@F>Lr>MLfj>z;b~!IB!Dy46H9DvRD&9V1*32hvua&Ms2P_eG&X2WEJJaC z1g`3nO=1;#iP~e`LtS6OD?5fgq7pBqfff&mN0FNmvyfGwropMB#(rH^&j(=kR0El_*Kl2|`L-=DUf>;it$cX8zuTOe-#DJ*8^25{KFfXdp zE4tQ7vV)zY(;m?~YeIBvRdwjU0b~4hKk8xA-Llqt-ykcmmzO`DCZ}7pY!qv#1S1ZG zy}q;lxQMU&4P{)fkq6HPYP2M2?xTGql_+ou=gZLhbj&uj@1$@UFijQ>tQ7i#Ez((K zE?83hGPZY8$IskDZ8$uKKyo<*A24GJ>g;xY9mAZDl}DH739LBx{{UEQ7>JjeZWu@C z!^_|DGTRZVyPa(x7$c7zeA#{dWjf6%(iR>vpnAa^Se|qKjoLqDxaUWC_!#s<6Rz3e zH;-LmhvPx`hp6|JGKWG6w;;sQ{{U#Ls=lXkU{C3uh)D6lMza-v>tSP^Zkr@R+xd;7eTZ#7DG#*O;R0mN8bWr&;mx#Nff> zmO^|tQ$BZ2f)IVo*rc~n7{24yZF6IcfeC6Y&NrZ$l~qTAF}b|VE2t^xdcfk^LHrZK zwVlWyf2^@?TXh&sFi^nxzI_A>*{P*p(`@lEH4;LSQ~nvFPa1~(Xd zMpAR?##Z`GqTE@K6>%xkb|#lWt4CWE7&NAx9kkm`hQ{Wy4}FF(=(mjSK=+uiA~xzY`a>`vVwUS7$=V@cARk5BZMRn!~^M> zdD9wfS}p0F^d{^dd}e9Z{)QT;C+x3t9#EbT`^|Q%T61w^Y!XoXJi|=| zgKksukT`G4$~f5IvghR|&x!V$HD{}pBxl!y{>D8O>XG^TRZVDLTrrGMuSW5Tal3a> z$OGCfI&a5iS2^p|GCcixkEEgYs2AEk5$QMl7Ipc3^B#*%lI#^_${wJ^&6d>oYYuEf z_2xZ?Ybj;tgVj$xCdExCZOKyX&!hD@g6dN6GF*lu>((-9tkk&9P8DTopw!n=?6Jl} z`G7ei^AJ~|T~Z?1w2Z5B4SFlQEULSL1A24*(MqF?a-3?Sn^_u#MXm1-WL)QfG-;tDdZo0}eT46)i zV<~qTZg`hk?QuOb$?F>0ne?WoE`(sd4-s@tMzdOh>%UBu+=S#DaT7(_0HUgBZaeB^ zufpGW|A|+F1$~Rr)ge$9gJUDJnMdB|`JQ zt;k~Au3D(xLCHSc7`nGluMbi zsKI@NZxxxyQRGR7Tc*E4&A6y9QTK;SMJeV4UE^kXIWmfAYwTRAjt8lMgE0YA#JNk> z+gcm-EcT7G(eYT`-k+SKRE)t?Fz5tBs#YX|P7GhQvhMh1+eeTcAT=`smWy7bGu8;6 z0j~6NQTi{Wqf#uej6FQc?zOR6aVxdi-3A1wSz?Oa>i3=v0+hGJ23UceSAHd$TZ2~2 zq#TtqL9AWe)q9VLm&na!RV8+)y0+tdx~9X|g*^-}M~I9V`Hwj7pr>C_6OgsJ^kK*P z49h9N2jOm_20#G_*x}SgzLiTx>GoYgp}to6NrhO}-;taC5!8R2B{H8D&zO5pwCTo& zRZ+U2*(4JOQEw==XjgX_wOlpvw+jkNdK5$auY~*8W0}5)@kmY)z9%3ujF07uv7%|ee zC`l+Yh)qmi;0@42O{;A@J~^AwAF0k58TN`Tptjw=5R3tRfQ9N}YAB}F_$={2SM(5# zSJ^cfJHg0d!I$VPYJuHQ&d+Ggsx;lgu%0DF9D=yP^$=;@uLLz>d~TLLcjx1H}6~ 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%0AcO->rQ!+A?=i#-{oZ%yB$z0KHn3O701Y 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%0A+7V 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 z z+C{*4EtxL=(EFM9Bu*rau`r`65veP9W0+00CB*N3iheSibWC5pRL0NO!B*s~E$vbSS_))#_hAnxh=TNRT3v`Qc1C~BvCpQne4r;UL_m>0l zN?5*O%fl464CJZqsnS9ooO3cCy>c%1J6!&h`+BQn6->i!>MidugwAxpBF56=E{TEA zQZ|)0>)%}w?&!fd)Y@f7s+z$y{5&SY#V!)d5w$q2$2^PvLPF92GeYF0wz7{V+OAOn z%#`P|EtLlZM@x{AyGT?Z3CWT~UYRVUF$IH9CqlC`Dp$D-(sxBF3SKON4Oo7E(yX_O zsAcAKY8ZQEn<6G@jS}P4ALc<>8?aKQzANq7fE~m$fu9rLSyqWkD^4qh@6)%W^zziw z*qaMfSM?wm=VQ=o8WR3ELZI<=DjyLDzj_8{@?5|q&WToA_ zT<={5sg?yy3SDLbW!$t3rDK!yS@?^vQEMpLW|^ax#)_B&-v zw^qD=MrTQtLkN{^0nQlRiB3tbo?gBiQJr6MoO;VAz6W#xkYmiOYZl>Ao ztZEm(;7cu^yxkwJ$QP#lVk`Yc4pYmPL(s-JErg#{za3C`33dFY5L=AQ$a7Ciwa2XO zy|F9&brwMeRb0v$#?shjvpFV}P0r&F4DEhNch!nV+`V=Ejvup2Wrw-w7pXfS6hFjG z{pJ0m@!a17U)NaIt`*LuIwH4ad>VPt9!H!fF`_=RJG@+?vSDi_`YE62PtjO!rYX{IOR(Zk&1pU)Gf;>}-}G|jb*m`NncU9< zZOxE&mPD}>DkSNKC8M}wnyO;wETOV}>y2*uw(@NbB@H{Sk-14DC1L$ASe`JGhn9D@ z8jJnfg^Z?oJ^!HGK90{%UtKIOQQFe#8_BpKXYr%KcgRSXaia|sfL*= z=J;!lX-c%{y+R)l^=Fggcd@`fh%ds~q|~1HQTRV{nq+Kv&>75F_Q!2cU@=z)O- zI(Eb6UJ1W|K}(RtH^y>H&!DniK>)Oe_VRkc$@$=DArk_*>@hpC3r7Io_qSYFkd zJKn2A0Y+_`NgWNfQJO@5@j|UC%#*Y}2<70=U^d)0)lgm1TTF-dAY}_5E_Npzu?5wf zW=sn|*H}Ern8%+Qv`C4=M^GuAl5)0Jm{?jAZscww@0SNpp&qgO+^;tiuEU!i_#7u? zqN1E6xv<{BNkkuBp9txHpi))#W9Cxf%`_h!<(}#smtb`E&e(-F&ld&{V&(Bz8Mmkg}Oyk)7YXN>D=0X0o zmwtan+LCb-Ya}-bfPnHYhM5?Kemxo-Athl7Jd4LlE-Ztrx?(ERvmWA5-kHAiYMysc-MxkC0{|H$i8w#9J{ zIztDTn~#8#chZl@W=Hhkas*UZ0C{PoZJutzAs!2|HzzobCt1fN)iKeDe-?^r&nJ_! zHt)PD`9ZP1WqE74Bp9e~3j)E>-6BHBMy>>vC#EdtkS>~xRIJUT;ZBNMTk=11Xl#2f zxp}w8$K%Ye^HM$&rJ~6bl*RcN0rApOAs2^Ms0(=ly;PR4@)5^%QFR5y$Mu}}fU}M^ zcDE_yHMbL($NqP&ooUGA5NA>ht~xfZItP3;=T{`^+C3eg@u{}mC6e0%#-@F`eu4={ z!gJnavCM#J{+qx>{t9C9kUM>y&X^Sk^PWXiarxz|hJoZuGKWnj(&lAiGU*VU!_REf zp#d?_wrRl3EwruRz?&EBFwbmSs9V~{(OOy63&uUQqYm=vIR65$(SRXYipy|#ar>QX!a((c}9w${WDSI{8lf-CtTBjZd$NUSnj z8w`_49ik0Qn|WUjaWH#(bf)UbolZqdK$~Af+xO%EPvg z+ccOJF9Mls3(A0ieIm?j3V=rE4izNLSUiixqWbc=&vWHG@a0#@c#$p898Eb1*34W^ z#!D0m1afHfnTp4_^`GUw)!M6)oQT>e&C2w8#X)T z$}_Y~E90D8X5wNLbA1<_Hk<&|&eD)*C32aA_{`piC^|#)Z58+kC{!a4Cx;E`IPk29 zOu}8`>Ik9K4?^kRMG34y#oIp>w)CPFUSVf?ErldKeB@>%eS%CqY}V^-ux;t%s139` z#plhMBbMHg?cq_###;QH$SBidjndpd_a^4zx2oj8gNPucHhA@rzdr1P;~8cZTODn| zvRNMoOyMrR{D?M&PoNakU9t-JY9Zu}Stu`6lv7Zdc##!Cywj(gWoErFJ8GeD*%>nk zd!A^ugzj#&wp(T)=dm;E<;u(vQjN82^DR(Y*npo&iLZF73e=E4jC-l6@Msa@6M^sc zKI5jNBe(B{w#~NBba_7%MNWS&W*Sk=r2~r3@ZK}U|tO<0jiKfz9UbCPYAR& z@<~T358nV50tC^izk9&G5p@ZhMoocD=UE=@EoOJ{Xsk1`i3mR<-784U%_NhP91Hwd&UsvI z*^J%zY)Z%HKhrZv$t=x`?;5YR6&`yNX@)aqPEWRYXmiY!Rr4zv48NGsE*Wh5Or{ON zJxrvi%p15W__Ew#)TuBo!YD>lQ^W9DNMHWyEGv9ke~^4)D1EZPi0jwv@TVzJ)rYsW zPdPBQnbCBq4q`5M%g(#aol(}i-*mP5l(vlG9Ghp6_A=Bl40$LLVgm`Q;P?A&qE=xT zDNLRCecil80HN4GZqb3JHJD>OqSh-Hl3w4Eb}PKmDYBNi){h-Cw6|%hvKtu#Wm1;5 zm24{uoOId+bD?l(;#II?B{#N|iSoo~Y%yZXywYGVP>e7t|7v7&XgpMrazP|!px)hC z5f>OB6(GOxy+phzpwH*38Y~zzO)Yg5EOHdYyjQ<=+IXnxTFTppipe@{8P0k98W1%n zoq=T57xJYQQRBvZ(rW`Fc@6cC|1?=s%)XmZmT$0T{~jtbs3$Ju^s~*dr+JB$p5< zS822T4D>dD+P2{`3g-QZIFyL(YyYBL|Q7JNq4} zvlTvN+T5xDK}WDedLI{=>jT&`fH2Ws)FwPKRWa=4?F`^JBDdCXFVDcSu-ma+)3R1K zS}S&O%h*{WOQ+b{Sg|~cXeRW?4k(B~2ULFEQvozbc_y&sWo&@O=>xDf0Kg3d->-)( zpmoOBLak6wFDn@D6K@IID=tt-BsawUc|(cngvwOCl+=lwG5qSmPHX^zbp8rUNzL0v zc`lo};s=c(#`U$fMl_`AmU%gF&d8F6HEhZnz+T_u4t8G~`(_p*yq2p}px6+1;B?|D zSD7~Dza~#~&5!9zZkfB?3XLa7!PB!`YoD*%njZn{v4Pg$EgPYSwk31w!r9NUOifqE>gLs%~8HLg20#6MRLxpWk2@yqCS~%9LA1JRy`Z6 z*bktvz2o_)EGg4$l-DrV!KAYieq%uXiH$_6|1JzZerf5gNkc7p{Gh2Ru(0)%b5;-p zfw-ldte-IcF+}|8a@7$P;(}4J6?xJx|1;lku6XaVkhHyxKQhGM_TskZ6lv;DTl+&9 zQJu}-nm21o#htlkp%f_OEYp_9hmWP(mB=@gJcXn==XSMLlxWcn9F(5-wZRi(#%rYk z?>z;%80_!2>ymjs-1(iejRJwm_fPGam+DPQ4tS#{^wcu(JRL$1d zJ;TCkZIdCyP2~r9^H^kv!8T5zrI$zXnap_(u)ZH7O>Tl&{@GaN2+bA^nXhN8yi!V! zIFwy*PS~y;xdSI-&ON13eR6~U#n%ltFPZ3Nnz4kSYFED;5+4C&FNfADXV4NUu9UN& z3UT4P3348B4x^z+9dRrc{W^>daHhfxXdS%%(UB-7IPWK#bp&L`_T-$y`>`*co}mnK zb$PcpEfB(kJCW& zmyR?z<$KLD7VZp&aaLA-hlG^q4Iw%BeePAUU)o&^RUk9n^S?W=^|8fD6e{cyr8NGe z;zJs`LA(+W#Lu)h;KuS17llPBq-?DZDs`u)8}>SYSIsWV@&(2XojahVabVnaWb%le z#@$S+9(WeZ-80;W*W86W!lJZH+lFTPz-6CPd>m#+zc13+duq2fpe9#asl9|O-2@4D zE%o#Vid?iWG-|V{NMVLALe-8(Rp8EbU$ZMF=nq~$SnZU3qY**1fpA;Ex$}bL``eD7 zGv(&bEquLPs*Sb_o_|wft+&^<2Y&RUNaxyo?ek~Gh@m7Akaw~JPkoiAzrr;XZ2Mh- zni@0vClr195DiQ-xojc76KvJz_kiTuz^Enp%4}3fz%E>MDr%wCF0=BvI(jtB_91XaEcf_BXsR$e*tEQgIM)pojyWCQ4brsm%)=#ZN_*R2Q8i6mV`@5UT?yrth#jBf+$HYvWyzS)ZCzi*LY&9N+a_(giQMzvwmdI+r-6h)yoHiLK}ks(zp#^D@T!?fRxIaz?_+JG4%5nd0-H;7 zxTssnvW-#w@pu*^i3(wS2s*I*@RA2T?%r8rp3}~E=8jK!KDQjUlM|H1A^0GbODY0a z_PS@fMjRU@-=EG%MN%S~?JrjOa^CFoe&a_2H4EqPsLSMm!tMK<$ec}^x;&LH8zBW| ztmj4Zedg7ECE90-j4xW4_;Si7np^JKr_oOZSYH}dlkNgpvA%0GFcWklF$>qS8?)m| zC?FMsp_h@`>I7!1tVPCN$ksNoaMhC_KU>m|pls^}gui4NRB)3gS=Dr_hnHR6d=VkDrSlU~?%$vZ?caR9E`NeOpT@>r;$=h6#<1}2$hhLH1=}seSpm2(abq(FaIRXK zb|N968N=nTU1jExX!cy+XNvl&BzfA%MMoVrJGV9FLC1^std<)tl7Mii8T-ZvCy%hy zHcZ`D{-Ip>x)c1^=UMxNJxo(FIE=V+`Cc(@^nDOhFYKDeFYta3SHbv$zzsLMiL8a$ z6vNOej)!KZEBQNovND-0k6mp}M)broE$ei+^|1rkSIaEi4sP013{SMd$nwC_m6FRW zbNwvdq~Ng8wDfb3z^l3ty!xtY@|sln`CSe?>Wj&6mwM{Z-++& z9>v%q=qY2ne|2;_%jME{i)^M zFcIeqBm55YU&~VQA<-2`z<19){F1YzyF22}OINyYsur{PxBXCQxZ3H5zW4pIBc=Y; z4LRmt;^_^bwsJ^BbONb7y$jE&r&x7Cm;0P1nglt>O#d-GP&wA^1{C>wsB+ zCwl_VwcgpOsq|7|IiFcU!A|BJ)0>Mhg*N!jKx$9gueJ`Q{1Qr-!LWk^5UqKy@~E9R zyUk|%d_r{ZTw9M|)p%kG6|}alcL%JVXnEFOyc0+Z{&g^?oXL1qr%gdJXoR*&&M3f1 z%CvL%iP>S5!UaL@6-1(0Uj{1$wg=K=BGU*QH<)cpbKraG!dYyZLi~z0^-Lf<;a#W5 zZswZovd*r5FTO)yg)oFohVY9Qz$W@K;c_`q?Er6Z^|Iv|X4|UV3H$Ou!8(Ny@N$TL zW@6VeQNr?GfiL{cDc;EOEIG#(ET|QDCi5+%iF57;uqh%dtk!z*2HnED@p@E{-rO7= zOY(k1RVdEK+Dy7-lS}cSiJXy?!QC>LYC@2BNOqP^c6Q!N4%fY^jB#h%a8Yr!@YQzK zi?2>yX&Zmv0Fo3DC#(0_M@ljt1^>2IR{i*-RiK>ZilNI}wuVyZp~Ppt2fm(G35Q~l zrc6CP_ZvPP1p0?yCGwP+FOk26MP4+iY+<|4CeyWBl!l`2^G@v5y4Z&qU$Ys`{c6r* zVK|#+AUgPQKEB$BwGPX8xvTc9fgalqAv+7N4OaFI5fV)|cHpb3&q@&BD~GuVDwG_m z8-zo7CtOyB<~#Y`P@h?V@|~I0%M^G-?})dcK>q>?^o#GE83Bv?@?1;a)nG;NqZB=o z?&yaXpY>_p1C>YmItid7`9=rs3!yg`peQJtolx<;p=NQ*2O~qi@3xdxx3u_;`A@S5 z5?6J_u9yLAOqIC@_S&D(JUCx1(x)f<+(h3v?isO%=A`fiCg#_BOqX6{^u|@nm*{(I zQd4?I*h<0%z-3|g%vA8SySgJXi!g=BSihy>m_oCt5j?BRp8pQyhaXHJRj&JCd(fmw zkc~+&rjxLy#MD-z6{r9`z3_T6Nd;eF@iG&aRmLk0M6J!RIq9Mg90`cfdnK=C3e1sq!;EqnsWQ)B$xY zD5}N(@$f)7B~8$%icL=X)WPU#C%*$zAHbIYm|SM}zCwQULzkV~8ATX%QVv9gzk&*i z-y0|wA#GyA`~{FWwvLgmNtL)SMx}Q~jqZ(Kw_VR?Y)mm>*ZYl&@S<=1r3n>T|1S(L_+3FSssY9@F;hA@9Lq&ckFE*qOC(SI+C(T z5>T5uFn z3NR{V)qljV;YBr*ow@i3{dx}0@000yw)uGcu1P@RqgWKsQ0SGN{)M-w$8jE%ZMbG$sp94 zN*+QwWj%NM7;U$vtP@)M)Q+0z`z1{PeP_)_TbOxqjE`H!M`^M>{;@0Tn=qgFuRb8R z&%|>uL%2w$tfZHhw0cI)>xR>YWeq42)V zjV!lPP-AQeUNi)+#=L|heNIo`xsh#a8)tF>pg3&%t5WfGc4h;M)UKz+4r=427^JLP za5m?aY0KJdC$X^+RqlHJ3SH$!4R~N(;exNueXzFN^Uqs}iZ(r1li&o3G*%c6Zf5op{7}(dIL(X|k8-H(?F+&1Q zOcz~vHOeV#xy@hY!trq51wcq~T0{!k&6FcD?X*UmPV@{ZOivQHaW@?c3niaAZw<(%>>@a$>@S$4h9cuXAa`!QsKYcAuN;|V&)4v)a)GcgnEsq z4ZO9HnB6hg82~z^QI&3MsL^y%(|8FIcOhw2gBpRU4jNY$!Ilm2_VSM{mfQF(Zb4B3eNNZg#8( zZPmND>q|OqDQ8{xH~W<^HxOtVl)-->!9G>E$F@fBhc4{7sUq$l_u1V>zK=*%bXuTx z8=vjw>@!2lx|PEHVp56tH^He?VWTRqhi`NWAH%gRR5k4y)PF{BetOxvDg!#7ZQz?`kI&KkkUUP*JCnaBelQo)BhF^7g5KzJx+u_o%r z>FVoSuh~=;3M&YFq8(F_A`Qi-*_`Cl9%mF1old$#@$;`yN4mh}7=bSF8u-E}%cAdO zRhy4b+;z^_tH3zPh%f<>(ksA#S2$gMCTkApqXEFmEt4c&u}{$)u#Nt~GdGZ< z;gvqaz3PyS^t?z6${<5g)FFDUJWVd*!DGDaNayRcoo?IZeXu53c~>EqEj}nrQf4qS zlVn34v9>KqvR{x}CKgE(?8keSd4P^T5d8_eitWdC!o*f|kG)lLLy*+bQf}~`fSeZQ z$$;X`bBwxvHbbL0-<#zN)M91&gKDhhJ?|;@MwP)akY?;n3l_GLlKIn6QxX2y?w=vG z#{r?AjOBVr9U;8)Mk~|Y>o-ec zX83myYAvM^k+e%$e8l1VFCg*y8}y>oH*06GKPo-X33BuC)eKtSlj0YV!eYaHUmkD{`8t+w+I~DMPg^LZE>E%)j3>D z<`0}1=y&Z6`ym-$Ejm+18V;Uw;o-eBKh#4WR*@@hA8as88$bMQE`@JEE+r}RFHh{Y zq3`-U`fie*I$I=W_-WPo>HQ0qJ2Hn*%&pD|Y8HKiJ}wMH{bdSRMtRk^Zkh0Vu2T>^mmYLR#%*4svg5M0XB~paxlsOYaC_#6u(?|;aQgoff1?Ws@vff zqZlr{6;=6JZixAmh?VW=(ht0-uXrfN>nBau9E@Oc;{ zHIZoc-6~1Q{uBq{ZXk5O(Pwo_5bjW~aGrGNz5MD{i$h)yzoN$Si0B|)GH~O$`IgKh z?BX$}`%zq4g6m{RjU#T9U}$r=IfI$2R?x&+-|@dFv+1t^`K9=2h>-DM=-y?vMEG!i z5`Azfkl0zA$-auuy6~8(DJCcE4!mjFFiZxZ-;ZqsUgkx?rq*^>_OdE&lazm9$t`Ks ziED^38C!8NmjYA71aDEB1u^QvHLeG}AtH0VY7{U2>9B$(9qUGAt$85*L5>o6_l7ac zmtc?0QwI-{vyfdl+=}W0jMgZnd&zsjQ!1)>ISx>dyg5B8z0@_%Eb@sznAoYX<}W?+ z-129MU*H~)ascE=3A*2D{MFyx+lHwcf=NL7;v2Oc&KB>O`n(eo$!cj!wQc+E(W-R& z)5K^jZu*_5QfWhxh)ncIfuDQXs5m7KM2W6fmT7fkmvRJlPCJER58n3>WDioPPtxlo#xd%z-pZszh@RgY$ z-7g<3dSw4qJV&@D0*LV43Y~^UIuh~XlwY->=R-2E;tA|m&tOg`D9rI;iO7Qajr9dE zr&bR8F*k>6h%cX0_Tsv9b9wt(Zr(_0I7>vU;BhW;aJq53S~$);C?mQreW(I(B<6@W zOFM0i+kk~@4d}pm1#%N``Wg@(bi2KEph?Qg1$H{YOSz=miqq&hoH+;Rb4JB{-14b( zM{Mn>n^hDRb3wh`uYd*$5&iu~scT0YJ^KfRMTjV^E-==|xQ=&gxr#T|Hod|z2 zqX;7)P2risNP+{e!Ud)&>JS}MA#S>YS9& zx=0r0wqJBo$|L<@(Rbl7onwUF?7{Lc;PP!;Xr+q{`)0Z6pEW<3bdST`#AW@f zj0`68TFN1hX3}rl28faAlUqHxc>(|#^r>6dn;N{HxDm#jV~o(}7}*Y}3!e)_zOH6m z9_NpbTPToyaM@_!n{?{wtjisn;u+2|&+FZ-hBUcc6rb?E_71^d7E}jI@$T28^9$&@ zK+(Zlq$L%Xz_mWk8mpumR`(LQQSQvX%%@vw8db|HehR*0f~-GGGrnGH!;G~YnC56$ zDKuFf_He4w;zY7Dclou5uP^0I*gE_$3m40K_oi)Kj5)B1#!V~^O{ttUs8|x|I5Td! z1>E(WhqA)q1U5z{D8$C5s}*14cth?_*}wtz$D9zd!cKDUicI`S_Of`U@TGISFOo*p z@}A5zJV<+Qfk@S4)V5eG)QC>;tTba+f*_}dE(rWa!!d8ui$Cxf#^>Fa6dkKH&v^gZT-X7{gZvZvjR*y4>jpu~U2ga8Aj4M5oEYDvxK-ut zgdaOC0F>`>a2S2O+{Okyh?(&m^fv%5MzHt!ZAZkItzHpoOZ4`+z7+l}nkj;Bt&Amj z+Nw+N+`dfk(SWmL4B$OX4DsxhhKEZzKX3|uz{KzFs5O61@SKRYzIt}$jC;x;6wL*F z(-9fG#H@M#j7)fEglTX+<~LxZur&gNNX}4H7O2k>N{JGiV<)1Zd^2hWx80XQ!;sbs#j$6#v;c3Or#f|wZC^g}<63Ugs?tSdyiCux;zj#&E&PLjxug>E zd6DtD8rNXH_z@$k{BTIc&JNgyz)15ULKae57O&830yy|m%?Ie((d;3}Yk0E?4j%B0 zVc!0SLW){d_|oiPy3VT+61NPhP{#E(Ak3VPe|wCtcvr;%Is{n}V9e|s99u|HtSfb& zSMU7`SVyf__+^`RggMA>|9=#ngK6jwG_}B+ZHS|^xPBeS#c|6z7X_D3;;dk|5jCz$J@D;SV z$Xn~=Z&S7RRLThb0J;%Y(&{TY(OED5`%_R=$s%`;cb9Tz8WS_s3>|Hz@`>Nyy6>)~ ziJy+iaI&T?j8tG?(ZK@K**_rMaYF{|{gndXAnYxvA8AK=dvJ5jnOFthjAnu?0MNH% z4t0xR+WM1~)W>T}rjZJ<;55?EEOslIy(eiP=C9N)S7m&!48*9M3xUNa(3^3kJiU22 zUuncV!3*Ik`($@UP+Te#=(Wd8w|Em{qZo z0&Br$2MBRqOI*w8pxekweJJxVsO0dMyzMgy?!Es262rJBq0Hv3_Rsb}sen?$4J4`l zy4+?ACL2M&vd_~KD*{aybnMTT4woPUYWs^0YBX|k7n3b5`2@ZlYUp7tON`dz_>7u4FEz;0xw)`>f zS0f-p(x01|<2&zjgAZ=KCrdf^4H$Zp({7`R&_i2m@u{)q(?6wAUM0j+V_NbUR_A7` zmwL=0OOgzKa#pNy!XL()oK;fyKPuJruw;~r=FLb=T43@rZ2MFAT7B?EC91qOgo-MM zoN&@+zD%S+)YgucR7irUk+-m#@xvUWrASqiyY@Uip4apPKi*|70^0GX#g%B-(Q*a{ zFmZ(Ht021lIgjQPpajv>5UiHMI~AYrW>ufAQajFsWr(HRgJ;Nr~zSgxB^P zlax+aPgAy(u4x+`H$OT|&4FZ+5UI{Q`Q9JFVCVHHOpK=8ZbHbT+YG=9F&}v%3pq783^g{D7vaI z)K$nA3N(KdnJ3e~cTe$UZ_gr2sALBPWPN3yL0RRJ-5aj_>c@`KX%1qmJ<9_MkfcE{|; zKG}(8h%muiLtLwk>X)7@YGmE*0I6}1S8iumnOgSqo=-t@n8vT6qgD4P58*o zy0?b+!G9xdAQR%-Xao>e*CC6c7r263c)ntcj47rPyu`gAOSnLmL}==eu7r_bIc?zR*JkZ z%S>`b(r=gA)D8rTE*vXzMNF@U{Mh$B*@X)5aIvpE=LkwJXXy;D;RA$s$$GK(l}_6+ zL>X_<$>VF+8dh3j0qEt`(th)DpYM@^Q=pu}yZkTZ6_Ze{!|3E99;n^b!q7n24kYyX zj{8(C@3sPa-m+9KO zKh@7OBt5~Z%L)m+gB@c2XL~@f>npb!SJexnR(dWZ*OfAp3!%d)G;MDC}DF0t4MKFh=bEsJB9kzPX8t}4oyq%3vyINUC9)nkFs1e|$9 zkW2}XYGM`6hP+Krn@mt2Og)R@t<%dxGB(3sMnxkwnUG8!keBUCI9K)z1Cf5Z!-Bkw zY#%7gsHLgV6N<1HkZ;sv=(FD=&MQzGcD&6qtmgN(o+@n13w38LT=|!Oho?y3!%I}A zSM|I{aHB$kmd5t=YR&aXdj8seUg3cPKM?bWtU%0IJ}i%cooM&$Ece zgW6fIhO3$1iNz}btzYeioTCL8Na|z6&UBX_^lGq+YE#IDzq&xo&8Nsy%1e_llWWl3 zxtFu5etXFZ!nBCt-fUEi8@9X**IHw}8)nsg(>N!C+9K($Da`*{kpx_mqU%tW9SS&E zeE42{HG}dPPq;M1T(#}b0AUPHUJ(0oMV)y$_XEEC7PQY%GOamIWH9Y9QUKxlPT~VD zucp0mq(L200@#xjbk28}MEZsBatanB7F?B($B#s5qLPQGj3kt3g z?K8C(P*aO8NKFTY-!E7(RzL^r+)e!(Vy)H`t?@TLfu{KTJi!bFE~_OV7)U^(_+;!3%Gskc4TO(?x6n??sq79{*XD-5GVjnEl0dRuN zeF4=-Vwc=-L75k1#kLK<5Lc^hc!K0-@DNjE?ruz2ItQLgwZHx>yBGd@xVY$mw zKhqaz-LKn$uM=pF%hk#p%py4H`9!`*US(r#7y%SnCau^oN*%M`V?^)2ggcL_Nb1Oe z2aa39TF{qqJW3A-&T;2%0jMY*@#k}I(UlGuQ?8DZqwOZmGlIF&W{++4fR1*jqG6bl zPPwt&bpEtd$I)8`IQa)(j~wNR-)J)fSLRf5o}`T}{c?2YF0h>60{qRLK%0Sbf_yCw8c1E@ z!{szQuCy17)~asEzGIIV1R6xNSj;@U8Ix=^xLLR<+Eewdb-h@q4s%;-Oz8Q;S2cWh zyRXrjE86qADCF}0csLOmr3TZhU6R_Fd%eQS?CYnI<09Te1+50(F_b=?s`3v}Rq!F^ zT%=N}RD2V!hj8Si)j4|~Qrpd2DoC zg~<3c3aKpn+@q>LrAQ+u@y~PhOYTU-%z28~)^_`Oj<=VcfhAmjYM*mKXC9#+2s~ze zPh@7I@eS4ysdH1fApiwBzHQQX2k)9%x@PK7p7{6icFqtpbh_FP%GzXSXufin-i=D` zRW4z0tvM6?ds82%TnYs#(f0Nz)+{F91|qeeT-IpjSnLbyMRs8Uxs;fHQ(XxEA%VSP zsjw`C55MVoGcW@)0?K>#Hl0~|n?rBS1zCKA<(6js=T%yvUA~lm)u-zxGtz5z4A;Cm zXxXKA86_IkJ-K9O~jKx_M#3CdO+eOEjBo7N?L0g8c>Uf}h=L&6R0ZkSyj+!H=eZj?`I_CNj z#T9;TW6HIS43MD+X2qs z7#E5m>QYbdh|A3qe*4OGWo(FG@rnAot$6;K){52{w%Rm1XyvF@pK%}x<;D0_h1cSPTh$%*tiKIhez9Tv0v3nTdRR^5#ot=juEmkxVuJHK~+mpwLLRc}1Va-n^Zp=a64) z6?$dnzLhX3Kuci%oRd}oI}SF!@~q{X^oD~%9Y=$b zpl)Yi37zw#oiCy1>2t0J%RSzIH3;_v@ufw=GAKx;+*R|KZ_sXXVbkh#ja?F>+>)tYmFv|7YBl|Al zP#vy#;4KC?)|8iNdBkhfuBN4=;+R3HYyUlgZ>)Xru^Cw}T6ChI|;4H!^W!3khMn|c&NRHlH&(}&H3XB7)x#?ejN{<8+<%30Wuarsw&Qcia!nPi%DoifZG@39BPJ#VnoG35OP#J{h;A3qPg(lmeH+*$pR?qsw zlbCk})U5=p?EPPZH~0*U$1nlyLh&w#*|akcespc@XZafd*2vDh?x(Yqv2UrW*#>nQ z&_n~#bb%)O?(710ko5Ly&25#9j>nUwISx=-s9c{>0a8YDW<&c)s0n+I@a5jJB*i#S zcugX?nrnb1TQcYeYvs{Ix#C8TtXivc!2GwIiv2OA=VKfXGYsD-{L>ONn--Sa7Yt9P z2ztst=&j0o6rm`?^0{wB#?s?gUQr_pZ0}zFMu2FYo|@Q_x598wa_IHZE2U$gA;r3U zi%0a=*W$fPofEHk&d3NwTdWqz_0aM^353eGU<9GgIbE(;i(znB4R{xZycCuTlz5o* z(40Vv5v&~HPR+_l4YL-(^lbT#J_|2a3*b_$O?e1+FS=5eoR|B{4i3!8D;|R}=uYIk zHT;yDb(TI&}@&l3t`!`b65CL8y(Zq zp&l!~1bW+s#>uk92RioZXSlUZ^7%CR_)yd|mLX5O==LV@C;74EFBf)qp>Jmaa z$A!13*0IKvtd6&fs&&L*V?l><%I!HLB8|ZTPbRF*(UIH1S1y^#?)cq2#=P4JrHL+O zmQs>hub#VLxBMsHSo|X?^9)GPVBlWDR{>X#B2e zW*Zp$tBaP5Y3(}TI7fizyRch3>cIKg z?+OO0uFZ$!%^M;YY3mPgxf4CRgVgh5#Pj3fA#TFF&A&y;2t2Z8lo?%s<{=OBrX+G&<_kzjP8nBQ)@y%akA=Q>C&Q|z%yFS~O}pq3 z2OJ$HL3?d2DKDVK52jFz7z+#DBI+PE4d(a~6u(cupNdw*Bz60*TzW zKW_(r9+pO93$_=wouW6~be*c)V4Xra7OGp6gww#WNEf0gb~Tkvzd8$Z$p3 zOAoYk<+*OU@bnz`Il2l$dluvS3&}r&PWurrjm4+eA6#a)*F|5G_z3X@-MJ!OQ2N20 zoGw_GKI_B^yV9vD{);PLL*)gKnhO%}vM=CU5+q!Yng=jKOG$a=&w0gf7UUyF^7XEP zqFwgp3?s?YUc*Jav!Wchp}8#+D({=Pl;Oy7biIH4SiR&1`fH*`Q!LaltLMY+$!m0t zurKRNCWZsXe03Yc-sIv zSCa9YyRVF}el6r4JhpVWjo{k&?GKKPGC!Z~MzZH=F!{?6w>mKTP`|+_1`LzjThfjd zBjhb4TB&Skt5Vlf?R{9AMGnWucF+;L+=gX>_jqwD9Cs?b1}~E9e0UWle&<`8EPFQo^*ZG>&V-6{&-ZRLrlxI@*gd_y# z&7>0;g%hW(GUMN$qX_g6QZk&1-G1Y*7Woqh{_Otb%B=Zs-L4dWDWJxwb01w2 z%FmY4;f{|QXNit(X*VQ$nf%5wBy?JrQbxY&6XNBJJEV!YCTrFPWIsJ_>!FQhE@k(QnI48e`DO94=X<{G9em1PX$s~ zA(}QX55B)uwi%^NVjD#&OJUPSxmqC8@OfOe1D$VwA1QG0mkjDxDrTeId%WSMsznFa zBno;pgM9EGpbukp6}C>d^d#Syg~o4WpB=infBI!M&NOsW&Yt43#AEjJ`eRjicE0P^ zlizMn>L)t4XA}5Ob}aMGP+(o7b1y>?SXw#*EL7YgP2B4H#nwsd@}!CnHFLf;yc*fX z$OH7cD(wF9t*t)^CWG}@UrdNzX%2rW^qaooZ+n-|j6zu~2gb7r^LWSd~!^Ju~2BCz7;@o={17g63M1*R(d zM(8=$b-hHR!_M`0KJ%NlFNQv^?h;F4XOw8hyRRkyipk^bhBYTSv25vE^(S88CYGAC zm*cN2>!zM;RRyr%e=^m?I7M*;n}?~ub_y6;S>L7#1Bc}#*w>~~UJYw;=}cP(03*}!N_2t7ih^ZX1=G3!R7FjUYw;7kjg!>ciuDXZWA=7eJS5py9xnG z)&1LHR(~n*=1O5mv}o^^Pm4(?ed@{#F=#;|C%dvBJi-!&bWh0`KlfakD1W9a^0}f- zsud~2)~fI6Q~7iJMUy7^1uftG35mN(>9At2K~ZFE4Dlx8u52UfoDj+6>56;*N9d>Q-v^kgF4IX zOxQP59Xi=*NVds8Oi9d%;DKjj`ctMgA1Q&&^38pmpUt`cnDT0arL!OXNt4^QWJ=ov z(;WhO(W{XP9eT|Q)%0fZE3973dzqC|Enw3DqMFglp@73-uqij6sSMMCd@=(H4sk z^{|~UdlhMwCKQE?b+ij-pcn+v&Okzjs>&F+*w^Z3iv_;B>!@IwMxY};(^YPeic4NX zJvhXf5xO|(`^PKGQ!X40hgtA8O$Ew5J`&ZSYVK}QPs25bn7NYS+U|fWO)u0GE}(%5 z)7}vh3PtxMm@CytQ6}^OGa6xYUF>F^9mAc%BWvqOf01>g(nuD2!>}zNlcy{)>mlA$~`iXry|4tP5rg}r>R1B1HrGiq(|$2 zN^moI#X)PJDOMysx)|u@=tZ85IXj;3W#mK#mzS5@x~#y+c(V(x1KVuuG|IQ{Gr6ZW zv}4WZ!$&arNliZqDxHeYoDPE^x?N9oDA{Mq8}d{y!J&a+?_c%h3fy=D+ z;QpnVu9+vwRZ>@@u1<2$$enM|G;ocK_G!oJnjnGS$U1-I*B{CIKL}D@1((#R9q^~S zrw|*7GlIC(;B;Ywkr-+1^Q>_%x7=ES6s$biyN^1REzxOE3Nd$6hk1XN0Cg^1X1rU| z&@kHXpZt6SskGuFcDeoa|A|(pG&e@^nbG$4Xekwdw4D(%8cd5$buck;oy*U#1SQ`% zGG(6(H_Q<_wZ+ZNe%iHT?U#h03--2dZ4zyVK2$mDe~?um?i!paExY^0+ALj7^_rR; zP~@`7g*XrblbDOyY+H>ShhVd4%6N_A)+JE2xmpo10k4@=gUr{`W<+x{7eV|N(h`58 zz78(4!@c6YEZUWp*i!|}+|daYGt!xio>o-gIB;%86%%`=*CVV!nXqcshSpJWc zjdUOzy8D_NdVH>=IcAJ7l3VTxl>lTG#Jd=2MzPIgEIgQg13bOPVV5Bvsw?IL3wEBy z7Ao?g-on}Pa6+6dP%R5+ggi@8xbXS&w4=}Ed-ulj#^W%0A>x8ih7I|Tw=Z4_iGE}- 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�uZAH@s})VXr-b)-q~hxe1t$G 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 literal 0 HcmV?d00001 diff --git a/assets/images/bg_1.jpg b/assets/images/bg_1.jpg deleted file mode 100644 index 1b85b7f044f18bd670417a53098e89c04310c86e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141800 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�O1fp1B9Dy63coQ*8c#zdP0$og!P1wn}S>t;J?>l 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

    vRVF=;LHFHE>bg^!J0KXL(C+If*ncg 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

    b;9FLg{^fC^ku;JXWb@iVLnl)edp|V*{yf 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 L0KfkLArJrA6>rRn diff --git a/assets/images/bg_3.jpg b/assets/images/bg_3.jpg deleted file mode 100644 index 04be9fe72da1b4163b5da4f2990a85cc06047a17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137291 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 cI2k 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 diff --git a/client/index.js b/client/index.js index 48f04872..7f5c2c19 100644 --- a/client/index.js +++ b/client/index.js @@ -1,17 +1,4 @@ 'use strict' -let logic = document.documentElement.dataset.logic - -switch (logic) { - case 'error': - require('./scss/error.scss') - break - case 'login': - require('./scss/login.scss') - require('./js/login.js') - break - default: - require('./scss/app.scss') - require('./js/app.js') - break -} +require('./scss/app.scss') +require('./js/app.js') diff --git a/client/js/app.js b/client/js/app.js index 7c4b5899..00991909 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -1,28 +1,21 @@ 'use strict' -/* global $, siteRoot */ +/* global siteConfig */ /* eslint-disable no-new */ import Vue from 'vue' import VueResource from 'vue-resource' import VueClipboards from 'vue-clipboards' -import VueLodash from 'vue-lodash' import store from './store' -import io from 'socket-io-client' import i18next from 'i18next' import i18nextXHR from 'i18next-xhr-backend' import VueI18Next from '@panter/vue-i18next' -import 'jquery-contextmenu' -import 'jquery-simple-upload' -import 'jquery-smooth-scroll' -import 'jquery-sticky' // ==================================== // Load Helpers // ==================================== import helpers from './helpers' -import _ from './helpers/lodash' // ==================================== // Load Vue Components @@ -63,7 +56,6 @@ import sourceViewComponent from './pages/source-view.component.js' Vue.use(VueResource) Vue.use(VueClipboards) Vue.use(VueI18Next) -Vue.use(VueLodash, _) Vue.use(helpers) // ==================================== @@ -105,39 +97,27 @@ i18next .use(i18nextXHR) .init({ backend: { - loadPath: siteRoot + '/js/i18n/{{lng}}.json' + loadPath: siteConfig.path + '/js/i18n/{{lng}}.json' }, - lng: siteLang, - fallbackLng: siteLang + lng: siteConfig.lang, + fallbackLng: siteConfig.lang }) -$(() => { +document.addEventListener('DOMContentLoaded', ev => { // ==================================== // Notifications // ==================================== - $(window).bind('beforeunload', () => { + window.addEventListener('beforeunload', () => { store.dispatch('startLoading') }) - $(document).ajaxSend(() => { - store.dispatch('startLoading') - }).ajaxComplete(() => { - store.dispatch('stopLoading') - }) - - // ==================================== - // Establish WebSocket connection - // ==================================== - - let socket = io(window.location.origin) - window.socket = socket // ==================================== // Bootstrap Vue // ==================================== const i18n = new VueI18Next(i18next) - window.wikijs = new Vue({ + window.wiki = new Vue({ mixins: [helpers], components: {}, store, @@ -151,9 +131,7 @@ $(() => { } }, mounted() { - $('a:not(.toc-anchor)').smoothScroll({ speed: 500, offset: -50 }) - $('#header').sticky({ topSpacing: 0 }) - $('.sidebar-pagecontents').sticky({ topSpacing: 15, bottomSpacing: 75 }) + } }) }) diff --git a/client/js/app.old.js b/client/js/app.old.js new file mode 100644 index 00000000..fc69cfc3 --- /dev/null +++ b/client/js/app.old.js @@ -0,0 +1,153 @@ +'use strict' + +/* global $, siteConfig */ +/* eslint-disable no-new */ + +import Vue from 'vue' +import VueResource from 'vue-resource' +import VueClipboards from 'vue-clipboards' +import VueLodash from 'vue-lodash' +import store from './store' +import i18next from 'i18next' +import i18nextXHR from 'i18next-xhr-backend' +import VueI18Next from '@panter/vue-i18next' +import 'jquery-contextmenu' +import 'jquery-simple-upload' +import 'jquery-smooth-scroll' +import 'jquery-sticky' + +// ==================================== +// Load Helpers +// ==================================== + +import helpers from './helpers' +import _ from './helpers/lodash' + +// ==================================== +// Load Vue Components +// ==================================== + +import alertComponent from './components/alert.vue' +import anchorComponent from './components/anchor.vue' +import colorPickerComponent from './components/color-picker.vue' +import editorCodeblockComponent from './components/editor-codeblock.vue' +import editorFileComponent from './components/editor-file.vue' +import editorVideoComponent from './components/editor-video.vue' +import historyComponent from './components/history.vue' +import loadingSpinnerComponent from './components/loading-spinner.vue' +import modalCreatePageComponent from './components/modal-create-page.vue' +import modalCreateUserComponent from './components/modal-create-user.vue' +import modalDeleteUserComponent from './components/modal-delete-user.vue' +import modalDiscardPageComponent from './components/modal-discard-page.vue' +import modalMovePageComponent from './components/modal-move-page.vue' +import modalProfile2faComponent from './components/modal-profile-2fa.vue' +import modalUpgradeSystemComponent from './components/modal-upgrade-system.vue' +import pageLoaderComponent from './components/page-loader.vue' +import searchComponent from './components/search.vue' +import toggleComponent from './components/toggle.vue' +import treeComponent from './components/tree.vue' + +import adminEditUserComponent from './pages/admin-edit-user.component.js' +import adminProfileComponent from './pages/admin-profile.component.js' +import adminSettingsComponent from './pages/admin-settings.component.js' +import adminThemeComponent from './pages/admin-theme.component.js' +import contentViewComponent from './pages/content-view.component.js' +import editorComponent from './components/editor.component.js' +import sourceViewComponent from './pages/source-view.component.js' + +// ==================================== +// Initialize Vue Modules +// ==================================== + +Vue.use(VueResource) +Vue.use(VueClipboards) +Vue.use(VueI18Next) +Vue.use(VueLodash, _) +Vue.use(helpers) + +// ==================================== +// Register Vue Components +// ==================================== + +Vue.component('alert', alertComponent) +Vue.component('adminEditUser', adminEditUserComponent) +Vue.component('adminProfile', adminProfileComponent) +Vue.component('adminSettings', adminSettingsComponent) +Vue.component('adminTheme', adminThemeComponent) +Vue.component('anchor', anchorComponent) +Vue.component('colorPicker', colorPickerComponent) +Vue.component('contentView', contentViewComponent) +Vue.component('editor', editorComponent) +Vue.component('editorCodeblock', editorCodeblockComponent) +Vue.component('editorFile', editorFileComponent) +Vue.component('editorVideo', editorVideoComponent) +Vue.component('history', historyComponent) +Vue.component('loadingSpinner', loadingSpinnerComponent) +Vue.component('modalCreatePage', modalCreatePageComponent) +Vue.component('modalCreateUser', modalCreateUserComponent) +Vue.component('modalDeleteUser', modalDeleteUserComponent) +Vue.component('modalDiscardPage', modalDiscardPageComponent) +Vue.component('modalMovePage', modalMovePageComponent) +Vue.component('modalProfile2fa', modalProfile2faComponent) +Vue.component('modalUpgradeSystem', modalUpgradeSystemComponent) +Vue.component('pageLoader', pageLoaderComponent) +Vue.component('search', searchComponent) +Vue.component('sourceView', sourceViewComponent) +Vue.component('toggle', toggleComponent) +Vue.component('tree', treeComponent) + +// ==================================== +// Load Localization strings +// ==================================== + +i18next + .use(i18nextXHR) + .init({ + backend: { + loadPath: siteConfig.path + '/js/i18n/{{lng}}.json' + }, + lng: siteConfig.lang, + fallbackLng: siteConfig.lang + }) + +$(() => { + // ==================================== + // Notifications + // ==================================== + + $(window).bind('beforeunload', () => { + store.dispatch('startLoading') + }) + $(document).ajaxSend(() => { + store.dispatch('startLoading') + }).ajaxComplete(() => { + store.dispatch('stopLoading') + }) + + // ==================================== + // Bootstrap Vue + // ==================================== + + const i18n = new VueI18Next(i18next) + if (document.querySelector('#root')) { + window.wikijs = new Vue({ + mixins: [helpers], + components: {}, + store, + i18n, + el: '#root', + methods: { + changeTheme(opts) { + this.$el.className = `has-stickynav is-primary-${opts.primary} is-alternate-${opts.alt}` + this.$refs.header.className = `nav is-${opts.primary}` + this.$refs.footer.className = `footer is-${opts.footer}` + } + }, + mounted() { + $('a:not(.toc-anchor)').smoothScroll({ speed: 500, offset: -50 }) + $('#header').sticky({ topSpacing: 0 }) + $('.sidebar-pagecontents').sticky({ topSpacing: 15, bottomSpacing: 75 }) + } + }) + } +}) diff --git a/client/js/helpers/index.js b/client/js/helpers/index.js index 6f802e8b..6335809b 100644 --- a/client/js/helpers/index.js +++ b/client/js/helpers/index.js @@ -1,6 +1,7 @@ 'use strict' const helpers = { + _: require('./lodash'), common: require('./common'), form: require('./form'), pages: require('./pages') diff --git a/client/js/login.js b/client/js/login.js deleted file mode 100644 index 892e3306..00000000 --- a/client/js/login.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' - -/* global $ */ - -$(() => { - $('#login-user').focus() -}) diff --git a/client/scss/app.scss b/client/scss/app.scss index 8bf44dd7..fc68ef23 100644 --- a/client/scss/app.scss +++ b/client/scss/app.scss @@ -42,6 +42,7 @@ $primary: 'indigo'; @import 'layout/_header'; @import 'layout/_loader'; -@import 'pages/_welcome'; +@import 'pages/login'; +@import 'pages/welcome'; @import 'base/print'; diff --git a/client/scss/components/button.scss b/client/scss/components/button.scss index 97338a0e..c53754a3 100644 --- a/client/scss/components/button.scss +++ b/client/scss/components/button.scss @@ -4,7 +4,7 @@ border: 1px solid mc('orange','700'); border-radius: 3px; display: inline-flex; - height: 30px; + height: 40px; align-items: center; padding: 0 15px; font-size: 13px; @@ -74,7 +74,13 @@ &.is-featured { animation: btnInvertedPulse .6s ease alternate infinite; - } + } + + &.is-fullwidth { + width: 100%; + text-align: center; + justify-content: center; + } &.is-disabled, &:disabled { background-color: mc('grey', '300'); diff --git a/client/scss/pages/_login.scss b/client/scss/pages/_login.scss index abfd9c93..284bf7f6 100644 --- a/client/scss/pages/_login.scss +++ b/client/scss/pages/_login.scss @@ -1,306 +1,161 @@ - -body { - padding: 0; - margin: 0; - font-family: $core-font-standard; - font-size: 14px; -} - -a { - color: #FFF; - transition: color 0.4s ease; - text-decoration: none; - - &:hover { - color: mc('orange','600'); - text-decoration: underline; - } - -} - -#bg { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1; - background-color: #000; - - > div { - background-size: cover; - background-position: center center; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - opacity: 0; - visibility: hidden; - transition: opacity 3s ease, visibility 3s; - animation: bg 30s linear infinite; - - &:nth-child(1) { - animation-delay: 10s; - } - - &:nth-child(2) { - animation-delay: 20s; - } - - } - -} - -#root { - position: fixed; - top: 15vh; - left: 10vw; - z-index: 2; - color: #FFF; - display: flex; - flex-direction: column; - - h1 { - font-size: 4rem; - font-weight: bold; - color: #FFF; - padding: 0; - margin: 0; - animation: headerIntro 3s ease; - } - - h2 { - font-size: 1.5rem; - font-weight: normal; - color: rgba(255,255,255,0.7); - padding: 0; - margin: 0 0 25px 0; - animation: headerIntro 3s ease; - } - - h3 { - font-size: 1.25rem; - font-weight: normal; - color: #FB8C00; - padding: 0; - margin: 0; - animation: shake 1s ease; - - > .fa { - margin-right: 7px; - } - - } - - h4 { - font-size: 0.8rem; - font-weight: normal; - color: rgba(255,255,255,0.7); - padding: 0; - margin: 0 0 15px 0; - animation: fadeIn 3s ease; - } - - form { - display: flex; - flex-direction: column; - } - - input[type=text], input[type=password] { - width: 350px; - max-width: 80vw; - border: 1px solid rgba(255,255,255,0.3); - border-radius: 3px; - background-color: rgba(0,0,0,0.2); - padding: 0 15px; - height: 40px; - margin: 0 0 10px 0; - color: #FFF; - font-weight: bold; - font-size: 14px; - transition: all 0.4s ease; - - &:focus { - outline: none; - border-color: mc('orange','600'); - } - - } - - button { - background-color: mc('orange','600'); - color: #FFF; - border: 1px solid lighten(mc('orange','600'), 10%); - border-radius: 3px; - height: 40px; - width: 125px; - padding: 0; - font-weight: bold; - margin: 15px 0 0 0; - transition: all 0.4s ease; - cursor: pointer; - - span { - font-weight: bold; - } - - &:focus { - outline: none; - border-color: #FFF; - } - - &:hover { - background-color: darken(mc('orange','600'), 10%); - } - - } - - #social { - margin-top: 25px; - - > span { - display: block; - font-weight: bold; - color: rgba(255,255,255,0.7); - } - - button { - margin-right: 5px; - width: auto; - padding: 0 15px; - - > i { - margin-right: 10px; - font-size: 16px; - } - - &.ms { - background-color: mc('blue','600'); - border-color: lighten(mc('blue','600'), 10%); - - &:focus { - border-color: #FFF; - } - - &:hover { - background-color: darken(mc('blue','600'), 10%); - } - - } - - &.google { - background-color: mc('light-blue','600'); - border-color: lighten(mc('light-blue','600'), 10%); - - &:focus { - border-color: #FFF; - } - - &:hover { - background-color: darken(mc('light-blue','600'), 10%); - } - - } - - &.facebook { - background-color: mc('indigo','600'); - border-color: lighten(mc('indigo','600'), 10%); - - &:focus { - border-color: #FFF; - } - - &:hover { - background-color: darken(mc('indigo','600'), 10%); - } - - } - - &.github { - background-color: mc('blue-grey','700'); - border-color: lighten(mc('blue-grey','700'), 10%); - - &:focus { - border-color: #FFF; - } - - &:hover { - background-color: darken(mc('blue-grey','700'), 10%); - } - } - - &.slack { - background-color: mc('purple','700'); - border-color: lighten(mc('purple','700'), 10%); - - &:focus { - border-color: #FFF; - } - - &:hover { - background-color: darken(mc('purple','700'), 10%); - } - } - - } - - } - -} - -#copyright { - display: flex; - align-items: center; - justify-content: flex-start; - position: absolute; - left: 10vw; - bottom: 10vh; - z-index: 2; - color: rgba(255,255,255,0.5); - font-weight: bold; - - .icon { - font-size: 1.2rem; - margin: 0 8px; - } - - a { - opacity: 0.75; - } - -} - -@include keyframes(bg) { - 0% { - @include prefix(transform, scale(1,1)); - visibility: visible; - opacity: 0; - }, - 5% { - opacity: 0.5; - }, - 33% { - opacity: 0.5; - }, - 38% { - @include prefix(transform, scale(1.2, 1.2)); - opacity: 0; - }, - 39% { - visibility: hidden; - } - 100% { - visibility: hidden; - opacity: 0; - } -} - -@include keyframes(headerIntro) { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } +.login { + background-size: cover; + background-position: center center; + background-image: url('../images/bg.jpg'); + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + + &-container { + display: flex; + width: 650px; + align-items: stretch; + box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); + } + + &-providers { + display: flex; + flex-direction: column; + width: 200px; + border: 1px solid #FFF; + background-color: mc('grey', '900'); + z-index: 1; + + button { + flex: 1 1; + padding: 0 15px; + border: none; + color: #FFF; + background-color: mc('grey', '800'); + border-top: 1px solid mc('grey', '900'); + font-family: $core-font-standard; + font-weight: 600; + text-align: left; + min-height: 40px; + + &:first-child { + border-top: none; + } + + &.is-active { + background-color: mc('grey', '100'); + background-image: radial-gradient(circle at top left, rgba(mc('grey', '200'),1) 0%,rgba(255,255,255,1) 100%); + color: mc('grey', '700'); + } + + i { + margin-right: 10px; + font-size: 16px; + } + + span { + font-weight: 600; + } + } + } + + &-frame { + background-image: radial-gradient(circle at top left, rgba(255,255,255,1) 0%,rgba(240,240,240,.6) 100%); + border: 1px solid #FFF; + width: 450px; + padding: 1rem; + color: mc('grey', '700'); + display: flex; + justify-content: center; + flex-direction: column; + text-align: center; + + h1 { + font-size: 2rem; + font-weight: 600; + color: mc('grey', '700'); + padding: 0; + margin: 0; + } + + h2 { + font-size: 1.5rem; + font-weight: 300; + color: mc('grey', '700'); + padding: 0; + margin: 0 0 25px 0; + } + + h3 { + font-size: 1.25rem; + font-weight: normal; + color: #FB8C00; + padding: 0; + margin: 0; + animation: shake 1s ease; + + > .fa { + margin-right: 7px; + } + + } + + h4 { + font-size: .8rem; + font-weight: normal; + color: rgba(255,255,255,0.7); + padding: 0; + margin: 0 0 15px 0; + animation: fadeIn 3s ease; + } + + form { + display: flex; + flex-direction: column; + } + + input[type=text], input[type=password] { + width: 100%; + border: 1px solid #FFF; + border-radius: 3px; + background-color: rgba(255,255,255,.7); + padding: 0 15px; + height: 40px; + margin: 0 0 10px 0; + color: mc('grey', '700'); + font-weight: 600; + font-size: .8rem; + transition: all 0.4s ease; + text-align: center; + + &:focus { + outline: none; + border-color: mc('grey','400'); + } + + } + + } + + &-copyright { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + left: 0; + bottom: 10vh; + width: 100%; + z-index: 2; + color: #FFF; + font-weight: 400; + text-shadow: 1px 1px 0 #000; + + .icon { + font-size: 1.2rem; + margin: 0 8px; + } + + a { + font-weight: 600; + color: #FFF; + } + + } } diff --git a/package.json b/package.json index 7545f72b..7e27ce96 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "axios": "0.16.2", "bcryptjs-then": "1.0.1", "bluebird": "3.5.0", - "body-parser": "1.17.2", - "bull": "3.0.0", + "body-parser": "1.18.0", + "bull": "3.1.0", "bunyan": "1.8.12", "cheerio": "1.0.0-rc.2", "child-process-promise": "2.2.1", @@ -63,7 +63,7 @@ "follow-redirects": "1.2.4", "fs-extra": "4.0.1", "git-wrapper2-promise": "0.2.9", - "graphql": "0.11.2", + "graphql": "0.11.3", "graphql-tools": "1.2.2", "highlight.js": "9.12.0", "i18next": "9.0.0", @@ -73,7 +73,7 @@ "ioredis": "3.1.4", "jimp": "0.2.28", "js-yaml": "3.9.1", - "jsonwebtoken": "7.4.3", + "jsonwebtoken": "8.0.0", "klaw": "2.1.0", "levelup": "1.3.9", "lodash": "4.17.4", @@ -88,7 +88,7 @@ "markdown-it-mathjax": "2.0.0", "markdown-it-task-lists": "2.0.1", "mathjax-node": "1.2.0", - "memdown": "1.2.4", + "memdown": "1.2.7", "mime-types": "2.1.17", "moment": "2.18.1", "moment-timezone": "0.5.13", @@ -108,24 +108,24 @@ "passport.socketio": "3.7.0", "pg": "7.3.0", "pg-hstore": "2.3.2", - "pg-promise": "6.5.1", + "pg-promise": "6.5.2", "pm2": "2.6.1", - "pug": "2.0.0-rc.3", + "pug": "2.0.0-rc.4", "read-chunk": "2.1.0", "remove-markdown": "0.2.2", "request": "2.81.0", "search-index-adder": "0.3.9", "search-index-searcher": "0.2.10", "semver": "5.4.1", - "sequelize": "4.8.0", + "sequelize": "4.8.2", "serve-favicon": "2.4.3", "simplemde": "1.11.2", "socket.io": "2.0.3", - "stopword": "0.1.6", + "stopword": "0.1.7", "stream-to-promise": "2.2.0", "tar": "4.0.1", "through2": "2.0.3", - "validator": "8.1.0", + "validator": "8.2.0", "validator-as-promised": "1.0.2", "winston": "2.3.1", "yargs": "8.0.2" @@ -134,7 +134,7 @@ "@glimpse/glimpse": "0.22.15", "@panter/vue-i18next": "0.5.1", "babel-cli": "6.26.0", - "babel-jest": "21.0.0", + "babel-jest": "21.0.2", "babel-plugin-transform-object-assign": "6.22.0", "babel-preset-es2015": "6.24.1", "brace": "0.10.0", @@ -146,18 +146,18 @@ "eslint-plugin-node": "5.1.1", "eslint-plugin-promise": "3.5.0", "eslint-plugin-standard": "3.0.1", - "fuse-box": "2.2.3", + "fuse-box": "^2.2.31", "i18next-xhr-backend": "1.4.2", - "jest": "21.0.0", + "jest": "21.0.2", "jquery": "3.2.1", - "jquery-contextmenu": "2.5.0", + "jquery-contextmenu": "2.6.2", "jquery-simple-upload": "1.0.0", "jquery-smooth-scroll": "2.2.0", "jquery-sticky": "1.0.4", "lodash-cli": "4.17.4", "lodash-es": "4.17.4", "node-sass": "4.5.3", - "nodemon": "1.11.0", + "nodemon": "1.12.0", "pug-lint": "2.5.0", "twemoji-awesome": "1.0.6", "typescript": "2.5.2", diff --git a/server/master.js b/server/master.js index 85754011..844eee05 100644 --- a/server/master.js +++ b/server/master.js @@ -136,10 +136,10 @@ module.exports = Promise.join( // ---------------------------------------- app.locals._ = require('lodash') - app.locals.t = wiki.lang.t.bind(wiki.config.site.lang) + app.locals.t = wiki.lang.t.bind(wiki.lang) app.locals.moment = require('moment') app.locals.moment.locale(wiki.config.site.lang) - app.locals.appconfig = wiki.config + app.locals.config = wiki.config app.use(mw.flash) // ---------------------------------------- diff --git a/server/modules/config.js b/server/modules/config.js index 334fba3c..5884b8cf 100644 --- a/server/modules/config.js +++ b/server/modules/config.js @@ -47,11 +47,11 @@ module.exports = { appconfig.port = process.env.PORT || 80 } - // Convert booleans + // Convert booleans - appconfig.public = (appconfig.public === true || _.toLower(appconfig.public) === 'true') + appconfig.public = (appconfig.public === true || _.toLower(appconfig.public) === 'true') - // List authentication strategies + // List authentication strategies wiki.config = appconfig wiki.data = appdata }, diff --git a/server/views/auth/login.pug b/server/views/auth/login.pug index ad860349..14105179 100644 --- a/server/views/auth/login.pug +++ b/server/views/auth/login.pug @@ -1,75 +1,54 @@ -doctype html -html(data-logic='login') - head - meta(http-equiv='X-UA-Compatible', content='IE=edge') - meta(charset='UTF-8') - meta(name='viewport', content='width=device-width, initial-scale=1') - meta(name='theme-color', content='#009688') - meta(name='msapplication-TileColor', content='#009688') - meta(name='msapplication-TileImage', content='/favicons/ms-icon-144x144.png') - title= appconfig.title - - // Favicon - each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180] - link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href='/favicons/apple-icon-' + favsize + 'x' + favsize + '.png') - link(rel='icon', type='image/png', sizes='192x192', href='/favicons/android-icon-192x192.png') - each favsize in [32, 96, 16] - link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href='/favicons/favicon-' + favsize + 'x' + favsize + '.png') - link(rel='manifest', href='/manifest.json') - - // JS / CSS - script(type='text/javascript', src=appconfig.host + '/js/vendor.js') - script(type='text/javascript', src=appconfig.host + '/js/app.js') +extends ../master.pug +block body body - #bg - each bg in _.sampleSize([1, 2, 3],3) - div(style='background-image:url(/images/bg_' + bg + '.jpg);') - #root - h1= appconfig.title - h2= t('auth:loginrequired') - if appflash.length > 0 - h3 - i.icon-warning-outline - = appflash[0].title - h4= appflash[0].message - if appconfig.auth.local.enabled - form(method='post', action='/login') - input#login-user(type='text', name='email', placeholder=t('auth:fields.emailuser')) - input#login-pass(type='password', name='password', placeholder=t('auth:fields.password')) - button(type='submit')= t('auth:actions.login') - if appconfig.authStrategies.socialEnabled - #social - if appconfig.auth.local.enabled - span= t('auth:loginusingalt') - else - span= t('auth:loginusing') - if appconfig.auth.microsoft && appconfig.auth.microsoft.enabled - button.ms(onclick='window.location.assign("/login/ms")') - i.icon-windows2 - span= t('auth:providers.windowslive') - if appconfig.auth.azure && appconfig.auth.azure.enabled - button.ms(onclick='window.location.assign("/login/azure")') - i.icon-windows2 - span= t('auth:providers.azure') - if appconfig.auth.google && appconfig.auth.google.enabled - button.google(onclick='window.location.assign("/login/google")') - i.icon-google - span= t('auth:providers.google') - if appconfig.auth.facebook && appconfig.auth.facebook.enabled - button.facebook(onclick='window.location.assign("/login/facebook")') - i.icon-facebook - span= t('auth:providers.facebook') - if appconfig.auth.github && appconfig.auth.github.enabled - button.github(onclick='window.location.assign("/login/github")') - i.icon-github - span= t('auth:providers.github') - if appconfig.auth.slack && appconfig.auth.slack.enabled - button.slack(onclick='window.location.assign("/login/slack")') - i.icon-slack - span= t('auth:providers.slack') - #copyright - = t('footer.poweredby') + ' ' - a.icon(href='https://github.com/Requarks/wiki') - i.icon-github - a(href='https://wiki.requarks.io/') Wiki.js + .login#root + .login-container + if config.authStrategies.socialEnabled + .login-providers + button.is-active(onclick='window.location.assign("/login/ms")') + i.nc-icon-outline.ui-1_database + span= t('auth:providers.local') + if config.auth.microsoft && config.auth.microsoft.enabled + button(onclick='window.location.assign("/login/ms")') + i.icon-windows2 + span= t('auth:providers.windowslive') + if config.auth.azure && config.auth.azure.enabled + button(onclick='window.location.assign("/login/azure")') + i.icon-windows2 + span= t('auth:providers.azure') + if config.auth.google && config.auth.google.enabled + button(onclick='window.location.assign("/login/google")') + i.icon-google + span= t('auth:providers.google') + if config.auth.facebook && config.auth.facebook.enabled + button(onclick='window.location.assign("/login/facebook")') + i.icon-facebook + span= t('auth:providers.facebook') + if config.auth.github && config.auth.github.enabled + button(onclick='window.location.assign("/login/github")') + i.icon-github + span= t('auth:providers.github') + if config.auth.slack && config.auth.slack.enabled + button(onclick='window.location.assign("/login/slack")') + i.icon-slack + span= t('auth:providers.slack') + .login-frame + h1= config.site.title + h2= t('auth:loginrequired') + if appflash.length > 0 + h3 + i.icon-warning-outline + = appflash[0].title + h4= appflash[0].message + if config.auth.local.enabled + form(method='post', action='/login') + input#login-user(type='text', name='email', placeholder=t('auth:fields.emailuser')) + input#login-pass(type='password', name='password', placeholder=t('auth:fields.password')) + button.button.is-light-green.is-fullwidth(type='submit') + span= t('auth:actions.login') + .login-copyright + = t('footer.poweredby') + ' ' + a.icon(href='https://github.com/Requarks/wiki') + i.icon-github + a(href='https://wiki.requarks.io/') Wiki.js diff --git a/server/views/error.pug b/server/views/error.pug index 3ef6c43f..51b53efe 100644 --- a/server/views/error.pug +++ b/server/views/error.pug @@ -1,32 +1,12 @@ -doctype html -html(data-logic='error') - head - meta(http-equiv='X-UA-Compatible', content='IE=edge') - meta(charset='UTF-8') - meta(name='viewport', content='width=device-width, initial-scale=1') - meta(name='theme-color', content='#009688') - meta(name='msapplication-TileColor', content='#009688') - meta(name='msapplication-TileImage', content=appconfig.host + '/favicons/ms-icon-144x144.png') - title= appconfig.title - - // Favicon - each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180] - link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/apple-icon-' + favsize + 'x' + favsize + '.png') - link(rel='icon', type='image/png', sizes='192x192', href=appconfig.host + '/favicons/android-icon-192x192.png') - each favsize in [32, 96, 16] - link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/favicon-' + favsize + 'x' + favsize + '.png') - link(rel='manifest', href=appconfig.host + '/manifest.json') - - // JS / CSS - script(type='text/javascript', src=appconfig.host + '/js/vendor.js') - script(type='text/javascript', src=appconfig.host + '/js/app.js') +extends ./master.pug +block body body(class='is-error') .container - a(href='/'): img(src=appconfig.host + '/images/logo.png') + a(href='/'): img(src=config.site.path + '/images/logo.png') h1= message h2= t('errors:generic') - a.button.is-amber.is-inverted.is-featured(href=appconfig.host + '/')= t('errors:actions.gohome') + a.button.is-amber.is-inverted.is-featured(href=config.site.path+ '/')= t('errors:actions.gohome') if error.stack h3= t('errors:debugmsg') diff --git a/server/views/layout.pug b/server/views/layout.pug index 4e0f0a9f..49d4747a 100644 --- a/server/views/layout.pug +++ b/server/views/layout.pug @@ -1,33 +1,6 @@ -doctype html -html - head - meta(http-equiv='X-UA-Compatible', content='IE=edge') - meta(charset='UTF-8') - meta(name='viewport', content='width=device-width, initial-scale=1') - meta(name='theme-color', content='#009688') - meta(name='msapplication-TileColor', content='#009688') - meta(name='msapplication-TileImage', content=appconfig.host + '/favicons/ms-icon-144x144.png') - title= appconfig.title - - //- Favicon - each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180] - link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/apple-icon-' + favsize + 'x' + favsize + '.png') - link(rel='icon', type='image/png', sizes='192x192', href=appconfig.host + '/favicons/android-icon-192x192.png') - each favsize in [32, 96, 16] - link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=appconfig.host + '/favicons/favicon-' + favsize + 'x' + favsize + '.png') - link(rel='manifest', href=appconfig.host + '/manifest.json') - - //- Site Lang - script. - var siteLang = '!{appconfig.lang}'; - var siteRoot = '!{appconfig.host}'; - - //- JS / CSS - script(type='text/javascript', src=appconfig.host + '/js/vendor.js') - script(type='text/javascript', src=appconfig.host + '/js/app.js') - - block head +extends ./master.pug +block body body #root.has-stickynav(class=['is-primary-' + appconfig.theme.primary, 'is-alternate-' + appconfig.theme.alt]) include ./common/header.pug diff --git a/server/views/master.pug b/server/views/master.pug new file mode 100644 index 00000000..e924fd32 --- /dev/null +++ b/server/views/master.pug @@ -0,0 +1,30 @@ +doctype html +html + head + meta(http-equiv='X-UA-Compatible', content='IE=edge') + meta(charset='UTF-8') + meta(name='viewport', content='width=device-width, initial-scale=1') + meta(name='theme-color', content='#009688') + meta(name='msapplication-TileColor', content='#009688') + meta(name='msapplication-TileImage', content=config.site.path + '/favicons/ms-icon-144x144.png') + title= config.title + + //- Favicon + each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180] + link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=config.site.path + '/favicons/apple-icon-' + favsize + 'x' + favsize + '.png') + link(rel='icon', type='image/png', sizes='192x192', href=config.site.path + '/favicons/android-icon-192x192.png') + each favsize in [32, 96, 16] + link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=config.site.path + '/favicons/favicon-' + favsize + 'x' + favsize + '.png') + link(rel='manifest', href=config.site.path + '/manifest.json') + + //- Site Lang + script. + var siteConfig = !{JSON.stringify(config.site)} + + //- JS / CSS + script(type='text/javascript', src=config.site.path + '/js/vendor.js') + script(type='text/javascript', src=config.site.path + '/js/app.js') + + block head + + block body diff --git a/tools/fuse.js b/tools/fuse.js index 9fc79274..ef404827 100644 --- a/tools/fuse.js +++ b/tools/fuse.js @@ -126,7 +126,8 @@ globalTasks.then(() => { switch (mode) { case 'dev': - bundleApp.watch() + bundleApp.hmr().watch() + fuse.dev({ httpServer: false }) break case 'dev-configure': bundleSetup.watch() diff --git a/yarn.lock b/yarn.lock index 5d936277..0a625c96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -133,7 +133,13 @@ abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" -abstract-leveldown@2.4.1, abstract-leveldown@~2.4.0: +abstract-leveldown@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.4.1.tgz#b3bfedb884eb693a12775f0c55e9f0a420ccee64" dependencies: @@ -256,6 +262,12 @@ amp@0.3.1, amp@~0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/amp/-/amp-0.3.1.tgz#6adf8d58a74f361e82c1fa8d389c079e139fc47d" +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + dependencies: + string-width "^2.0.0" + ansi-escape-sequences@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-escape-sequences/-/ansi-escape-sequences-3.0.0.tgz#1c18394b6af9b76ff9a63509fa497669fd2ce53e" @@ -270,6 +282,10 @@ ansi-escapes@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" +ansi-escapes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -447,6 +463,10 @@ assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -689,12 +709,12 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@21.0.0, babel-jest@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.0.0.tgz#4f636a7dce105aa5753d5f3dde4422ff50c1d6c5" +babel-jest@21.0.2, babel-jest@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.0.2.tgz#817ea52c23f1c6c4b684d6960968416b6a9e9c6c" dependencies: babel-plugin-istanbul "^4.0.0" - babel-preset-jest "^21.0.0" + babel-preset-jest "^21.0.2" babel-messages@^6.23.0: version "6.23.0" @@ -716,9 +736,9 @@ babel-plugin-istanbul@^4.0.0: istanbul-lib-instrument "^1.7.2" test-exclude "^4.1.1" -babel-plugin-jest-hoist@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.0.0.tgz#aa2dbab7b0d58fa635640efd53aab730be7b3273" +babel-plugin-jest-hoist@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.0.2.tgz#cfdce5bca40d772a056cb8528ad159c7bb4bb03d" babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" @@ -952,11 +972,11 @@ babel-preset-es2015@6.24.1: babel-plugin-transform-es2015-unicode-regex "^6.24.1" babel-plugin-transform-regenerator "^6.24.1" -babel-preset-jest@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.0.0.tgz#13a8d82e999aa49f8b2dc14d0023d362f2e4ba23" +babel-preset-jest@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.0.2.tgz#9db25def2329f49eace3f5ea0de42a0b898d12cc" dependencies: - babel-plugin-jest-hoist "^21.0.0" + babel-plugin-jest-hoist "^21.0.2" babel-register@^6.24.1: version "6.24.1" @@ -1174,7 +1194,22 @@ bmp-js@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a" -body-parser@1.17.2, body-parser@^1.14.2: +body-parser@1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.0.tgz#d3b224d467fa2ce8d43589c0245043267c093634" + dependencies: + bytes "3.0.0" + content-type "~1.0.2" + debug "2.6.8" + depd "~1.1.1" + http-errors "~1.6.2" + iconv-lite "0.4.18" + on-finished "~2.3.0" + qs "6.5.0" + raw-body "2.3.1" + type-is "~1.6.15" + +body-parser@^1.14.2: version "1.17.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee" dependencies: @@ -1199,6 +1234,18 @@ boom@2.x.x: dependencies: hoek "2.x.x" +boxen@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.2.1.tgz#0f11e7fe344edb9397977fc13ede7f64d956481d" + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^2.0.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^1.2.0" + widest-line "^1.0.0" + brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -1248,9 +1295,9 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bull@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bull/-/bull-3.0.0.tgz#39e76f9b3942dfe5d4209ab49e141ecd837d9430" +bull@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bull/-/bull-3.1.0.tgz#5cdf4ee8b9b72c17c5b257d745f62479c40ca016" dependencies: bluebird "^3.5.0" cron-parser "^2.4.1" @@ -1293,6 +1340,10 @@ bytes@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a" +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" @@ -1330,10 +1381,14 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -camelcase@^4.1.0: +camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -1414,7 +1469,7 @@ child-process-promise@^1.1.0: dependencies: q "^1.1.2" -chokidar@1.7.0, chokidar@^1.4.3, chokidar@^1.6.1, chokidar@^1.7: +chokidar@1.7.0, chokidar@^1.6.1, chokidar@^1.7, chokidar@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -1448,6 +1503,10 @@ clean-css@^3.3.0: commander "2.8.x" source-map "0.4.x" +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -1633,18 +1692,16 @@ config-chain@^1.1.10: ini "^1.3.4" proto-list "~1.2.1" -configstore@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-1.4.0.tgz#c35781d0501d268c25c54b8b17f6240e8a4fb021" +configstore@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90" dependencies: + dot-prop "^4.1.0" graceful-fs "^4.1.2" - mkdirp "^0.5.0" - object-assign "^4.0.1" - os-tmpdir "^1.0.0" - osenv "^0.1.0" - uuid "^2.0.1" - write-file-atomic "^1.1.2" - xdg-basedir "^2.0.0" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" connect-flash@0.1.1: version "0.1.1" @@ -1758,6 +1815,12 @@ crc@3.4.4, crc@^3.4.0: version "3.4.4" resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b" +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + cron-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.4.1.tgz#022befce1af293e4d3144ff04c2cbd2edb491271" @@ -1806,6 +1869,10 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" @@ -2058,6 +2125,12 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +dot-prop@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + dependencies: + is-obj "^1.0.0" + dottie@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.0.tgz#da191981c8b8d713ca0115d5898cf397c2f0ddd0" @@ -2086,7 +2159,7 @@ duplexer@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" -duplexify@^3.1.2, duplexify@^3.2.0: +duplexify@^3.1.2: version "3.5.0" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604" dependencies: @@ -2213,7 +2286,7 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -es6-promise@^3.0.2: +es6-promise@^3.0.2, es6-promise@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" @@ -2437,6 +2510,18 @@ execa@^0.5.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exif-parser@^0.1.9: version "0.1.12" resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922" @@ -2457,16 +2542,16 @@ expand-template@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a" -expect@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-21.0.0.tgz#55fbb07e989479863663975ae8e9ec51753c99ca" +expect@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-21.0.2.tgz#b34abf0635ec9d6aea1ce7edb4722afe86c4a38f" dependencies: ansi-styles "^3.2.0" - jest-diff "^21.0.0" - jest-get-type "^21.0.0" - jest-matcher-utils "^21.0.0" - jest-message-util "^21.0.0" - jest-regex-util "^21.0.0" + jest-diff "^21.0.2" + jest-get-type "^21.0.2" + jest-matcher-utils "^21.0.2" + jest-message-util "^21.0.2" + jest-regex-util "^21.0.2" express-brute-redis@0.0.1: version "0.0.1" @@ -2918,9 +3003,9 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -fuse-box@2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.3.tgz#411cc10f55329a462a5e1641d6864953e89ec79a" +fuse-box@^2.2.31: + version "2.2.31" + resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.31.tgz#36d267a6c6a79952a9c1fb7d1643c1949a6d42f5" dependencies: acorn "^5.0.3" acorn-es7 "^0.1.0" @@ -3113,20 +3198,21 @@ google-closure-compiler@20150901.x: version "20150901.0.0" resolved "https://registry.yarnpkg.com/google-closure-compiler/-/google-closure-compiler-20150901.0.0.tgz#3d01c6cade65790a9bfb4e30b2158b7635acbade" -got@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/got/-/got-3.3.1.tgz#e5d0ed4af55fc3eef4d56007769d98192bcb2eca" +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" dependencies: - duplexify "^3.2.0" - infinity-agent "^2.0.0" + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" is-stream "^1.0.0" lowercase-keys "^1.0.0" - nested-error-stacks "^1.0.0" - object-assign "^3.0.0" - prepend-http "^1.0.0" - read-all-stream "^3.0.0" - timed-out "^2.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" got@^7.0.0: version "7.1.0" @@ -3173,9 +3259,9 @@ graphql-tools@^1.1.0: optionalDependencies: "@types/graphql" "^0.9.0" -graphql@0.11.2: - version "0.11.2" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.2.tgz#13edb9f982f3571dd68ec4e9f3d6aca7e1ba57ef" +graphql@0.11.3: + version "0.11.3" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.3.tgz#9934e2df28f17d397a85f83cb39d1d179bffef47" dependencies: iterall "^1.1.0" @@ -3311,6 +3397,15 @@ htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^2.0.2" +http-errors@1.6.2, http-errors@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + http-errors@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" @@ -3327,15 +3422,6 @@ http-errors@~1.6.1: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" -http-errors@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - http-signature@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" @@ -3373,7 +3459,7 @@ iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" -iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.18, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.18" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" @@ -3381,7 +3467,7 @@ ieee754@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" -ignore-by-default@^1.0.0: +ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -3397,6 +3483,10 @@ immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -3415,10 +3505,6 @@ indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" -infinity-agent@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/infinity-agent/-/infinity-agent-2.0.3.tgz#45e0e2ff7a9eb030b27d62b74b3744b7a7ac4216" - inflection@1.12.0: version "1.12.0" resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" @@ -3651,6 +3737,10 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" @@ -3739,10 +3829,6 @@ isarray@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" -isemail@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -3837,17 +3923,17 @@ jackpot@>=0.0.6: dependencies: retry "0.6.0" -jest-changed-files@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.0.0.tgz#fa7cfc353187e2fb852dd5830e8d09068dde78d1" +jest-changed-files@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.0.2.tgz#0a74f35cf2d3b7c8ef9ab4fac0a75409f81ec1b0" dependencies: throat "^4.0.0" -jest-cli@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.0.0.tgz#25fc36badb6a78dc180a67f02c037c0209d12a98" +jest-cli@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.0.2.tgz#2e08af63d44fc21284ebf496cf71e381f3cc9786" dependencies: - ansi-escapes "^2.0.0" + ansi-escapes "^3.0.0" chalk "^2.0.1" glob "^7.1.2" graceful-fs "^4.1.11" @@ -3856,211 +3942,211 @@ jest-cli@^21.0.0: istanbul-lib-coverage "^1.0.1" istanbul-lib-instrument "^1.4.2" istanbul-lib-source-maps "^1.1.0" - jest-changed-files "^21.0.0" - jest-config "^21.0.0" - jest-environment-jsdom "^21.0.0" - jest-haste-map "^21.0.0" - jest-message-util "^21.0.0" - jest-regex-util "^21.0.0" - jest-resolve-dependencies "^21.0.0" - jest-runner "^21.0.0" - jest-runtime "^21.0.0" - jest-snapshot "^21.0.0" - jest-util "^21.0.0" + jest-changed-files "^21.0.2" + jest-config "^21.0.2" + jest-environment-jsdom "^21.0.2" + jest-haste-map "^21.0.2" + jest-message-util "^21.0.2" + jest-regex-util "^21.0.2" + jest-resolve-dependencies "^21.0.2" + jest-runner "^21.0.2" + jest-runtime "^21.0.2" + jest-snapshot "^21.0.2" + jest-util "^21.0.2" micromatch "^2.3.11" node-notifier "^5.0.2" - pify "^2.3.0" + pify "^3.0.0" slash "^1.0.0" - string-length "^1.0.1" + string-length "^2.0.0" strip-ansi "^4.0.0" which "^1.2.12" worker-farm "^1.3.1" - yargs "^7.0.2" + yargs "^9.0.0" -jest-config@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.0.0.tgz#81dcb20d15971f31bf44a82c6fe85b4423d98d95" +jest-config@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.0.2.tgz#ea42b94f3c22ae4e4aa11c69f5b45e34e342199d" dependencies: chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^21.0.0" - jest-environment-node "^21.0.0" - jest-get-type "^21.0.0" - jest-jasmine2 "^21.0.0" - jest-regex-util "^21.0.0" - jest-resolve "^21.0.0" - jest-util "^21.0.0" - jest-validate "^21.0.0" - pretty-format "^21.0.0" - -jest-diff@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.0.0.tgz#b996ba2963a783125e6bc59fd5623bce67df7f17" + jest-environment-jsdom "^21.0.2" + jest-environment-node "^21.0.2" + jest-get-type "^21.0.2" + jest-jasmine2 "^21.0.2" + jest-regex-util "^21.0.2" + jest-resolve "^21.0.2" + jest-util "^21.0.2" + jest-validate "^21.0.2" + pretty-format "^21.0.2" + +jest-diff@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.0.2.tgz#751014f36ad5d505f6affce5542fde0e444ee50a" dependencies: chalk "^2.0.1" diff "^3.2.0" - jest-get-type "^21.0.0" - pretty-format "^21.0.0" + jest-get-type "^21.0.2" + pretty-format "^21.0.2" -jest-docblock@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.0.0.tgz#7dd57568543aec98910f749540afc15fab53a27f" +jest-docblock@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.0.2.tgz#66f69ddb440799fc32f91d0ac3d8d35e99e2032f" -jest-environment-jsdom@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.0.0.tgz#1d53e34b1656254b8c539700e35360d8f8ebb579" +jest-environment-jsdom@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.0.2.tgz#6f6ab5bd71970d1900fbd47a46701c0a07fa3be5" dependencies: - jest-mock "^21.0.0" - jest-util "^21.0.0" + jest-mock "^21.0.2" + jest-util "^21.0.2" jsdom "^9.12.0" -jest-environment-node@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.0.0.tgz#ffc781b82569f3f4bc2d8fb8f1ea7373cb11f043" +jest-environment-node@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.0.2.tgz#4267ceb39551f8ecaed182ab882a93ef4d5de240" dependencies: - jest-mock "^21.0.0" - jest-util "^21.0.0" + jest-mock "^21.0.2" + jest-util "^21.0.2" -jest-get-type@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.0.0.tgz#ed8667533c0a24a4feebbf492661f23abac3620b" +jest-get-type@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.0.2.tgz#304e6b816dd33cd1f47aba0597bcad258a509fc6" -jest-haste-map@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.0.0.tgz#1f099ff6aedb52ec55fa9773ce26e4bbb00b0580" +jest-haste-map@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.0.2.tgz#bd98bc6cd6f207eb029b2f5918da1a9347eb11b7" dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" - jest-docblock "^21.0.0" + jest-docblock "^21.0.2" micromatch "^2.3.11" sane "^2.0.0" worker-farm "^1.3.1" -jest-jasmine2@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.0.0.tgz#539725989e45ab0b00029fcf37bc679aa39c2941" +jest-jasmine2@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.0.2.tgz#a368abb3a686def4d6e763509a265104943cd469" dependencies: chalk "^2.0.1" - expect "^21.0.0" + expect "^21.0.2" graceful-fs "^4.1.11" - jest-diff "^21.0.0" - jest-matcher-utils "^21.0.0" - jest-message-util "^21.0.0" - jest-snapshot "^21.0.0" + jest-diff "^21.0.2" + jest-matcher-utils "^21.0.2" + jest-message-util "^21.0.2" + jest-snapshot "^21.0.2" p-cancelable "^0.3.0" -jest-matcher-utils@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.0.0.tgz#493dc25b9ed6a23a61802ca20656f0f1c16f15b1" +jest-matcher-utils@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.0.2.tgz#eb6736a45b698546d71f7e1ffbbd36587eeb27bc" dependencies: chalk "^2.0.1" - jest-get-type "^21.0.0" - pretty-format "^21.0.0" + jest-get-type "^21.0.2" + pretty-format "^21.0.2" -jest-message-util@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.0.0.tgz#cd49c2e91d7a227e622884c418185a1a7cbe1fd6" +jest-message-util@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.0.2.tgz#81242e07d426ad54c15f3d7c55b072e9db7b39a9" dependencies: chalk "^2.0.1" micromatch "^2.3.11" slash "^1.0.0" -jest-mock@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.0.0.tgz#948fdbb44ef702ca998e078ca62b4968780e102e" +jest-mock@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.0.2.tgz#5e92902450e1ce78be3864cc4d50dbd5d1582fbd" -jest-regex-util@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.0.0.tgz#f13c382a1c55515c20471390ab38e5d71cbd320e" +jest-regex-util@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.0.2.tgz#06248c07b53ff444223ebe8e33a25bc051ac976f" -jest-resolve-dependencies@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.0.0.tgz#09dfd9654a8af92880a2f66076871d48810bd48d" +jest-resolve-dependencies@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.0.2.tgz#c42cc371034023ac1a226a7a52f86233c8871938" dependencies: - jest-regex-util "^21.0.0" + jest-regex-util "^21.0.2" -jest-resolve@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.0.0.tgz#04d3939203633cc57ae8219b34ad42687dd8d111" +jest-resolve@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.0.2.tgz#57b2c20cbeca2357eb5e638d5c28beca7f38c3f8" dependencies: browser-resolve "^1.11.2" chalk "^2.0.1" is-builtin-module "^1.0.0" -jest-runner@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.0.0.tgz#8969dd22ff73911c84043cf16b6cfadf609f3d1f" - dependencies: - jest-config "^21.0.0" - jest-docblock "^21.0.0" - jest-haste-map "^21.0.0" - jest-jasmine2 "^21.0.0" - jest-message-util "^21.0.0" - jest-runtime "^21.0.0" - jest-util "^21.0.0" - pify "^2.3.0" - throat "^3.0.0" +jest-runner@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.0.2.tgz#1462d431d25f7744e8b5e03837bbf9e268dc8b15" + dependencies: + jest-config "^21.0.2" + jest-docblock "^21.0.2" + jest-haste-map "^21.0.2" + jest-jasmine2 "^21.0.2" + jest-message-util "^21.0.2" + jest-runtime "^21.0.2" + jest-util "^21.0.2" + pify "^3.0.0" + throat "^4.0.0" worker-farm "^1.3.1" -jest-runtime@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.0.0.tgz#54af290dc664a49ddc251c7d7ce1a5661afc1ead" +jest-runtime@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.0.2.tgz#ce26ba06bcd5501991bd994b1eacc0c7c7913895" dependencies: babel-core "^6.0.0" - babel-jest "^21.0.0" + babel-jest "^21.0.2" babel-plugin-istanbul "^4.0.0" chalk "^2.0.1" convert-source-map "^1.4.0" graceful-fs "^4.1.11" - jest-config "^21.0.0" - jest-haste-map "^21.0.0" - jest-regex-util "^21.0.0" - jest-resolve "^21.0.0" - jest-util "^21.0.0" + jest-config "^21.0.2" + jest-haste-map "^21.0.2" + jest-regex-util "^21.0.2" + jest-resolve "^21.0.2" + jest-util "^21.0.2" json-stable-stringify "^1.0.1" micromatch "^2.3.11" slash "^1.0.0" strip-bom "3.0.0" write-file-atomic "^2.1.0" - yargs "^7.0.2" + yargs "^9.0.0" -jest-snapshot@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.0.0.tgz#00b582b13ef42112bd431b498e37f7829b30cd66" +jest-snapshot@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.0.2.tgz#5b8f4dd05c1759381db835451fba4bcd85a55611" dependencies: chalk "^2.0.1" - jest-diff "^21.0.0" - jest-matcher-utils "^21.0.0" + jest-diff "^21.0.2" + jest-matcher-utils "^21.0.2" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^21.0.0" + pretty-format "^21.0.2" -jest-util@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.0.0.tgz#62b3a3ec3ff91022ef7e1ffbcf3293424715919f" +jest-util@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.0.2.tgz#3ee2380af25c414a39f07b23c84da6f2d5f1f76a" dependencies: callsites "^2.0.0" chalk "^2.0.1" graceful-fs "^4.1.11" - jest-message-util "^21.0.0" - jest-mock "^21.0.0" - jest-validate "^21.0.0" + jest-message-util "^21.0.2" + jest-mock "^21.0.2" + jest-validate "^21.0.2" mkdirp "^0.5.1" -jest-validate@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.0.0.tgz#f906d54eca2a485ffbfb2d8a7d58831c026e6dd5" +jest-validate@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.0.2.tgz#dd066b257bd102759c214747d73bed6bcfa4349d" dependencies: chalk "^2.0.1" - jest-get-type "^21.0.0" + jest-get-type "^21.0.2" leven "^2.1.0" - pretty-format "^21.0.0" + pretty-format "^21.0.2" -jest@21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-21.0.0.tgz#6b1536b73ea1a4fa2f0904d26f32949c39cf4690" +jest@21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/jest/-/jest-21.0.2.tgz#a5c9bdc9d4322ae672fe8cb3eaf25c268c5f04b2" dependencies: - jest-cli "^21.0.0" + jest-cli "^21.0.2" jimp@0.2.28: version "0.2.28" @@ -4083,22 +4169,13 @@ jimp@0.2.28: tinycolor2 "^1.1.2" url-regex "^3.0.0" -joi@^6.10.1: - version "6.10.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" - dependencies: - hoek "2.x.x" - isemail "1.x.x" - moment "2.x.x" - topo "1.x.x" - jpeg-js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482" -jquery-contextmenu@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/jquery-contextmenu/-/jquery-contextmenu-2.5.0.tgz#940dbadbd0f2d7e0a0a8f1bbc5e71667d8257405" +jquery-contextmenu@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/jquery-contextmenu/-/jquery-contextmenu-2.6.2.tgz#83c7ba45c67c814cc4095b19551fd12e5d71da7e" jquery-simple-upload@1.0.0: version "1.0.0" @@ -4245,12 +4322,18 @@ jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" -jsonwebtoken@7.4.3: - version "7.4.3" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638" +jsonwebtoken@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.0.0.tgz#7b241aa67c61b3d0b3e641254a9a6f5b66f550e8" dependencies: - joi "^6.10.1" jws "^3.1.4" + lodash.includes "^4.3.0" + lodash.isarray "^4.0.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" lodash.once "^4.0.0" ms "^2.0.0" xtend "^4.0.1" @@ -4310,11 +4393,11 @@ klaw@2.1.0: dependencies: graceful-fs "^4.1.9" -latest-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-1.0.1.tgz#72cfc46e3e8d1be651e1ebb54ea9f6ea96f374bb" +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" dependencies: - package-json "^1.0.0" + package-json "^4.0.0" lazy-cache@^1.0.3: version "1.0.4" @@ -4580,6 +4663,10 @@ lodash.foreach@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + lodash.intersection@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.intersection/-/lodash.intersection-4.4.0.tgz#0a11ba631d0e95c23c7f2f4cbb9a692ed178e705" @@ -4592,6 +4679,14 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.isarray@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-4.0.0.tgz#2aca496b28c4ca6d726715313590c02e6ea34403" + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + lodash.isempty@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" @@ -4600,6 +4695,22 @@ lodash.isequal@^4.0.0, lodash.isequal@^4.1.3: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -4722,9 +4833,15 @@ lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.0.2: pseudomap "^1.0.2" yallist "^2.1.2" -ltgt@~2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" +ltgt@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.0.tgz#b65ba5fcb349a29924c8e333f7c6a5562f2e4842" + +make-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" + dependencies: + pify "^2.3.0" makeerror@1.0.x: version "1.0.11" @@ -4830,15 +4947,15 @@ memcached@~0.2.4: hashring "0.0.x" jackpot ">=0.0.6" -memdown@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.2.4.tgz#cd9a34aaf074d53445a271108eb4b8dd4ec0f27f" +memdown@1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.2.7.tgz#64f2d6b511724c016f3cbd5a40b84349da247b0f" dependencies: - abstract-leveldown "2.4.1" + abstract-leveldown "2.6.3" functional-red-black-tree "^1.0.1" immediate "^3.2.3" inherits "~2.0.1" - ltgt "~2.1.3" + ltgt "~2.2.0" meow@^3.7.0: version "3.7.0" @@ -4977,7 +5094,7 @@ moment-timezone@0.5.13, moment-timezone@^0.5.0, moment-timezone@^0.5.4, moment-t dependencies: moment ">= 2.9.0" -moment@2.18.1, moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.16.1, moment@^2.18: +moment@2.18.1, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.16.1, moment@^2.18: version "2.18.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" @@ -5053,12 +5170,6 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -nested-error-stacks@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz#19f619591519f096769a5ba9a86e6eeec823c3cf" - dependencies: - inherits "~2.0.1" - ngraminator@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/ngraminator/-/ngraminator-0.0.1.tgz#29cfd699df6970f42de9b2f0bdc7f4b60fad6f8e" @@ -5157,20 +5268,20 @@ node-version@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.0.0.tgz#1b9b9584a9a7f7a6123f215cd14a652bf21ab19e" -nodemon@1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.11.0.tgz#226c562bd2a7b13d3d7518b49ad4828a3623d06c" +nodemon@1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.12.0.tgz#e538548a777340a19f855c4f087b7e528aa3feda" dependencies: - chokidar "^1.4.3" - debug "^2.2.0" - es6-promise "^3.0.2" - ignore-by-default "^1.0.0" + chokidar "^1.7.0" + debug "^2.6.8" + es6-promise "^3.3.1" + ignore-by-default "^1.0.1" lodash.defaults "^3.1.2" - minimatch "^3.0.0" - ps-tree "^1.0.1" - touch "1.0.0" + minimatch "^3.0.4" + ps-tree "^1.1.0" + touch "^3.1.0" undefsafe "0.0.3" - update-notifier "0.5.0" + update-notifier "^2.2.0" noop-logger@^0.1.1: version "0.1.1" @@ -5384,7 +5495,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -osenv@0, osenv@^0.1.0, osenv@^0.1.4: +osenv@0, osenv@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" dependencies: @@ -5423,12 +5534,14 @@ p-timeout@^1.1.1: dependencies: p-finally "^1.0.0" -package-json@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-1.2.0.tgz#c8ecac094227cdf76a316874ed05e27cc939a0e0" +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" dependencies: - got "^3.2.0" - registry-url "^3.0.0" + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" packet-reader@0.3.1: version "0.3.1" @@ -5694,9 +5807,9 @@ pg-pool@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257" -pg-promise@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.5.1.tgz#d71d262978ea5a8e9ea9be1325e25e4841201c30" +pg-promise@6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.5.2.tgz#84d18d8f14bd5a60bf8415d96c3c634e0d1745a2" dependencies: manakin "~0.5.1" pg "~6.4.2" @@ -5924,7 +6037,7 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -prepend-http@^1.0.0, prepend-http@^1.0.1: +prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -5932,9 +6045,9 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -pretty-format@^21.0.0: - version "21.0.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.0.0.tgz#bea1522c4c47e49b44db5b6fbf83e7737251f305" +pretty-format@^21.0.2: + version "21.0.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.0.2.tgz#76adcebd836c41ccd2e6b626e70f63050d2a3534" dependencies: ansi-regex "^3.0.0" ansi-styles "^3.2.0" @@ -6015,7 +6128,7 @@ prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" -ps-tree@^1.0.1: +ps-tree@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" dependencies: @@ -6033,9 +6146,9 @@ pug-attrs@^2.0.1, pug-attrs@^2.0.2: js-stringify "^1.0.1" pug-runtime "^2.0.3" -pug-code-gen@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-1.1.1.tgz#1cf72744ef2a039eae6a3340caaa1105871258e8" +pug-code-gen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.0.tgz#96aea39a9e62f1ec5d2b6a5b42a29d528c70b43d" dependencies: constantinople "^3.0.1" doctypes "^1.1.0" @@ -6050,15 +6163,15 @@ pug-error@^1.3.0, pug-error@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.2.tgz#53ae7d9d29bb03cf564493a026109f54c47f5f26" -pug-filters@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.4.tgz#ab247c0f58765414b61be7b54fe979e9f6fc898f" +pug-filters@^2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-2.1.5.tgz#66bf6e80d97fbef829bab0aa35eddff33fc964f3" dependencies: clean-css "^3.3.0" constantinople "^3.0.1" jstransformer "1.0.0" pug-error "^1.3.2" - pug-walk "^1.1.4" + pug-walk "^1.1.5" resolve "^1.1.6" uglify-js "^2.6.1" @@ -6078,12 +6191,12 @@ pug-lexer@^3.1.0: is-expression "^3.0.0" pug-error "^1.3.2" -pug-linker@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.2.tgz#cc0780cf9f3f5522b270871785492b99588d3142" +pug-linker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.3.tgz#25f59eb750237f0368e59c3379764229c0189c41" dependencies: pug-error "^1.3.2" - pug-walk "^1.1.4" + pug-walk "^1.1.5" pug-lint@2.5.0: version "2.5.0" @@ -6103,16 +6216,16 @@ pug-lint@2.5.0: strip-json-comments "^2.0.1" void-elements "^2.0.1" -pug-load@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.8.tgz#1df1c1716f3e68c70d71699cff9458472dc38b9b" +pug-load@^2.0.9: + version "2.0.9" + resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.9.tgz#ee217c914cc1d9324d44b86c32d1df241d36de7a" dependencies: object-assign "^4.1.0" - pug-walk "^1.1.4" + pug-walk "^1.1.5" -pug-parser@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-3.0.1.tgz#dc0c5dd6c9c2d89da6105abbdf3d1b0fb4d39b5e" +pug-parser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-4.0.0.tgz#c9f52322e4eabe4bf5beeba64ed18373bb627801" dependencies: pug-error "^1.3.2" token-stream "0.0.1" @@ -6127,20 +6240,20 @@ pug-strip-comments@^1.0.2: dependencies: pug-error "^1.3.2" -pug-walk@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.4.tgz#29e5174af43b67e99c31b448632e1ff86ddd671c" +pug-walk@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.5.tgz#90e943acbcf7021e6454cf1b32245891cba6f851" -pug@2.0.0-rc.3: - version "2.0.0-rc.3" - resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.3.tgz#553cb3c3a97bb54ec3cb1e08591dcae3b6f58891" +pug@2.0.0-rc.4: + version "2.0.0-rc.4" + resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.0-rc.4.tgz#b7b08f6599bd5302568042b7436984fb28c80a13" dependencies: - pug-code-gen "^1.1.1" - pug-filters "^2.1.4" + pug-code-gen "^2.0.0" + pug-filters "^2.1.5" pug-lexer "^3.1.0" - pug-linker "^3.0.2" - pug-load "^2.0.8" - pug-parser "^3.0.1" + pug-linker "^3.0.3" + pug-load "^2.0.9" + pug-parser "^4.0.0" pug-runtime "^2.0.3" pug-strip-comments "^1.0.2" @@ -6198,6 +6311,15 @@ range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" +raw-body@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.1.tgz#30f95e2a67a14e2e4413d8d51fdd92c877e8f2ed" + dependencies: + bytes "3.0.0" + http-errors "1.6.2" + iconv-lite "0.4.18" + unpipe "1.0.0" + raw-body@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.2.0.tgz#994976cf6a5096a41162840492f0bdc5d6e7fb96" @@ -6215,13 +6337,6 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -read-all-stream@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa" - dependencies: - pinkie-promise "^2.0.0" - readable-stream "^2.0.0" - read-chunk@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655" @@ -6378,7 +6493,14 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -registry-url@^3.0.0: +registry-auth-token@^3.0.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" dependencies: @@ -6410,12 +6532,6 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" -repeating@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" - dependencies: - is-finite "^1.0.0" - repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" @@ -6707,9 +6823,9 @@ send@0.15.4: range-parser "~1.2.0" statuses "~1.3.1" -sequelize@4.8.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.8.0.tgz#1987a97deceb749da7e25cd27059adb69dbf81c2" +sequelize@4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.8.2.tgz#d16a6e75e8b48303beab4787b946bf06f32f1a94" dependencies: bluebird "^3.4.6" cls-bluebird "^2.0.1" @@ -6843,10 +6959,6 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -6989,9 +7101,9 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -stopword@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/stopword/-/stopword-0.1.6.tgz#435cc3e9d4311aedca2876ed4cae79153cd3d0fb" +stopword@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/stopword/-/stopword-0.1.7.tgz#4bf4f6bbb157f5ca43e4800559854943828563d6" stream-combiner@~0.0.4: version "0.0.4" @@ -7031,11 +7143,12 @@ streamsearch@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" -string-length@^1.0.0, string-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" +string-length@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" dependencies: - strip-ansi "^3.0.0" + astral-regex "^1.0.0" + strip-ansi "^4.0.0" string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" @@ -7200,6 +7313,12 @@ term-frequency@^0.0.15: version "0.0.15" resolved "https://registry.yarnpkg.com/term-frequency/-/term-frequency-0.0.15.tgz#ff4aeaff2ac31ee1096b5c685852816a5da676e7" +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + dependencies: + execa "^0.7.0" + term-vector@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/term-vector/-/term-vector-0.1.2.tgz#774e7e44aef2274b3b1d8a2441981f99d0f7e0aa" @@ -7243,10 +7362,6 @@ thirty-two@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-0.0.2.tgz#4253e29d8cb058f0480267c5698c0e4927e54b6a" -throat@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836" - throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -7262,10 +7377,6 @@ through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" -timed-out@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" - timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -7300,19 +7411,13 @@ token-stream@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" -topo@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" - dependencies: - hoek "2.x.x" - toposort-class@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" -touch@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de" +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" dependencies: nopt "~1.0.10" @@ -7462,6 +7567,12 @@ underscore@~1.5.1: version "1.5.2" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.5.2.tgz#1335c5e4f5e6d33bbb4b006ba8c86a00f556de08" +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + dependencies: + crypto-random-string "^1.0.0" + universalify@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" @@ -7474,17 +7585,22 @@ unzip-response@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" -update-notifier@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +update-notifier@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.2.0.tgz#1b5837cf90c0736d88627732b661c138f86de72f" dependencies: + boxen "^1.0.0" chalk "^1.0.0" - configstore "^1.0.0" + configstore "^3.0.0" + import-lazy "^2.1.0" is-npm "^1.0.0" - latest-version "^1.0.0" - repeating "^1.1.2" + latest-version "^3.0.0" semver-diff "^2.0.0" - string-length "^1.0.0" + xdg-basedir "^3.0.0" url-parse-lax@^1.0.0: version "1.0.0" @@ -7531,7 +7647,7 @@ utils-merge@1.0.0, utils-merge@1.x.x: version "1.0.0" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" -uuid@^2.0.1, uuid@^2.0.2: +uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" @@ -7564,14 +7680,18 @@ validator-as-promised@1.0.2: lodash "^4.14.0" validator "^5.5.0" -validator@8.1.0, validator@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-8.1.0.tgz#89cf6b512ff71eba886afd8d10d47f8dc800eac0" +validator@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-8.2.0.tgz#3c1237290e37092355344fef78c231249dab77b9" validator@^5.5.0: version "5.7.0" resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c" +validator@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-8.1.0.tgz#89cf6b512ff71eba886afd8d10d47f8dc800eac0" + vary@^1, vary@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" @@ -7737,6 +7857,12 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2" +widest-line@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c" + dependencies: + string-width "^1.0.1" + window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" @@ -7804,15 +7930,7 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -write-file-atomic@^1.1.2: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - -write-file-atomic@^2.1.0: +write-file-atomic@^2.0.0, write-file-atomic@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" dependencies: @@ -7840,11 +7958,9 @@ ws@~2.3.1: safe-buffer "~5.0.1" ultron "~1.1.0" -xdg-basedir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2" - dependencies: - os-homedir "^1.0.0" +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" xhr@^2.0.1: version "2.4.0" @@ -7933,7 +8049,7 @@ yargs@8.0.2: y18n "^3.2.1" yargs-parser "^7.0.0" -yargs@^7.0.0, yargs@^7.0.2: +yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" dependencies: @@ -7951,6 +8067,24 @@ yargs@^7.0.0, yargs@^7.0.2: y18n "^3.2.1" yargs-parser "^5.0.0" +yargs@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.0.tgz#efe5b1ad3f94bdc20423411b90628eeec0b25f3c" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" + yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" From cac3d21c6e5d012d3a9f379524294628f4dc5d86 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 10 Sep 2017 23:00:03 -0400 Subject: [PATCH 19/33] feat: self-contained auth modules + login UI + icons --- assets/svg/auth-icon-azure.svg | 1 + assets/svg/auth-icon-facebook.svg | 3 + assets/svg/auth-icon-github.svg | 1 + assets/svg/auth-icon-google.svg | 1 + assets/svg/auth-icon-ldap.svg | 10 +++ assets/svg/auth-icon-microsoft.svg | 1 + assets/svg/auth-icon-slack.svg | 1 + client/scss/login.scss | 13 ---- client/scss/pages/_login.scss | 121 +++++++++++++++++++++-------- server/authentication/azure.js | 45 ++++++----- server/authentication/facebook.js | 35 +++++---- server/authentication/github.js | 35 +++++---- server/authentication/google.js | 33 ++++---- server/authentication/ldap.js | 61 ++++++++------- server/authentication/local.js | 47 ++++++----- server/authentication/microsoft.js | 33 ++++---- server/authentication/slack.js | 33 ++++---- server/controllers/auth.js | 3 +- server/master.js | 11 +-- server/middlewares/flash.js | 2 +- server/modules/auth.js | 38 ++++++--- server/views/auth/login.pug | 62 +++++---------- 22 files changed, 341 insertions(+), 249 deletions(-) create mode 100644 assets/svg/auth-icon-azure.svg create mode 100644 assets/svg/auth-icon-facebook.svg create mode 100644 assets/svg/auth-icon-github.svg create mode 100644 assets/svg/auth-icon-google.svg create mode 100644 assets/svg/auth-icon-ldap.svg create mode 100644 assets/svg/auth-icon-microsoft.svg create mode 100644 assets/svg/auth-icon-slack.svg delete mode 100644 client/scss/login.scss diff --git a/assets/svg/auth-icon-azure.svg b/assets/svg/auth-icon-azure.svg new file mode 100644 index 00000000..cf13b912 --- /dev/null +++ b/assets/svg/auth-icon-azure.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svg/auth-icon-facebook.svg b/assets/svg/auth-icon-facebook.svg new file mode 100644 index 00000000..fa706aa2 --- /dev/null +++ b/assets/svg/auth-icon-facebook.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/svg/auth-icon-github.svg b/assets/svg/auth-icon-github.svg new file mode 100644 index 00000000..18e9450e --- /dev/null +++ b/assets/svg/auth-icon-github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svg/auth-icon-google.svg b/assets/svg/auth-icon-google.svg new file mode 100644 index 00000000..06dc52f0 --- /dev/null +++ b/assets/svg/auth-icon-google.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svg/auth-icon-ldap.svg b/assets/svg/auth-icon-ldap.svg new file mode 100644 index 00000000..679fc237 --- /dev/null +++ b/assets/svg/auth-icon-ldap.svg @@ -0,0 +1,10 @@ + + + + + + + diff --git a/assets/svg/auth-icon-microsoft.svg b/assets/svg/auth-icon-microsoft.svg new file mode 100644 index 00000000..0d47e89a --- /dev/null +++ b/assets/svg/auth-icon-microsoft.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svg/auth-icon-slack.svg b/assets/svg/auth-icon-slack.svg new file mode 100644 index 00000000..47232d6d --- /dev/null +++ b/assets/svg/auth-icon-slack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/scss/login.scss b/client/scss/login.scss deleted file mode 100644 index 725ce498..00000000 --- a/client/scss/login.scss +++ /dev/null @@ -1,13 +0,0 @@ -@charset "utf-8"; - -$primary: 'indigo'; - -@import "base/variables"; -@import "base/colors"; -@import "base/reset"; -@import "base/mixins"; -@import "base/fonts"; -@import "base/base"; - -@import "libs/animate"; -@import 'pages/login'; diff --git a/client/scss/pages/_login.scss b/client/scss/pages/_login.scss index 284bf7f6..440148c0 100644 --- a/client/scss/pages/_login.scss +++ b/client/scss/pages/_login.scss @@ -9,23 +9,65 @@ justify-content: center; &-container { + position: relative; display: flex; - width: 650px; + width: 450px; align-items: stretch; box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); + + &.is-expanded { + width: 650px; + } + + @include until($tablet) { + width: 350px; + + &.is-expanded { + width: 400px; + } + } + } + + &-error { + position: absolute; + bottom: 100%; + width: 100%; + min-height: 50px; + background-image: radial-gradient(ellipse at top left, rgba(mc('red', '900'),.9) 0%,rgba(mc('red', '400'),.8) 100%); + border: 1px solid #FFF; + color: #FFF; + display: flex; + justify-content: center; + align-items: center; + + strong { + font-weight: 600; + text-transform: uppercase; + display: block; + padding: 0 1rem 0 0; + border-right: 1px solid #FFF; + } + span { + padding: 0 0 0 1rem; + display: block; + } } &-providers { display: flex; flex-direction: column; - width: 200px; + width: 250px; border: 1px solid #FFF; background-color: mc('grey', '900'); z-index: 1; + @include until($tablet) { + width: 50px; + } + button { flex: 1 1; - padding: 0 15px; + padding: 5px 15px; border: none; color: #FFF; background-color: mc('grey', '800'); @@ -34,6 +76,18 @@ font-weight: 600; text-align: left; min-height: 40px; + display: flex; + justify-content: flex-start; + align-items: center; + transition: all .4s ease; + + @include until($tablet) { + justify-content: center; + } + + &:hover { + background-color: mc('grey', '600'); + } &:first-child { border-top: none; @@ -48,10 +102,36 @@ i { margin-right: 10px; font-size: 16px; + + @include until($tablet) { + margin-right: 0; + font-size: 20px; + } + } + + svg { + margin-right: 10px; + width: auto; + height: 20px; + max-width: 18px; + max-height: 20px; + + path { + fill: #FFF; + } + + @include until($tablet) { + margin-right: 0; + font-size: 20px; + } } span { font-weight: 600; + + @include until($tablet) { + display: none; + } } } } @@ -59,7 +139,7 @@ &-frame { background-image: radial-gradient(circle at top left, rgba(255,255,255,1) 0%,rgba(240,240,240,.6) 100%); border: 1px solid #FFF; - width: 450px; + width: 400px; padding: 1rem; color: mc('grey', '700'); display: flex; @@ -67,6 +147,10 @@ flex-direction: column; text-align: center; + @include until($tablet) { + width: 350px; + } + h1 { font-size: 2rem; font-weight: 600; @@ -83,29 +167,6 @@ margin: 0 0 25px 0; } - h3 { - font-size: 1.25rem; - font-weight: normal; - color: #FB8C00; - padding: 0; - margin: 0; - animation: shake 1s ease; - - > .fa { - margin-right: 7px; - } - - } - - h4 { - font-size: .8rem; - font-weight: normal; - color: rgba(255,255,255,0.7); - padding: 0; - margin: 0 0 15px 0; - animation: fadeIn 3s ease; - } - form { display: flex; flex-direction: column; @@ -147,14 +208,10 @@ font-weight: 400; text-shadow: 1px 1px 0 #000; - .icon { - font-size: 1.2rem; - margin: 0 8px; - } - a { font-weight: 600; color: #FFF; + margin-left: .25rem; } } diff --git a/server/authentication/azure.js b/server/authentication/azure.js index c54830ef..c6d71b4d 100644 --- a/server/authentication/azure.js +++ b/server/authentication/azure.js @@ -8,24 +8,29 @@ const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy -module.exports = (passport, conf) => { - const jwt = require('jsonwebtoken') - passport.use('azure_ad_oauth2', - new AzureAdOAuth2Strategy({ - clientID: conf.clientId, - clientSecret: conf.clientSecret, - callbackURL: conf.callbackURL, - resource: conf.resource, - tenant: conf.tenant - }, (accessToken, refreshToken, params, profile, cb) => { - let waadProfile = jwt.decode(params.id_token) - waadProfile.id = waadProfile.oid - waadProfile.provider = 'azure' - wiki.db.User.processProfile(waadProfile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) +module.exports = { + key: 'azure', + title: 'Azure Active Directory', + props: ['clientId', 'clientSecret', 'callbackURL', 'resource', 'tenant'], + init (passport, conf) { + const jwt = require('jsonwebtoken') + passport.use('azure_ad_oauth2', + new AzureAdOAuth2Strategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL, + resource: conf.resource, + tenant: conf.tenant + }, (accessToken, refreshToken, params, profile, cb) => { + let waadProfile = jwt.decode(params.id_token) + waadProfile.id = waadProfile.oid + waadProfile.provider = 'azure' + wiki.db.User.processProfile(waadProfile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } } diff --git a/server/authentication/facebook.js b/server/authentication/facebook.js index 1a1d3822..03375dac 100644 --- a/server/authentication/facebook.js +++ b/server/authentication/facebook.js @@ -8,19 +8,24 @@ const FacebookStrategy = require('passport-facebook').Strategy -module.exports = (passport, conf) => { - passport.use('facebook', - new FacebookStrategy({ - clientID: conf.clientId, - clientSecret: conf.clientSecret, - callbackURL: conf.callbackURL, - profileFields: ['id', 'displayName', 'email'] - }, function (accessToken, refreshToken, profile, cb) { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) +module.exports = { + key: 'facebook', + title: 'Facebook', + props: ['clientId', 'clientSecret', 'callbackURL'], + init (passport, conf) { + passport.use('facebook', + new FacebookStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL, + profileFields: ['id', 'displayName', 'email'] + }, function (accessToken, refreshToken, profile, cb) { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } } diff --git a/server/authentication/github.js b/server/authentication/github.js index 7c225e6a..ff3aec3b 100644 --- a/server/authentication/github.js +++ b/server/authentication/github.js @@ -8,19 +8,24 @@ const GitHubStrategy = require('passport-github2').Strategy -module.exports = (passport, conf) => { - passport.use('github', - new GitHubStrategy({ - clientID: conf.clientId, - clientSecret: conf.clientSecret, - callbackURL: conf.callbackURL, - scope: ['user:email'] - }, (accessToken, refreshToken, profile, cb) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) +module.exports = { + key: 'github', + title: 'GitHub', + props: ['clientId', 'clientSecret', 'callbackURL'], + init (passport, conf) { + passport.use('github', + new GitHubStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL, + scope: ['user:email'] + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } } diff --git a/server/authentication/google.js b/server/authentication/google.js index 9531f4a8..371f4c30 100644 --- a/server/authentication/google.js +++ b/server/authentication/google.js @@ -8,18 +8,23 @@ const GoogleStrategy = require('passport-google-oauth20').Strategy -module.exports = (passport, conf) => { - passport.use('google', - new GoogleStrategy({ - clientID: conf.clientId, - clientSecret: conf.clientSecret, - callbackURL: conf.callbackURL - }, (accessToken, refreshToken, profile, cb) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) +module.exports = { + key: 'google', + title: 'Google ID', + props: ['clientId', 'clientSecret', 'callbackURL'], + init (passport, conf) { + passport.use('google', + new GoogleStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } } diff --git a/server/authentication/ldap.js b/server/authentication/ldap.js index 0eb4ccbe..c7a993db 100644 --- a/server/authentication/ldap.js +++ b/server/authentication/ldap.js @@ -9,32 +9,37 @@ const LdapStrategy = require('passport-ldapauth').Strategy const fs = require('fs') -module.exports = (passport, conf) => { - passport.use('ldapauth', - new LdapStrategy({ - server: { - url: conf.url, - bindDn: conf.bindDn, - bindCredentials: conf.bindCredentials, - searchBase: conf.searchBase, - searchFilter: conf.searchFilter, - searchAttributes: ['displayName', 'name', 'cn', 'mail'], - tlsOptions: (conf.tlsEnabled) ? { - ca: [ - fs.readFileSync(conf.tlsCertPath) - ] - } : {} - }, - usernameField: 'email', - passReqToCallback: false - }, (profile, cb) => { - profile.provider = 'ldap' - profile.id = profile.dn - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) +module.exports = { + key: 'ldap', + title: 'LDAP / Active Directory', + props: ['url', 'bindDn', 'bindCredentials', 'searchBase', 'searchFilter', 'tlsEnabled', 'tlsCertPath'], + init (passport, conf) { + passport.use('ldapauth', + new LdapStrategy({ + server: { + url: conf.url, + bindDn: conf.bindDn, + bindCredentials: conf.bindCredentials, + searchBase: conf.searchBase, + searchFilter: conf.searchFilter, + searchAttributes: ['displayName', 'name', 'cn', 'mail'], + tlsOptions: (conf.tlsEnabled) ? { + ca: [ + fs.readFileSync(conf.tlsCertPath) + ] + } : {} + }, + usernameField: 'email', + passReqToCallback: false + }, (profile, cb) => { + profile.provider = 'ldap' + profile.id = profile.dn + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } } diff --git a/server/authentication/local.js b/server/authentication/local.js index ae00171b..1c4c7c07 100644 --- a/server/authentication/local.js +++ b/server/authentication/local.js @@ -8,25 +8,30 @@ const LocalStrategy = require('passport-local').Strategy -module.exports = (passport, conf) => { - passport.use('local', - new LocalStrategy({ - usernameField: 'email', - passwordField: 'password' - }, (uEmail, uPassword, done) => { - wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => { - if (user) { - return user.validatePassword(uPassword).then(() => { - return done(null, user) || true - }).catch((err) => { - return done(err, null) - }) - } else { - return done(new Error('INVALID_LOGIN'), null) - } - }).catch((err) => { - done(err, null) - }) - } - )) +module.exports = { + key: 'local', + title: 'Local', + props: [], + init (passport, conf) { + passport.use('local', + new LocalStrategy({ + usernameField: 'email', + passwordField: 'password' + }, (uEmail, uPassword, done) => { + wiki.db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => { + if (user) { + return user.validatePassword(uPassword).then(() => { + return done(null, user) || true + }).catch((err) => { + return done(err, null) + }) + } else { + return done(new Error('INVALID_LOGIN'), null) + } + }).catch((err) => { + done(err, null) + }) + } + )) + } } diff --git a/server/authentication/microsoft.js b/server/authentication/microsoft.js index 6ccd1b88..e8069de2 100644 --- a/server/authentication/microsoft.js +++ b/server/authentication/microsoft.js @@ -8,18 +8,23 @@ const WindowsLiveStrategy = require('passport-windowslive').Strategy -module.exports = (passport, conf) => { - passport.use('windowslive', - new WindowsLiveStrategy({ - clientID: conf.clientId, - clientSecret: conf.clientSecret, - callbackURL: conf.callbackURL - }, function (accessToken, refreshToken, profile, cb) { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) +module.exports = { + key: 'microsoft', + title: 'Microsoft Account', + props: ['clientId', 'clientSecret', 'callbackURL'], + init (passport, conf) { + passport.use('windowslive', + new WindowsLiveStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL + }, function (accessToken, refreshToken, profile, cb) { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } } diff --git a/server/authentication/slack.js b/server/authentication/slack.js index 778d6abf..17b7e0ae 100644 --- a/server/authentication/slack.js +++ b/server/authentication/slack.js @@ -8,18 +8,23 @@ const SlackStrategy = require('passport-slack').Strategy -module.exports = (passport, conf) => { - passport.use('slack', - new SlackStrategy({ - clientID: conf.clientId, - clientSecret: conf.clientSecret, - callbackURL: conf.callbackURL - }, (accessToken, refreshToken, profile, cb) => { - wiki.db.User.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) - } - )) +module.exports = { + key: 'slack', + title: 'Slack', + props: ['clientId', 'clientSecret', 'callbackURL'], + init (passport, conf) { + passport.use('slack', + new SlackStrategy({ + clientID: conf.clientId, + clientSecret: conf.clientSecret, + callbackURL: conf.callbackURL + }, (accessToken, refreshToken, profile, cb) => { + wiki.db.User.processProfile(profile).then((user) => { + return cb(null, user) || true + }).catch((err) => { + return cb(err, null) || true + }) + } + )) + } } diff --git a/server/controllers/auth.js b/server/controllers/auth.js index a29e2873..179dbae8 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -37,7 +37,8 @@ const bruteforce = new ExpressBrute(EBstore, { */ router.get('/login', function (req, res, next) { res.render('auth/login', { - usr: res.locals.usr + authStrategies: wiki.auth.strategies, + hasMultipleStrategies: Object.keys(wiki.config.auth.strategies).length > 0 }) }) diff --git a/server/master.js b/server/master.js index 844eee05..9199bc71 100644 --- a/server/master.js +++ b/server/master.js @@ -16,6 +16,7 @@ module.exports = Promise.join( // Load global modules // ---------------------------------------- + wiki.auth = require('./modules/auth').init() wiki.disk = require('./modules/disk').init() wiki.docs = require('./modules/documents').init() wiki.git = require('./modules/git').init(false) @@ -38,7 +39,6 @@ module.exports = Promise.join( const http = require('http') const i18nBackend = require('i18next-node-fs-backend') const path = require('path') - const passport = require('passport') const passportSocketIo = require('passport.socketio') const session = require('express-session') const SessionRedisStore = require('connect-redis')(session) @@ -78,10 +78,6 @@ module.exports = Promise.join( // Passport Authentication // ---------------------------------------- - require('./modules/auth').init(passport) - wiki.rights = require('./modules/rights') - // wiki.rights.init() - let sessionStore = new SessionRedisStore({ client: wiki.redis }) @@ -95,8 +91,8 @@ module.exports = Promise.join( saveUninitialized: false })) app.use(flash()) - app.use(passport.initialize()) - app.use(passport.session()) + app.use(wiki.auth.passport.initialize()) + app.use(wiki.auth.passport.session()) // ---------------------------------------- // SEO @@ -135,6 +131,7 @@ module.exports = Promise.join( // View accessible data // ---------------------------------------- + app.locals.basedir = wiki.ROOTPATH app.locals._ = require('lodash') app.locals.t = wiki.lang.t.bind(wiki.lang) app.locals.moment = require('moment') diff --git a/server/middlewares/flash.js b/server/middlewares/flash.js index 98182b47..09e4adf0 100644 --- a/server/middlewares/flash.js +++ b/server/middlewares/flash.js @@ -9,7 +9,7 @@ * @return {any} void */ module.exports = (req, res, next) => { - res.locals.appflash = req.flash('alert') + res.locals.flash = req.flash('alert') next() } diff --git a/server/modules/auth.js b/server/modules/auth.js index 2fd96206..95befaeb 100644 --- a/server/modules/auth.js +++ b/server/modules/auth.js @@ -3,10 +3,16 @@ /* global wiki */ const _ = require('lodash') +const passport = require('passport') +const fs = require('fs-extra') +const path = require('path') module.exports = { - init(passport) { - // Serialization user methods + strategies: {}, + init() { + this.passport = passport + + // Serialization user methods passport.serializeUser(function (user, done) { done(null, user._id) @@ -27,20 +33,26 @@ module.exports = { // Load authentication strategies - wiki.config.authStrategies = { - list: _.pickBy(wiki.config.auth, strategy => strategy.enabled), - socialEnabled: (_.chain(wiki.config.auth).omit('local').filter(['enabled', true]).value().length > 0) - } - - _.forOwn(wiki.config.authStrategies.list, (strategyConfig, strategyName) => { - strategyConfig.callbackURL = `${wiki.config.site.host}/login/${strategyName}/callback` - require(`../authentication/${strategyName}`)(passport, strategyConfig) - wiki.logger.info(`Authentication Provider ${_.upperFirst(strategyName)}: OK`) + _.forOwn(wiki.config.auth.strategies, (strategyConfig, strategyKey) => { + strategyConfig.callbackURL = `${wiki.config.site.host}${wiki.config.site.path}/login/${strategyKey}/callback` + let strategy = require(`../authentication/${strategyKey}`) + strategy.init(passport, strategyConfig) + fs.readFile(path.join(wiki.ROOTPATH, `assets/svg/auth-icon-${strategyKey}.svg`), 'utf8').then(iconData => { + strategy.icon = iconData + }).catch(err => { + if (err.code === 'ENOENT') { + strategy.icon = '[missing icon]' + } else { + wiki.logger.error(err) + } + }) + this.strategies[strategy.key] = strategy + wiki.logger.info(`Authentication Provider ${strategyKey}: OK`) }) // Create Guest account for first-time - return wiki.db.User.findOne({ + wiki.db.User.findOne({ where: { provider: 'local', email: 'guest@example.com' @@ -88,5 +100,7 @@ module.exports = { // }) // } else { return true } // }) + + return this } } diff --git a/server/views/auth/login.pug b/server/views/auth/login.pug index 14105179..fad51aff 100644 --- a/server/views/auth/login.pug +++ b/server/views/auth/login.pug @@ -3,52 +3,30 @@ extends ../master.pug block body body .login#root - .login-container - if config.authStrategies.socialEnabled + .login-container(:class={ "is-expanded": hasMultipleStrategies }) + if flash.length > 0 + .login-error + strong + i.icon-warning-outline + = flash[0].title + span= flash[0].message + if hasMultipleStrategies .login-providers - button.is-active(onclick='window.location.assign("/login/ms")') + button.is-active(title=t('auth:providers.local')) i.nc-icon-outline.ui-1_database span= t('auth:providers.local') - if config.auth.microsoft && config.auth.microsoft.enabled - button(onclick='window.location.assign("/login/ms")') - i.icon-windows2 - span= t('auth:providers.windowslive') - if config.auth.azure && config.auth.azure.enabled - button(onclick='window.location.assign("/login/azure")') - i.icon-windows2 - span= t('auth:providers.azure') - if config.auth.google && config.auth.google.enabled - button(onclick='window.location.assign("/login/google")') - i.icon-google - span= t('auth:providers.google') - if config.auth.facebook && config.auth.facebook.enabled - button(onclick='window.location.assign("/login/facebook")') - i.icon-facebook - span= t('auth:providers.facebook') - if config.auth.github && config.auth.github.enabled - button(onclick='window.location.assign("/login/github")') - i.icon-github - span= t('auth:providers.github') - if config.auth.slack && config.auth.slack.enabled - button(onclick='window.location.assign("/login/slack")') - i.icon-slack - span= t('auth:providers.slack') + each strategy in authStrategies + button(onclick='window.location.assign("/login/' + strategy.key + '")', title=strategy.title) + != strategy.icon + span= strategy.title .login-frame h1= config.site.title h2= t('auth:loginrequired') - if appflash.length > 0 - h3 - i.icon-warning-outline - = appflash[0].title - h4= appflash[0].message - if config.auth.local.enabled - form(method='post', action='/login') - input#login-user(type='text', name='email', placeholder=t('auth:fields.emailuser')) - input#login-pass(type='password', name='password', placeholder=t('auth:fields.password')) - button.button.is-light-green.is-fullwidth(type='submit') - span= t('auth:actions.login') + form(method='post', action='/login') + input#login-user(type='text', name='email', placeholder=t('auth:fields.emailuser')) + input#login-pass(type='password', name='password', placeholder=t('auth:fields.password')) + button.button.is-light-green.is-fullwidth(type='submit') + span= t('auth:actions.login') .login-copyright - = t('footer.poweredby') + ' ' - a.icon(href='https://github.com/Requarks/wiki') - i.icon-github - a(href='https://wiki.requarks.io/') Wiki.js + = t('footer.poweredby') + a(href='https://wiki.js.org', rel='external', title='Wiki.js') Wiki.js From 759b66469c8b8139dc49524fa698ab38512f0a5c Mon Sep 17 00:00:00 2001 From: NGPixel Date: Mon, 11 Sep 2017 21:38:23 -0400 Subject: [PATCH 20/33] feat: persian locales + auth fix --- server/controllers/auth.js | 31 ++++++------- server/locales/fa/admin.json | 82 ++++++++++++++++++++++++++++++++ server/locales/fa/auth.json | 32 +++++++++++++ server/locales/fa/browser.json | 85 ++++++++++++++++++++++++++++++++++ server/modules/auth.js | 2 + 5 files changed, 216 insertions(+), 16 deletions(-) create mode 100644 server/locales/fa/admin.json create mode 100644 server/locales/fa/auth.json create mode 100644 server/locales/fa/browser.json diff --git a/server/controllers/auth.js b/server/controllers/auth.js index 179dbae8..317938a3 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -5,7 +5,6 @@ const Promise = require('bluebird') const express = require('express') const router = express.Router() -const passport = require('passport') const ExpressBrute = require('express-brute') const ExpressBruteRedisStore = require('express-brute-redis') const moment = require('moment') @@ -45,16 +44,16 @@ router.get('/login', function (req, res, next) { router.post('/login', bruteforce.prevent, function (req, res, next) { new Promise((resolve, reject) => { // [1] LOCAL AUTHENTICATION - passport.authenticate('local', function (err, user, info) { + wiki.auth.passport.authenticate('local', function (err, user, info) { if (err) { return reject(err) } if (!user) { return reject(new Error('INVALID_LOGIN')) } resolve(user) })(req, res, next) }).catch({ message: 'INVALID_LOGIN' }, err => { - if (appconfig.auth.ldap && appconfig.auth.ldap.enabled) { + if (_.has(wiki.config.auth.strategy, 'ldap')) { // [2] LDAP AUTHENTICATION return new Promise((resolve, reject) => { - passport.authenticate('ldapauth', function (err, user, info) { + wiki.auth.passport.authenticate('ldapauth', function (err, user, info) { if (err) { return reject(err) } if (info && info.message) { return reject(new Error(info.message)) } if (!user) { return reject(new Error('INVALID_LOGIN')) } @@ -94,19 +93,19 @@ router.post('/login', bruteforce.prevent, function (req, res, next) { * Social Login */ -router.get('/login/ms', passport.authenticate('windowslive', { scope: ['wl.signin', 'wl.basic', 'wl.emails'] })) -router.get('/login/google', passport.authenticate('google', { scope: ['profile', 'email'] })) -router.get('/login/facebook', passport.authenticate('facebook', { scope: ['public_profile', 'email'] })) -router.get('/login/github', passport.authenticate('github', { scope: ['user:email'] })) -router.get('/login/slack', passport.authenticate('slack', { scope: ['identity.basic', 'identity.email'] })) -router.get('/login/azure', passport.authenticate('azure_ad_oauth2')) +router.get('/login/ms', wiki.auth.passport.authenticate('windowslive', { scope: ['wl.signin', 'wl.basic', 'wl.emails'] })) +router.get('/login/google', wiki.auth.passport.authenticate('google', { scope: ['profile', 'email'] })) +router.get('/login/facebook', wiki.auth.passport.authenticate('facebook', { scope: ['public_profile', 'email'] })) +router.get('/login/github', wiki.auth.passport.authenticate('github', { scope: ['user:email'] })) +router.get('/login/slack', wiki.auth.passport.authenticate('slack', { scope: ['identity.basic', 'identity.email'] })) +router.get('/login/azure', wiki.auth.passport.authenticate('azure_ad_oauth2')) -router.get('/login/ms/callback', passport.authenticate('windowslive', { failureRedirect: '/login', successRedirect: '/' })) -router.get('/login/google/callback', passport.authenticate('google', { failureRedirect: '/login', successRedirect: '/' })) -router.get('/login/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login', successRedirect: '/' })) -router.get('/login/github/callback', passport.authenticate('github', { failureRedirect: '/login', successRedirect: '/' })) -router.get('/login/slack/callback', passport.authenticate('slack', { failureRedirect: '/login', successRedirect: '/' })) -router.get('/login/azure/callback', passport.authenticate('azure_ad_oauth2', { failureRedirect: '/login', successRedirect: '/' })) +router.get('/login/ms/callback', wiki.auth.passport.authenticate('windowslive', { failureRedirect: '/login', successRedirect: '/' })) +router.get('/login/google/callback', wiki.auth.passport.authenticate('google', { failureRedirect: '/login', successRedirect: '/' })) +router.get('/login/facebook/callback', wiki.auth.passport.authenticate('facebook', { failureRedirect: '/login', successRedirect: '/' })) +router.get('/login/github/callback', wiki.auth.passport.authenticate('github', { failureRedirect: '/login', successRedirect: '/' })) +router.get('/login/slack/callback', wiki.auth.passport.authenticate('slack', { failureRedirect: '/login', successRedirect: '/' })) +router.get('/login/azure/callback', wiki.auth.passport.authenticate('azure_ad_oauth2', { failureRedirect: '/login', successRedirect: '/' })) /** * Logout diff --git a/server/locales/fa/admin.json b/server/locales/fa/admin.json new file mode 100644 index 00000000..1b4d5000 --- /dev/null +++ b/server/locales/fa/admin.json @@ -0,0 +1,82 @@ +{ + "profile": { + "displayname": "نام کامل", + "displaynameexample": "علی علوی", + "email": "ایمیل", + "lastprofileupdate": "آخرین زمان به روز رسانی پروفایل", + "membersince": "عضو از تاریخ", + "password": "گذرواژه", + "passwordverify": "تکرار گذرواژه", + "provider": "سرویس‌دهنده", + "savechanges": "ذخیره تغییرات", + "subtitle": "اطلاعات پروفایل و سیستم احراز هویت", + "tfa": "احراز هویت دو مرحله‌ای", + "tfadisable": "غیرفعال کردن سیستم احراز هویت دو مرحله‌ای", + "tfadisabled": "غیرفعال", + "tfaenable": "فعال کردن سیستم احراز هویت دو مرحله‌ای", + "tfaenabled": "فعال" + }, + "stats": { + "subtitle": "آمار کلی وبسایت", + "entries": "مدخل", + "uploads": "آپلودها", + "users": "کاربران" + }, + "settings": { + "subtitle": "مدیریت تنظیمات وبسایت" + }, + "system": { + "subtitle": "ابزارها و اطلاعات برای ویکی شما", + "systemversion": "نسخه سیستم", + "currentversion": "نسخه فعلی", + "latestversion": "آخرین نسخه", + "upgrade": "به روز رسانی", + "reinstall": "نصب مجدد نسخه فعلی", + "versioncheckfailed": "امکان پیدا کردن آخرین نسخه نرم افزار وجود ندارد. لطفا بعدا امتحان کنید.", + "administrativetools": "ابزارهای مدیریت", + "flushcache": "پاک کردن کش و بازسازی فهرست‌ها", + "flushcachetext": "اگر به نظر میرسد محتوای وبسایت به روز نیست یا آخرین تغییرات در آن وجود ندارد، پاک کردن کش احتمالا میتواند به حل این مشکل کمک کند.", + "flushcachebtn": "پاک کردن و بازسازی", + "resetaccounts": "ریست کردن حسابهای کاربری به حالت پیش‌فرض", + "resetaccountstext": "حسابهای کاربری سیستمی (مثل حساب مهمان) به حالت پیش‌فرض برخواهند گشت.", + "resetaccountsbtn": "ریست کردن حسابهای سیستمی", + "flushsessions": "پاک کردن نشست تمام کاربران آنلاین", + "flushsessionstext": "نشست تمام کاربرانی که در حال حاضر مشغول استفاده از وبسایت هستند پاک و باید مجددا وارد سیستم شوند.", + "flushsessionsbtn": "پاک‌کردن نشست‌ها", + "hostinfo": "اطلاعات مربوط به سیستم میزبان", + "os": "سیستم عامل", + "nodeversion": "نسخه نود‌جی‌اس", + "hostname": "نام میزبان", + "cores": "تعداد هسته‌های پردازنده", + "totalmem": "مجموع حافظه", + "cwd": "دایرکتوری کاری" + }, + "theme": { + "subtitle": "تغییر ظاهر وبسایت", + "primarycolor": "رنگ اصلی", + "primarycolordesc": "در نوار جهت‌یابی بالا، سرساز، پیوند‌ها و غیره استفاده میشود.", + "altcolor": "رنگ دوم", + "altcolordesc": "در نوارابزار گوشه استفاده میشود (با رنگ کمی تیره‌تر)", + "footercolor": "رنگ پاورقی", + "footercolordesc": "برای پاورقی پایین صفحه استفاده میشود (با رنگ کمی روشن‌تر)", + "codeblock": { + "title": "قطعات کد", + "dark": "استفاده از تم تیره", + "colorize": "رنگ‌آمیزی کد بر اساس سینتکس" + }, + "savechanges": "ذخیره تغییرات", + "reset": "برگشت تغییرات به وضعیت پیش‌فرض" + }, + "users": { + "createauthorize": "مدیریت کاربران", + "subtitle": "ایجاد یا تغییر دسترسی کاربران به وبسایت", + "name": "نام", + "email": "آدرس ایمیل", + "provider": "سرویس‌دهنده", + "createdon": "ساخته شده در تاریخ", + "updatedon": "به روز رسانی شده در تاریخ", + "returntousers": "بازگشت به لیست کاربران", + "edituser": "ویرایش کاربر", + "uniqueid": "شناسه یکتا" + } +} diff --git a/server/locales/fa/auth.json b/server/locales/fa/auth.json new file mode 100644 index 00000000..87e7d6a5 --- /dev/null +++ b/server/locales/fa/auth.json @@ -0,0 +1,32 @@ +{ + "loginrequired": "باید وارد سیستم شوید", + "loginusing": "وارد شدن به وسیله...", + "loginusingalt": "یا وارد شدن به وسیله...", + "fields": { + "emailuser": "ایمیل/شناسه کاربری", + "password": "گذرواژه" + }, + "actions": { + "login": "ورود" + }, + "errors": { + "invalidlogin": "شناسه کاربری نادرست", + "invalidloginmsg": "آدرس ایمیل یا گذرواژه نادرست است.", + "invaliduseremail": "آدرس ایمیل نادرست", + "loginerror": "خطا در ورود به سیستم", + "notyetauthorized": "هنوز اجازه ورود به وبسایت به شما داده نشده است.", + "toomanyattempts": "تلاش‌های ناموفق زیاد!", + "toomanyattemptsmsg": "شما در مدت زمان کوتاهی تلاشهای ناموفق بسیاری کرده‌اید. لطفا مجددا بعد از {{time}} امتحان کنید.", + "usernotfound": "کاربر پیدا نشد" + }, + "providers": { + "local": "محلی", + "windowslive": "حساب مایکروسافت", + "azure": "حساب اکتیو دایرکتوری اژر مایکروسافت", + "google": "حساب گوگل", + "facebook": "فیسبوک", + "github": "گیتهاب", + "slack": "اسلک", + "ldap": "ال‌دپ/اکتیو دایرکتوری" + } +} diff --git a/server/locales/fa/browser.json b/server/locales/fa/browser.json new file mode 100644 index 00000000..69b46747 --- /dev/null +++ b/server/locales/fa/browser.json @@ -0,0 +1,85 @@ +{ + "editor": { + "codeblockinsert": "وارد کردن بلوک کد", + "codeblocklanguage": "زبان", + "codeblockloading": "در حال بارگذاری سینتکس {{name}}", + "codeblockloadingerror": "خطا: امکان بارگذاری سینتکس برای این زبان وجود ندارد.", + "codeblocksuccess": "بلوک کد شما الحاق شد.", + "codeblocktitle": "الحاق بلوک کد", + "discard": "دور انداختن", + "filedeleteaction": "پاک کردن", + "filedeleteloading": "در حال پاک کردن فایل...", + "filedeletedefault": "این فایل", + "filedeletesuccess": "فایل با موفقیت پاک شد.", + "fileerror": "امکان دریافت فهرست به روز رسانی شده وجود ندارد.", + "filefolderempty": "این پوشه خالی است.", + "fileinsert": "افزودن لینک به فایل", + "fileloading": "در حال دریافت فایلها...", + "filemoveaction": "انتقال به...", + "filemoveerror": "خطا در انتقال: {{err}}", + "filemoveloading": "در حال انتقال فایل...", + "filemovesuccess": "فایل با موفقیت منتقل شد.", + "fileprocessing": "در حال پردازش...", + "filerenameaction": "تغییر نام", + "filesuccess": "پیوند به فایل الحاق شد.", + "filetitle": "الحاق فایل", + "fileupload": "بارگذاری فایل", + "fileuploaderror": "خطا در بارگذاری: {{err}}", + "fileuploadsuccess": "فایلها با موفقیت بارگذاری شدند.", + "folders": "پوشه‌ها", + "foldersloading": "در حال دریافت لیست پوشه‌ها...", + "imagetitle": "الحاق عکس", + "imageinsert": "الحاق عکس", + "imagesuccess": "عکس الحاق شد.", + "imageupload": "بارگذاری عکس", + "imagealignleft": "چپ (پیش‌فرض)", + "imagealigncenter": "مرکز", + "imagealignright": "راست", + "imagealignlogo": "لوگوی صفحه", + "newfolder": "پوشه جدید", + "videoanymp4file": "هر فایل ام‌پی‌۴ استاندارد", + "videoinsert": "الحاق ویدئو", + "videolinktitle": "برای قرار دادن ویدئوی توکار، پیوند ویدئو را وارد کنید:", + "videonotsupported": "این یوآرال نادرست است یا پشتیبانی نمی‌شود.", + "videosuccess": "کد ویدئو الحاق شد.", + "videosupportedtitle": "موارد زیر پشتیبانی میشوند:", + "videotitle": "الحاق ویدئو" + }, + "history": { + "pastversions": "نسخه‌های پیشین", + "timestamp": "زمان", + "author": "نویسنده", + "commit": "کامیت", + "comparewith": "مقایسه کن با...", + "view": "نمایش", + "reverttoversion": "برگرداندن به نسخه", + "sidebyside": "نمایش پهلو به پهلو" + }, + "modal": { + "abort": "قطع کردن", + "anchorerror": "کپی از کلیپ‌برد امکان‌پذیر نیست. لطفا پیوند را دستی وارد کنید.", + "anchorsuccess": "یوآرال در کلیپ‌برد کپی شد.", + "anchortitle": "پیوند به این قسمت را کپی کن", + "copyclipboard": "کپی در کلیپ‌برد", + "create": "ایجاد", + "createpageinvalid": "مسیر این صفحه نادرست است.", + "createpagepath": "مسیر جدید صفحه را وارد کنید:", + "createpagetitle": "ایجاد صفحه جدید", + "createuser": "ایجاد حساب کاربری", + "createuserauthorize": "دسترسی دادن به کاربر", + "createuseremail": "آدرس ایمیل:", + "createuseremailplaceholder": "مثلا john.doe@company.com", + "createusername": "نام کامل:", + "createusernameplaceholder": "مثلا علی علوی", + "createuserpassword": "گذرواژه:", + "createuserprovider": "سرویس‌دهنده:", + "createusertitle": "ساخت حساب کاربری", + "delete": "پاک کردن", + "deletefiletitle": "پاک شود؟", + "deletefilewarn": "آیا مطمئن هستید که میخواهید پاک شود؟", + "deleteusertitle": "حساب کاربری پاک شود؟", + "deleteuserwarning": "آیا مطمئن هستید که میخواهید حساب کاربری شود؟ این عمل قابل بازگشت نیست.", + "discard": "دور انداختن", + "discardpagecreate": "آیا مطمئن هستید که میخواهید از این صفحه بروید؟ تمام چیزهایی که تا این لحظه نوشتید از بین میروند." + } +} diff --git a/server/modules/auth.js b/server/modules/auth.js index 95befaeb..7dd41afb 100644 --- a/server/modules/auth.js +++ b/server/modules/auth.js @@ -33,6 +33,8 @@ module.exports = { // Load authentication strategies + wiki.config.auth.strategies.local = {} + _.forOwn(wiki.config.auth.strategies, (strategyConfig, strategyKey) => { strategyConfig.callbackURL = `${wiki.config.site.host}${wiki.config.site.path}/login/${strategyKey}/callback` let strategy = require(`../authentication/${strategyKey}`) From cbe39102c3b6daa2a4db5d08f876125064b3d71a Mon Sep 17 00:00:00 2001 From: NGPixel Date: Mon, 11 Sep 2017 21:52:10 -0400 Subject: [PATCH 21/33] fix: login ldap detection --- server/controllers/auth.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/controllers/auth.js b/server/controllers/auth.js index 317938a3..cb320ddc 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -1,5 +1,3 @@ -'use strict' - /* global wiki */ const Promise = require('bluebird') @@ -8,6 +6,7 @@ const router = express.Router() const ExpressBrute = require('express-brute') const ExpressBruteRedisStore = require('express-brute-redis') const moment = require('moment') +const _ = require('lodash') /** * Setup Express-Brute From 16a47e46cec7fb59bdb1f7fb0e554e70b0976b3f Mon Sep 17 00:00:00 2001 From: NGPixel Date: Fri, 22 Sep 2017 21:33:09 -0400 Subject: [PATCH 22/33] feat: login UI - vector + dynamic colors --- assets/svg/login-bg-dark.svg | 7 ++++ assets/svg/login-bg.svg | 7 ++++ client/scss/pages/_login.scss | 69 +++++++++++++++++++++++------------ server/controllers/auth.js | 4 +- server/views/auth/login.pug | 6 +-- 5 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 assets/svg/login-bg-dark.svg create mode 100644 assets/svg/login-bg.svg diff --git a/assets/svg/login-bg-dark.svg b/assets/svg/login-bg-dark.svg new file mode 100644 index 00000000..8ab32dde --- /dev/null +++ b/assets/svg/login-bg-dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/login-bg.svg b/assets/svg/login-bg.svg new file mode 100644 index 00000000..bb1c6ffb --- /dev/null +++ b/assets/svg/login-bg.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/client/scss/pages/_login.scss b/client/scss/pages/_login.scss index 440148c0..017ea4dd 100644 --- a/client/scss/pages/_login.scss +++ b/client/scss/pages/_login.scss @@ -1,22 +1,41 @@ .login { - background-size: cover; - background-position: center center; - background-image: url('../images/bg.jpg'); + background-image: linear-gradient(to right, mc('blue', '400'), mc('blue', '600')); width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; + &.is-error { + background-image: linear-gradient(to right, mc('red', '400'), mc('red', '600')); + } + + &::before { + content: ''; + position: absolute; + background-image: url('../svg/login-bg.svg'); + background-position: center bottom; + background-size: cover; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + } + &-container { position: relative; display: flex; - width: 450px; + width: 400px; align-items: stretch; - box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); + box-shadow: 0 14px 28px rgba(0,0,0,0.2); + border-radius: 6px; &.is-expanded { width: 650px; + + .login-frame { + border-radius: 0 6px 6px 0; + } } @include until($tablet) { @@ -30,22 +49,24 @@ &-error { position: absolute; - bottom: 100%; + bottom: 105%; width: 100%; min-height: 50px; - background-image: radial-gradient(ellipse at top left, rgba(mc('red', '900'),.9) 0%,rgba(mc('red', '400'),.8) 100%); - border: 1px solid #FFF; - color: #FFF; + background-image: radial-gradient(ellipse at top left, rgba(255,255,255,.9) 0%,rgba(255,255,255,.8) 100%); + box-shadow: 0 5px 10px rgba(0,0,0,0.2); + border-radius: 6px; + color: mc('red', '800'); display: flex; justify-content: center; align-items: center; + padding: 1rem; strong { font-weight: 600; text-transform: uppercase; display: block; padding: 0 1rem 0 0; - border-right: 1px solid #FFF; + border-right: 1px solid mc('red', '200'); } span { padding: 0 0 0 1rem; @@ -57,9 +78,12 @@ display: flex; flex-direction: column; width: 250px; - border: 1px solid #FFF; + + border-right: none; + border-radius: 6px 0 0 6px; background-color: mc('grey', '900'); z-index: 1; + overflow: hidden; @include until($tablet) { width: 50px; @@ -70,8 +94,8 @@ padding: 5px 15px; border: none; color: #FFF; - background-color: mc('grey', '800'); - border-top: 1px solid mc('grey', '900'); + background-color: mc('light-blue', '800'); + border-top: 1px solid mc('light-blue', '900'); font-family: $core-font-standard; font-weight: 600; text-align: left; @@ -86,7 +110,7 @@ } &:hover { - background-color: mc('grey', '600'); + background-color: mc('light-blue', '600'); } &:first-child { @@ -96,7 +120,7 @@ &.is-active { background-color: mc('grey', '100'); background-image: radial-gradient(circle at top left, rgba(mc('grey', '200'),1) 0%,rgba(255,255,255,1) 100%); - color: mc('grey', '700'); + color: mc('light-blue', '700'); } i { @@ -137,8 +161,8 @@ } &-frame { - background-image: radial-gradient(circle at top left, rgba(255,255,255,1) 0%,rgba(240,240,240,.6) 100%); - border: 1px solid #FFF; + background-image: radial-gradient(circle at top left, rgba(255,255,255,1) 5%,rgba(240,240,240,.6) 100%); + border-radius: 6px; width: 400px; padding: 1rem; color: mc('grey', '700'); @@ -154,7 +178,7 @@ h1 { font-size: 2rem; font-weight: 600; - color: mc('grey', '700'); + color: mc('light-blue', '700'); padding: 0; margin: 0; } @@ -176,7 +200,7 @@ width: 100%; border: 1px solid #FFF; border-radius: 3px; - background-color: rgba(255,255,255,.7); + background-color: rgba(255,255,255,.9); padding: 0 15px; height: 40px; margin: 0 0 10px 0; @@ -188,7 +212,7 @@ &:focus { outline: none; - border-color: mc('grey','400'); + border-color: mc('light-blue','500'); } } @@ -204,13 +228,12 @@ bottom: 10vh; width: 100%; z-index: 2; - color: #FFF; + color: mc('grey', '500'); font-weight: 400; - text-shadow: 1px 1px 0 #000; a { font-weight: 600; - color: #FFF; + color: mc('light-blue', '500'); margin-left: .25rem; } diff --git a/server/controllers/auth.js b/server/controllers/auth.js index cb320ddc..9188102a 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -35,8 +35,8 @@ const bruteforce = new ExpressBrute(EBstore, { */ router.get('/login', function (req, res, next) { res.render('auth/login', { - authStrategies: wiki.auth.strategies, - hasMultipleStrategies: Object.keys(wiki.config.auth.strategies).length > 0 + authStrategies: _.reject(wiki.auth.strategies, { key: 'local' }), + hasMultipleStrategies: Object.keys(wiki.config.auth.strategies).length > 1 }) }) diff --git a/server/views/auth/login.pug b/server/views/auth/login.pug index fad51aff..982036e6 100644 --- a/server/views/auth/login.pug +++ b/server/views/auth/login.pug @@ -2,8 +2,8 @@ extends ../master.pug block body body - .login#root - .login-container(:class={ "is-expanded": hasMultipleStrategies }) + .login#root(class={ "is-error": flash.length > 0 }) + .login-container(class={ "is-expanded": hasMultipleStrategies }) if flash.length > 0 .login-error strong @@ -25,7 +25,7 @@ block body form(method='post', action='/login') input#login-user(type='text', name='email', placeholder=t('auth:fields.emailuser')) input#login-pass(type='password', name='password', placeholder=t('auth:fields.password')) - button.button.is-light-green.is-fullwidth(type='submit') + button.button.is-light-blue.is-fullwidth(type='submit') span= t('auth:actions.login') .login-copyright = t('footer.poweredby') From 32b794770414818bff96fad0621219e5b960b4fd Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 24 Sep 2017 23:22:33 -0400 Subject: [PATCH 23/33] feat: GraphQL translations + login form --- client/js/app.js | 43 ++-- client/js/components/login.vue | 50 ++++ client/js/modules/localization.js | 57 +++++ client/scss/base/base.scss | 7 +- client/scss/pages/_login.scss | 7 +- package.json | 7 +- server/authentication/azure.js | 1 + server/authentication/facebook.js | 1 + server/authentication/github.js | 1 + server/authentication/google.js | 1 + server/authentication/ldap.js | 1 + server/authentication/local.js | 1 + server/authentication/microsoft.js | 1 + server/authentication/slack.js | 1 + server/master.js | 52 +--- server/modules/graphql.js | 2 + server/modules/localization.js | 52 ++++ server/schemas/resolvers-comment.js | 1 - server/schemas/resolvers-document.js | 1 - server/schemas/resolvers-file.js | 1 - server/schemas/resolvers-folder.js | 1 - server/schemas/resolvers-group.js | 1 - server/schemas/resolvers-right.js | 1 - server/schemas/resolvers-setting.js | 1 - server/schemas/resolvers-tag.js | 1 - server/schemas/resolvers-translation.js | 12 + server/schemas/resolvers-user.js | 1 - server/schemas/scalar-date.js | 1 - server/schemas/types.graphql | 6 + server/views/auth/login.pug | 30 +-- server/views/layout.pug | 2 +- yarn.lock | 308 +++++++----------------- 32 files changed, 314 insertions(+), 339 deletions(-) create mode 100644 client/js/components/login.vue create mode 100644 client/js/modules/localization.js create mode 100644 server/modules/localization.js create mode 100644 server/schemas/resolvers-translation.js diff --git a/client/js/app.js b/client/js/app.js index 00991909..a42068a1 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -6,10 +6,14 @@ import Vue from 'vue' import VueResource from 'vue-resource' import VueClipboards from 'vue-clipboards' +import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client' import store from './store' -import i18next from 'i18next' -import i18nextXHR from 'i18next-xhr-backend' -import VueI18Next from '@panter/vue-i18next' + +// ==================================== +// Load Modules +// ==================================== + +import localization from './modules/localization' // ==================================== // Load Helpers @@ -29,6 +33,7 @@ import editorFileComponent from './components/editor-file.vue' import editorVideoComponent from './components/editor-video.vue' import historyComponent from './components/history.vue' import loadingSpinnerComponent from './components/loading-spinner.vue' +import loginComponent from './components/login.vue' import modalCreatePageComponent from './components/modal-create-page.vue' import modalCreateUserComponent from './components/modal-create-user.vue' import modalDeleteUserComponent from './components/modal-delete-user.vue' @@ -49,13 +54,24 @@ import contentViewComponent from './pages/content-view.component.js' import editorComponent from './components/editor.component.js' import sourceViewComponent from './pages/source-view.component.js' +// ==================================== +// Initialize Apollo Client (GraphQL) +// ==================================== + +window.apollo = new ApolloClient({ + networkInterface: createBatchingNetworkInterface({ + uri: window.location.protocol + '//' + window.location.host + siteConfig.path + '/graphql' + }), + connectToDevTools: true +}) + // ==================================== // Initialize Vue Modules // ==================================== Vue.use(VueResource) Vue.use(VueClipboards) -Vue.use(VueI18Next) +Vue.use(localization.VueI18Next) Vue.use(helpers) // ==================================== @@ -76,6 +92,7 @@ Vue.component('editorFile', editorFileComponent) Vue.component('editorVideo', editorVideoComponent) Vue.component('history', historyComponent) Vue.component('loadingSpinner', loadingSpinnerComponent) +Vue.component('login', loginComponent) Vue.component('modalCreatePage', modalCreatePageComponent) Vue.component('modalCreateUser', modalCreateUserComponent) Vue.component('modalDeleteUser', modalDeleteUserComponent) @@ -89,20 +106,6 @@ Vue.component('sourceView', sourceViewComponent) Vue.component('toggle', toggleComponent) Vue.component('tree', treeComponent) -// ==================================== -// Load Localization strings -// ==================================== - -i18next - .use(i18nextXHR) - .init({ - backend: { - loadPath: siteConfig.path + '/js/i18n/{{lng}}.json' - }, - lng: siteConfig.lang, - fallbackLng: siteConfig.lang - }) - document.addEventListener('DOMContentLoaded', ev => { // ==================================== // Notifications @@ -116,13 +119,13 @@ document.addEventListener('DOMContentLoaded', ev => { // Bootstrap Vue // ==================================== - const i18n = new VueI18Next(i18next) + const i18n = localization.init() window.wiki = new Vue({ mixins: [helpers], components: {}, store, i18n, - el: '#root', + el: '#app', methods: { changeTheme(opts) { this.$el.className = `has-stickynav is-primary-${opts.primary} is-alternate-${opts.alt}` diff --git a/client/js/components/login.vue b/client/js/components/login.vue new file mode 100644 index 00000000..3a56be6b --- /dev/null +++ b/client/js/components/login.vue @@ -0,0 +1,50 @@ + + + + diff --git a/client/js/modules/localization.js b/client/js/modules/localization.js new file mode 100644 index 00000000..cf696af1 --- /dev/null +++ b/client/js/modules/localization.js @@ -0,0 +1,57 @@ +import i18next from 'i18next' +import i18nextXHR from 'i18next-xhr-backend' +import i18nextCache from 'i18next-localstorage-cache' +import gql from 'graphql-tag' +import VueI18Next from '@panter/vue-i18next' +import loSet from 'lodash/set' + +/* global siteConfig */ + +module.exports = { + VueI18Next, + init() { + i18next + .use(i18nextXHR) + .use(i18nextCache) + .init({ + backend: { + loadPath: '{{lng}}/{{ns}}', + parse: (data) => data, + ajax: (url, opts, cb, data) => { + let langParams = url.split('/') + console.info(langParams) + window.apollo.query({ + query: gql` + { + translations(locale:"${langParams[0]}", namespace:"${langParams[1]}") { + key + value + } + } + ` + }).then(resp => { + let ns = {} + if (resp.data.translations.length > 0) { + resp.data.translations.forEach(entry => { + loSet(ns, entry.key, entry.value) + }) + } + return cb(ns, {status: '200'}) + }).catch(err => { + console.error(err) + return cb(null, {status: '404'}) + }) + } + }, + cache: { + enabled: true, + expiration: 60 * 60 * 1000 + }, + defaultNS: 'common', + lng: siteConfig.lang, + fallbackLng: siteConfig.lang, + ns: ['common', 'admin', 'auth'] + }) + return new VueI18Next(i18next) + } +} diff --git a/client/scss/base/base.scss b/client/scss/base/base.scss index 6d8a688e..54740abe 100644 --- a/client/scss/base/base.scss +++ b/client/scss/base/base.scss @@ -11,10 +11,15 @@ html { display: none; } -#root { +#app { padding-bottom: 67px; position: relative; min-height: 100%; + + &.is-fullscreen { + width: 100vw; + height: 100vh; + } } body { diff --git a/client/scss/pages/_login.scss b/client/scss/pages/_login.scss index 017ea4dd..be4bd602 100644 --- a/client/scss/pages/_login.scss +++ b/client/scss/pages/_login.scss @@ -81,7 +81,6 @@ border-right: none; border-radius: 6px 0 0 6px; - background-color: mc('grey', '900'); z-index: 1; overflow: hidden; @@ -94,8 +93,8 @@ padding: 5px 15px; border: none; color: #FFF; - background-color: mc('light-blue', '800'); - border-top: 1px solid mc('light-blue', '900'); + background: linear-gradient(to right, rgba(mc('light-blue', '800'), .7), rgba(mc('light-blue', '800'), 1)); + border-top: 1px solid rgba(mc('light-blue', '900'), .5); font-family: $core-font-standard; font-weight: 600; text-align: left; @@ -110,7 +109,7 @@ } &:hover { - background-color: mc('light-blue', '600'); + background-color: mc('light-blue', '900'); } &:first-child { diff --git a/package.json b/package.json index 7e27ce96..05737b09 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "connect-redis": "3.3.0", "cookie-parser": "1.4.3", "diff2html": "2.3.0", + "dotize": "^0.2.0", "execa": "0.8.0", "express": "4.15.4", "express-brute": "1.0.1", @@ -68,6 +69,7 @@ "highlight.js": "9.12.0", "i18next": "9.0.0", "i18next-express-middleware": "1.0.5", + "i18next-localstorage-cache": "^1.1.1", "i18next-node-fs-backend": "1.0.0", "image-size": "0.6.1", "ioredis": "3.1.4", @@ -105,7 +107,6 @@ "passport-local": "1.0.0", "passport-slack": "0.0.7", "passport-windowslive": "1.0.2", - "passport.socketio": "3.7.0", "pg": "7.3.0", "pg-hstore": "2.3.2", "pg-promise": "6.5.2", @@ -120,7 +121,6 @@ "sequelize": "4.8.2", "serve-favicon": "2.4.3", "simplemde": "1.11.2", - "socket.io": "2.0.3", "stopword": "0.1.7", "stream-to-promise": "2.2.0", "tar": "4.0.1", @@ -133,6 +133,7 @@ "devDependencies": { "@glimpse/glimpse": "0.22.15", "@panter/vue-i18next": "0.5.1", + "apollo-client": "^1.9.3", "babel-cli": "6.26.0", "babel-jest": "21.0.2", "babel-plugin-transform-object-assign": "6.22.0", @@ -147,6 +148,7 @@ "eslint-plugin-promise": "3.5.0", "eslint-plugin-standard": "3.0.1", "fuse-box": "^2.2.31", + "graphql-tag": "^2.4.2", "i18next-xhr-backend": "1.4.2", "jest": "21.0.2", "jquery": "3.2.1", @@ -166,6 +168,7 @@ "vue": "2.4.2", "vue-clipboards": "1.1.0", "vue-lodash": "1.0.3", + "vue-material": "^0.7.5", "vue-resource": "1.3.4", "vue-template-compiler": "2.4.2", "vue-template-es2015-compiler": "1.5.3", diff --git a/server/authentication/azure.js b/server/authentication/azure.js index c6d71b4d..70e23cc4 100644 --- a/server/authentication/azure.js +++ b/server/authentication/azure.js @@ -11,6 +11,7 @@ const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy module.exports = { key: 'azure', title: 'Azure Active Directory', + useForm: false, props: ['clientId', 'clientSecret', 'callbackURL', 'resource', 'tenant'], init (passport, conf) { const jwt = require('jsonwebtoken') diff --git a/server/authentication/facebook.js b/server/authentication/facebook.js index 03375dac..24b31416 100644 --- a/server/authentication/facebook.js +++ b/server/authentication/facebook.js @@ -11,6 +11,7 @@ const FacebookStrategy = require('passport-facebook').Strategy module.exports = { key: 'facebook', title: 'Facebook', + useForm: false, props: ['clientId', 'clientSecret', 'callbackURL'], init (passport, conf) { passport.use('facebook', diff --git a/server/authentication/github.js b/server/authentication/github.js index ff3aec3b..2dbca0c4 100644 --- a/server/authentication/github.js +++ b/server/authentication/github.js @@ -11,6 +11,7 @@ const GitHubStrategy = require('passport-github2').Strategy module.exports = { key: 'github', title: 'GitHub', + useForm: false, props: ['clientId', 'clientSecret', 'callbackURL'], init (passport, conf) { passport.use('github', diff --git a/server/authentication/google.js b/server/authentication/google.js index 371f4c30..d353e6c4 100644 --- a/server/authentication/google.js +++ b/server/authentication/google.js @@ -11,6 +11,7 @@ const GoogleStrategy = require('passport-google-oauth20').Strategy module.exports = { key: 'google', title: 'Google ID', + useForm: false, props: ['clientId', 'clientSecret', 'callbackURL'], init (passport, conf) { passport.use('google', diff --git a/server/authentication/ldap.js b/server/authentication/ldap.js index c7a993db..720b5f4b 100644 --- a/server/authentication/ldap.js +++ b/server/authentication/ldap.js @@ -12,6 +12,7 @@ const fs = require('fs') module.exports = { key: 'ldap', title: 'LDAP / Active Directory', + useForm: true, props: ['url', 'bindDn', 'bindCredentials', 'searchBase', 'searchFilter', 'tlsEnabled', 'tlsCertPath'], init (passport, conf) { passport.use('ldapauth', diff --git a/server/authentication/local.js b/server/authentication/local.js index 1c4c7c07..e2ca7faa 100644 --- a/server/authentication/local.js +++ b/server/authentication/local.js @@ -11,6 +11,7 @@ const LocalStrategy = require('passport-local').Strategy module.exports = { key: 'local', title: 'Local', + useForm: true, props: [], init (passport, conf) { passport.use('local', diff --git a/server/authentication/microsoft.js b/server/authentication/microsoft.js index e8069de2..20e3e1d9 100644 --- a/server/authentication/microsoft.js +++ b/server/authentication/microsoft.js @@ -11,6 +11,7 @@ const WindowsLiveStrategy = require('passport-windowslive').Strategy module.exports = { key: 'microsoft', title: 'Microsoft Account', + useForm: false, props: ['clientId', 'clientSecret', 'callbackURL'], init (passport, conf) { passport.use('windowslive', diff --git a/server/authentication/slack.js b/server/authentication/slack.js index 17b7e0ae..e4aa6d5f 100644 --- a/server/authentication/slack.js +++ b/server/authentication/slack.js @@ -11,6 +11,7 @@ const SlackStrategy = require('passport-slack').Strategy module.exports = { key: 'slack', title: 'Slack', + useForm: false, props: ['clientId', 'clientSecret', 'callbackURL'], init (passport, conf) { passport.use('slack', diff --git a/server/master.js b/server/master.js index 9199bc71..f4350edf 100644 --- a/server/master.js +++ b/server/master.js @@ -20,7 +20,7 @@ module.exports = Promise.join( wiki.disk = require('./modules/disk').init() wiki.docs = require('./modules/documents').init() wiki.git = require('./modules/git').init(false) - wiki.lang = require('i18next') + wiki.lang = require('./modules/localization').init() wiki.mark = require('./modules/markdown') wiki.search = require('./modules/search').init() wiki.upl = require('./modules/uploads').init() @@ -37,13 +37,10 @@ module.exports = Promise.join( const favicon = require('serve-favicon') const flash = require('connect-flash') const http = require('http') - const i18nBackend = require('i18next-node-fs-backend') const path = require('path') - const passportSocketIo = require('passport.socketio') const session = require('express-session') const SessionRedisStore = require('connect-redis')(session) const graceful = require('node-graceful') - const socketio = require('socket.io') const graphqlApollo = require('apollo-server-express') const graphqlSchema = require('./modules/graphql') @@ -100,23 +97,6 @@ module.exports = Promise.join( app.use(mw.seo) - // ---------------------------------------- - // Localization Engine - // ---------------------------------------- - - wiki.lang.use(i18nBackend).init({ - load: 'languageOnly', - ns: ['common', 'admin', 'auth', 'errors', 'git'], - defaultNS: 'common', - saveMissing: false, - preload: [wiki.config.site.lang], - lng: wiki.config.site.lang, - fallbackLng: 'en', - backend: { - loadPath: path.join(wiki.SERVERPATH, 'locales/{{lng}}/{{ns}}.json') - } - }) - // ---------------------------------------- // View Engine Setup // ---------------------------------------- @@ -133,7 +113,7 @@ module.exports = Promise.join( app.locals.basedir = wiki.ROOTPATH app.locals._ = require('lodash') - app.locals.t = wiki.lang.t.bind(wiki.lang) + app.locals.t = wiki.lang.engine.t.bind(wiki.lang) app.locals.moment = require('moment') app.locals.moment.locale(wiki.config.site.lang) app.locals.config = wiki.config @@ -173,11 +153,10 @@ module.exports = Promise.join( // Start HTTP server // ---------------------------------------- - wiki.logger.info(`HTTP/WS Server on port: ${wiki.config.port}`) + wiki.logger.info(`HTTP Server on port: ${wiki.config.port}`) app.set('port', wiki.config.port) - var server = http.createServer(app) - var io = socketio(server) + let server = http.createServer(app) server.listen(wiki.config.port) server.on('error', (error) => { @@ -199,35 +178,14 @@ module.exports = Promise.join( }) server.on('listening', () => { - wiki.logger.info('HTTP/WS Server: RUNNING') + wiki.logger.info('HTTP Server: RUNNING') }) - // ---------------------------------------- - // WebSocket - // ---------------------------------------- - - io.use(passportSocketIo.authorize({ - key: 'wikijs.sid', - store: sessionStore, - secret: wiki.config.site.sessionSecret, - cookieParser, - success: (data, accept) => { - accept() - }, - fail: (data, message, error, accept) => { - accept() - } - })) - - io.on('connection', ctrl.ws) - // ---------------------------------------- // Graceful shutdown // ---------------------------------------- graceful.on('exit', () => { - // wiki.logger.info('- SHUTTING DOWN - Terminating Background Agent...') - // bgAgent.kill() wiki.logger.info('- SHUTTING DOWN - Performing git sync...') return global.git.resync().then(() => { wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.') diff --git a/server/modules/graphql.js b/server/modules/graphql.js index e1897390..e625afe6 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -17,6 +17,7 @@ const FolderResolvers = require('../schemas/resolvers-folder') const GroupResolvers = require('../schemas/resolvers-group') const SettingResolvers = require('../schemas/resolvers-setting') const TagResolvers = require('../schemas/resolvers-tag') +const TranslationResolvers = require('../schemas/resolvers-translation') const UserResolvers = require('../schemas/resolvers-user') const resolvers = _.merge( @@ -27,6 +28,7 @@ const resolvers = _.merge( GroupResolvers, SettingResolvers, TagResolvers, + TranslationResolvers, UserResolvers, DateScalar ) diff --git a/server/modules/localization.js b/server/modules/localization.js new file mode 100644 index 00000000..d832935b --- /dev/null +++ b/server/modules/localization.js @@ -0,0 +1,52 @@ +const _ = require('lodash') +const dotize = require('dotize') +const i18nBackend = require('i18next-node-fs-backend') +const i18next = require('i18next') +const path = require('path') +const Promise = require('bluebird') + +/* global wiki */ + +module.exports = { + engine: null, + namespaces: ['common', 'admin', 'auth', 'errors', 'git'], + init() { + this.engine = i18next + this.engine.use(i18nBackend).init({ + load: 'languageOnly', + ns: this.namespaces, + defaultNS: 'common', + saveMissing: false, + preload: [wiki.config.site.lang], + lng: wiki.config.site.lang, + fallbackLng: 'en', + backend: { + loadPath: path.join(wiki.SERVERPATH, 'locales/{{lng}}/{{ns}}.json') + } + }) + return this + }, + getByNamespace(locale, namespace) { + if (this.engine.hasResourceBundle(locale, namespace)) { + let data = this.engine.getResourceBundle(locale, namespace) + return _.map(dotize.convert(data), (value, key) => { + return { + key, + value + } + }) + } else { + throw new Error('Invalid locale or namespace') + } + }, + loadLocale(locale) { + return Promise.fromCallback(cb => { + return this.engine.loadLanguages(locale, cb) + }) + }, + setCurrentLocale(locale) { + return Promise.fromCallback(cb => { + return this.engine.changeLanguage(locale, cb) + }) + } +} diff --git a/server/schemas/resolvers-comment.js b/server/schemas/resolvers-comment.js index f8d00ee2..fec565b3 100644 --- a/server/schemas/resolvers-comment.js +++ b/server/schemas/resolvers-comment.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-document.js b/server/schemas/resolvers-document.js index 666f8fef..41dc9160 100644 --- a/server/schemas/resolvers-document.js +++ b/server/schemas/resolvers-document.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-file.js b/server/schemas/resolvers-file.js index c1011d95..c8913413 100644 --- a/server/schemas/resolvers-file.js +++ b/server/schemas/resolvers-file.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-folder.js b/server/schemas/resolvers-folder.js index 4acf2806..b7fc9a2b 100644 --- a/server/schemas/resolvers-folder.js +++ b/server/schemas/resolvers-folder.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-group.js b/server/schemas/resolvers-group.js index 61afc2d0..cc9b10b7 100644 --- a/server/schemas/resolvers-group.js +++ b/server/schemas/resolvers-group.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-right.js b/server/schemas/resolvers-right.js index 72e42b76..3b286deb 100644 --- a/server/schemas/resolvers-right.js +++ b/server/schemas/resolvers-right.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-setting.js b/server/schemas/resolvers-setting.js index 1ece4a0e..dc0c4f9e 100644 --- a/server/schemas/resolvers-setting.js +++ b/server/schemas/resolvers-setting.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-tag.js b/server/schemas/resolvers-tag.js index ad11f674..0aa3e89e 100644 --- a/server/schemas/resolvers-tag.js +++ b/server/schemas/resolvers-tag.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/resolvers-translation.js b/server/schemas/resolvers-translation.js new file mode 100644 index 00000000..aed8d57d --- /dev/null +++ b/server/schemas/resolvers-translation.js @@ -0,0 +1,12 @@ + +/* global wiki */ + +module.exports = { + Query: { + translations (obj, args, context, info) { + return wiki.lang.getByNamespace(args.locale, args.namespace) + } + }, + Mutation: {}, + Translation: {} +} diff --git a/server/schemas/resolvers-user.js b/server/schemas/resolvers-user.js index 694306e2..90133707 100644 --- a/server/schemas/resolvers-user.js +++ b/server/schemas/resolvers-user.js @@ -1,4 +1,3 @@ -'use strict' /* global wiki */ diff --git a/server/schemas/scalar-date.js b/server/schemas/scalar-date.js index 6fa5b585..472312ad 100644 --- a/server/schemas/scalar-date.js +++ b/server/schemas/scalar-date.js @@ -1,4 +1,3 @@ -'use strict' const gql = require('graphql') diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index 4f5cc929..99bbbf33 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -114,6 +114,11 @@ type Tag implements Base { documents: [Document] } +type Translation { + key: String! + value: String! +} + # A User type User implements Base { id: Int! @@ -142,6 +147,7 @@ type Query { rights(id: Int): [Right] settings(key: String): [Setting] tags(key: String): [Tag] + translations(locale: String!, namespace: String!): [Translation] users(id: Int, email: String, provider: String, providerId: String, role: UserRole): [User] } diff --git a/server/views/auth/login.pug b/server/views/auth/login.pug index 982036e6..44ebc019 100644 --- a/server/views/auth/login.pug +++ b/server/views/auth/login.pug @@ -2,31 +2,5 @@ extends ../master.pug block body body - .login#root(class={ "is-error": flash.length > 0 }) - .login-container(class={ "is-expanded": hasMultipleStrategies }) - if flash.length > 0 - .login-error - strong - i.icon-warning-outline - = flash[0].title - span= flash[0].message - if hasMultipleStrategies - .login-providers - button.is-active(title=t('auth:providers.local')) - i.nc-icon-outline.ui-1_database - span= t('auth:providers.local') - each strategy in authStrategies - button(onclick='window.location.assign("/login/' + strategy.key + '")', title=strategy.title) - != strategy.icon - span= strategy.title - .login-frame - h1= config.site.title - h2= t('auth:loginrequired') - form(method='post', action='/login') - input#login-user(type='text', name='email', placeholder=t('auth:fields.emailuser')) - input#login-pass(type='password', name='password', placeholder=t('auth:fields.password')) - button.button.is-light-blue.is-fullwidth(type='submit') - span= t('auth:actions.login') - .login-copyright - = t('footer.poweredby') - a(href='https://wiki.js.org', rel='external', title='Wiki.js') Wiki.js + #app.is-fullscreen + login diff --git a/server/views/layout.pug b/server/views/layout.pug index 49d4747a..1d704f7e 100644 --- a/server/views/layout.pug +++ b/server/views/layout.pug @@ -2,7 +2,7 @@ extends ./master.pug block body body - #root.has-stickynav(class=['is-primary-' + appconfig.theme.primary, 'is-alternate-' + appconfig.theme.alt]) + #app.has-stickynav(class=['is-primary-' + appconfig.theme.primary, 'is-alternate-' + appconfig.theme.alt]) include ./common/header.pug alert main diff --git a/yarn.lock b/yarn.lock index 0a625c96..28796802 100644 --- a/yarn.lock +++ b/yarn.lock @@ -79,6 +79,10 @@ version "1.0.2" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.2.tgz#b02d10ab028e2928ac592a051aaa4981a1941d03" +"@types/graphql@0.10.2": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.10.2.tgz#d7c79acbaa17453b6681c80c34b38fcb10c4c08c" + "@types/graphql@^0.9.0": version "0.9.4" resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.4.tgz#cdeb6bcbef9b6c584374b81aa7f48ecf3da404fa" @@ -151,13 +155,6 @@ abstract-leveldown@~2.6.1: dependencies: xtend "~4.0.0" -accepts@1.3.3, accepts@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" - dependencies: - mime-types "~2.1.11" - negotiator "0.6.1" - accepts@~1.2.12: version "1.2.13" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" @@ -165,6 +162,13 @@ accepts@~1.2.12: mime-types "~2.1.6" negotiator "0.5.3" +accepts@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" + dependencies: + mime-types "~2.1.11" + negotiator "0.6.1" + acorn-es7-plugin@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz#f2ee1f3228a90eead1245f9ab1922eb2e71d336b" @@ -209,10 +213,6 @@ acorn@^5.0.3, acorn@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75" -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - ajax-request@^1.2.0: version "1.2.3" resolved "https://registry.yarnpkg.com/ajax-request/-/ajax-request-1.2.3.tgz#99fcbec1d6d2792f85fa949535332bd14f5f3790" @@ -329,6 +329,28 @@ ap@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" +apollo-client@^1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.9.3.tgz#37000b3c801f4571b7b089739e696a158896aeab" + dependencies: + apollo-link-core "^0.5.0" + graphql "^0.10.0" + graphql-anywhere "^3.0.1" + graphql-tag "^2.0.0" + redux "^3.4.0" + symbol-observable "^1.0.2" + whatwg-fetch "^2.0.0" + optionalDependencies: + "@types/graphql" "0.10.2" + +apollo-link-core@^0.5.0: + version "0.5.4" + resolved "https://registry.yarnpkg.com/apollo-link-core/-/apollo-link-core-0.5.4.tgz#8efd4cd747959872a32f313f0ccfc2a76b396668" + dependencies: + graphql "^0.10.3" + graphql-tag "^2.4.2" + zen-observable-ts "^0.4.4" + apollo-server-core@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.1.0.tgz#74c3bf4394e14eae7ab60b1d999a3c5b8aa94e9a" @@ -435,10 +457,6 @@ array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" -arraybuffer.slice@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" - arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -1090,10 +1108,6 @@ babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - backoff@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" @@ -1104,10 +1118,6 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" - base64-img@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/base64-img/-/base64-img-1.0.3.tgz#a8c0284900047103421e1f9e0214011333866806" @@ -1119,10 +1129,6 @@ base64-js@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" -base64id@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" - base64url@2.0.0, base64url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/base64url/-/base64url-2.0.0.tgz#eac16e03ea1438eff9423d69baa36262ed1f70bb" @@ -1144,12 +1150,6 @@ bcryptjs@^2.3.0, bcryptjs@^2.4.0: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - dependencies: - callsite "1.0.0" - bignumber.js@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" @@ -1176,10 +1176,6 @@ blessed@^0.1.81: version "0.1.81" resolved "https://registry.yarnpkg.com/blessed/-/blessed-0.1.81.tgz#f962d687ec2c369570ae71af843256e6d0ca1129" -blob@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" - block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -1350,10 +1346,6 @@ caller-path@^0.1.0: dependencies: callsites "^0.2.0" -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" @@ -1637,18 +1629,6 @@ commander@2.8.x: dependencies: graceful-readlink ">= 1.0.0" -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - compressible@~2.0.10: version "2.0.10" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.10.tgz#feda1c7f7617912732b29bf8cf26252a20b9eecd" @@ -1920,18 +1900,12 @@ de-indent@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" -debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6: +debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: ms "2.0.0" -debug@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" - dependencies: - ms "0.7.2" - debug@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e" @@ -2131,6 +2105,10 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" +dotize@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dotize/-/dotize-0.2.0.tgz#69e52f4a2b13344c56ff23c703c3074a2d6e57c7" + dottie@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.0.tgz#da191981c8b8d713ca0115d5898cf397c2f0ddd0" @@ -2230,46 +2208,6 @@ end-of-stream@~1.1.0: dependencies: once "~1.3.0" -engine.io-client@~3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.1.tgz#415a9852badb14fa008fa3ef1e31608db6761325" - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~2.6.4" - engine.io-parser "~2.1.1" - has-cors "1.1.0" - indexof "0.0.1" - parsejson "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~2.3.1" - xmlhttprequest-ssl "1.5.3" - yeast "0.1.2" - -engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.1.tgz#e0fb3f0e0462f7f58bb77c1a52e9f5a7e26e4668" - dependencies: - after "0.8.2" - arraybuffer.slice "0.0.6" - base64-arraybuffer "0.1.5" - blob "0.0.4" - has-binary2 "~1.0.2" - -engine.io@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.0.tgz#5ca438e3ce9fdbc915c4a21c8dd9e1266706e57e" - dependencies: - accepts "1.3.3" - base64id "1.0.0" - cookie "0.3.1" - debug "~2.6.4" - engine.io-parser "~2.1.0" - ws "~2.3.1" - optionalDependencies: - uws "~0.14.4" - entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" @@ -3241,6 +3179,14 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +graphql-anywhere@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz#3ea0d8e8646b5cee68035016a9a7557c15c21e96" + +graphql-tag@^2.0.0, graphql-tag@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.4.2.tgz#6a63297d8522d03a2b72d26f1b239aab343840cd" + graphql-tools@1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.2.tgz#ff791e91b78e05eec18a32716a7732bc7bf5cb4d" @@ -3265,6 +3211,12 @@ graphql@0.11.3: dependencies: iterall "^1.1.0" +graphql@^0.10.0, graphql@^0.10.3: + version "0.10.5" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" + dependencies: + iterall "^1.1.0" + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -3296,16 +3248,6 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-binary2@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.2.tgz#e83dba49f0b9be4d026d27365350d9f03f54be98" - dependencies: - isarray "2.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -3436,6 +3378,10 @@ i18next-express-middleware@1.0.5: dependencies: cookies "0.6.1" +i18next-localstorage-cache@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/i18next-localstorage-cache/-/i18next-localstorage-cache-1.1.1.tgz#575256cc35e8cb2d88148f754766fdd2d24bb1b7" + i18next-node-fs-backend@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/i18next-node-fs-backend/-/i18next-node-fs-backend-1.0.0.tgz#f5a625a3b287c1d098c7171b7dd376bb07299b59" @@ -3501,10 +3447,6 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - inflection@1.12.0: version "1.12.0" resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" @@ -3825,10 +3767,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -4573,7 +4511,7 @@ lodash-cli@4.17.4: semver "5.3.0" uglify-js "2.7.5" -lodash-es@4.17.4: +lodash-es@4.17.4, lodash-es@^4.2.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" @@ -4787,7 +4725,7 @@ lodash.values@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" -lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.4: +lodash@4.17.4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4805,7 +4743,7 @@ longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -loose-envify@^1.0.0: +loose-envify@^1.0.0, loose-envify@^1.1.0: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: @@ -5102,10 +5040,6 @@ ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" - ms@2.0.0, ms@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -5377,14 +5311,10 @@ object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" -object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@~4.1.1: +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" - object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" @@ -5594,24 +5524,6 @@ parse5@^3.0.1: dependencies: "@types/node" "^6.0.46" -parsejson@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" - dependencies: - better-assert "~1.0.0" - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - dependencies: - better-assert "~1.0.0" - parseurl@^1.3.0, parseurl@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" @@ -5704,12 +5616,6 @@ passport-windowslive@1.0.2: dependencies: passport-oauth2 "1.x.x" -passport.socketio@3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/passport.socketio/-/passport.socketio-3.7.0.tgz#2ee5fafe9695d4281c8cddd3fe975ecd18e6726e" - dependencies: - xtend "^4.0.0" - passport@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.0.tgz#c5095691347bd5ad3b5e180238c3914d16f05811" @@ -6458,6 +6364,15 @@ reduce-flatten@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-1.0.1.tgz#258c78efd153ddf93cb561237f61184f3696e327" +redux@^3.4.0: + version "3.7.2" + resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" + dependencies: + lodash "^4.2.1" + lodash-es "^4.2.1" + loose-envify "^1.1.0" + symbol-observable "^1.0.3" + regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" @@ -6651,7 +6566,7 @@ rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" -safe-buffer@5.0.1, safe-buffer@~5.0.1: +safe-buffer@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" @@ -6965,50 +6880,6 @@ sntp@1.x.x: dependencies: hoek "2.x.x" -socket.io-adapter@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.0.tgz#c7aa46501dd556c2cb8a28af8ff95c0b5e1daa4c" - dependencies: - debug "2.3.3" - -socket.io-client@~2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.3.tgz#6caf4aff9f85b19fd91b6ce13d69adb564f8873b" - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~2.6.4" - engine.io-client "~3.1.0" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.1.1" - to-array "0.1.4" - -socket.io-parser@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.2.tgz#dbc2282151fc4faebbe40aeedc0772eba619f7f2" - dependencies: - component-emitter "1.2.1" - debug "~2.6.4" - has-binary2 "~1.0.2" - isarray "2.0.1" - -socket.io@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.0.3.tgz#4359f06a24933ae6bd087798af78c680eae345e3" - dependencies: - debug "~2.6.6" - engine.io "~3.1.0" - object-assign "~4.1.1" - socket.io-adapter "~1.1.0" - socket.io-client "~2.0.2" - socket.io-parser "~3.1.1" - source-map-support@^0.4.15, source-map-support@^0.4.2: version "0.4.15" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" @@ -7235,6 +7106,10 @@ supports-color@^4.0.0, supports-color@^4.2.0: dependencies: has-flag "^2.0.0" +symbol-observable@^1.0.2, symbol-observable@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" + symbol-tree@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -7399,10 +7274,6 @@ tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - to-fast-properties@^1.0.1, to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -7551,10 +7422,6 @@ ultron@1.0.x: version "1.0.2" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" -ultron@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.0.tgz#b07a2e6a541a815fc6a34ccd4533baec307ca864" - undefsafe@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-0.0.3.tgz#ecca3a03e56b9af17385baac812ac83b994a962f" @@ -7655,10 +7522,6 @@ uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" -uws@~0.14.4: - version "0.14.5" - resolved "https://registry.yarnpkg.com/uws/-/uws-0.14.5.tgz#67aaf33c46b2a587a5f6666d00f7691328f149dc" - v8flags@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" @@ -7750,6 +7613,10 @@ vue-lodash@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/vue-lodash/-/vue-lodash-1.0.3.tgz#777ef3e190a4cdde0d211a614e52a0b38659c13f" +vue-material@^0.7.5: + version "0.7.5" + resolved "https://registry.yarnpkg.com/vue-material/-/vue-material-0.7.5.tgz#045517403c1338aceabd73030f3dd6b5c744fe55" + vue-resource@1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.3.4.tgz#9fc0bdf6a2f5cab430129fc99d347b3deae7b099" @@ -7826,7 +7693,7 @@ whatwg-encoding@^1.0.1: dependencies: iconv-lite "0.4.13" -whatwg-fetch@^2.0.3: +whatwg-fetch@^2.0.0, whatwg-fetch@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" @@ -7951,13 +7818,6 @@ ws@^1.1.1: options ">=0.0.5" ultron "1.0.x" -ws@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-2.3.1.tgz#6b94b3e447cb6a363f785eaf94af6359e8e81c80" - dependencies: - safe-buffer "~5.0.1" - ultron "~1.1.0" - xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" @@ -7992,10 +7852,6 @@ xmlbuilder@^4.1.0: dependencies: lodash "^4.0.0" -xmlhttprequest-ssl@1.5.3: - version "1.5.3" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" - xtend@4.0.1, xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -8094,9 +7950,9 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" +zen-observable-ts@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.4.4.tgz#c244c71eaebef79a985ccf9895bc90307a6e9712" zone.js@0.7.6: version "0.7.6" From 51f5c236d6046536c2df13138b891acbe209a6c1 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Fri, 29 Sep 2017 22:32:43 -0400 Subject: [PATCH 24/33] feat: updated dependencies --- client/js/components/login.vue | 2 +- package.json | 82 +-- server/schemas/types.graphql | 16 + yarn.lock | 1086 ++++++++++++++++++-------------- 4 files changed, 657 insertions(+), 529 deletions(-) diff --git a/client/js/components/login.vue b/client/js/components/login.vue index 3a56be6b..9db5f58c 100644 --- a/client/js/components/login.vue +++ b/client/js/components/login.vue @@ -39,7 +39,7 @@ export default { siteTitle() { return siteConfig.title } - } + }, methods: { selectProvider(key, useForm) { diff --git a/package.json b/package.json index 05737b09..cb7a94a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wiki", - "version": "1.0.5", + "version": "2.0.0", "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown", "main": "wiki.js", "scripts": { @@ -42,55 +42,55 @@ "axios": "0.16.2", "bcryptjs-then": "1.0.1", "bluebird": "3.5.0", - "body-parser": "1.18.0", - "bull": "3.1.0", + "body-parser": "1.18.2", + "bull": "3.2.0", "bunyan": "1.8.12", "cheerio": "1.0.0-rc.2", "child-process-promise": "2.2.1", "chokidar": "1.7.0", - "compression": "1.7.0", + "compression": "1.7.1", "connect-flash": "0.1.1", - "connect-redis": "3.3.0", + "connect-redis": "3.3.2", "cookie-parser": "1.4.3", "diff2html": "2.3.0", "dotize": "^0.2.0", "execa": "0.8.0", - "express": "4.15.4", + "express": "4.16.1", "express-brute": "1.0.1", "express-brute-redis": "0.0.1", - "express-session": "1.15.5", - "file-type": "6.1.0", + "express-session": "1.15.6", + "file-type": "6.2.0", "filesize.js": "1.0.2", "follow-redirects": "1.2.4", - "fs-extra": "4.0.1", + "fs-extra": "4.0.2", "git-wrapper2-promise": "0.2.9", - "graphql": "0.11.3", - "graphql-tools": "1.2.2", + "graphql": "0.11.6", + "graphql-tools": "1.2.3", "highlight.js": "9.12.0", "i18next": "9.0.0", - "i18next-express-middleware": "1.0.5", + "i18next-express-middleware": "1.0.6", "i18next-localstorage-cache": "^1.1.1", "i18next-node-fs-backend": "1.0.0", "image-size": "0.6.1", "ioredis": "3.1.4", "jimp": "0.2.28", - "js-yaml": "3.9.1", - "jsonwebtoken": "8.0.0", + "js-yaml": "3.10.0", + "jsonwebtoken": "8.0.1", "klaw": "2.1.0", "levelup": "1.3.9", "lodash": "4.17.4", "markdown-it": "8.4.0", "markdown-it-abbr": "1.0.4", "markdown-it-anchor": "4.0.0", - "markdown-it-attrs": "1.1.0", + "markdown-it-attrs": "1.2.0", "markdown-it-emoji": "1.4.0", "markdown-it-expand-tabs": "1.0.12", "markdown-it-external-links": "0.0.6", "markdown-it-footnote": "3.0.1", "markdown-it-mathjax": "2.0.0", "markdown-it-task-lists": "2.0.1", - "mathjax-node": "1.2.0", - "memdown": "1.2.7", + "mathjax-node": "1.2.1", + "memdown": "1.3.1", "mime-types": "2.1.17", "moment": "2.18.1", "moment-timezone": "0.5.13", @@ -101,7 +101,7 @@ "passport": "0.4.0", "passport-azure-ad-oauth2": "0.0.4", "passport-facebook": "2.1.1", - "passport-github2": "0.1.10", + "passport-github2": "0.1.11", "passport-google-oauth20": "1.0.0", "passport-ldapauth": "2.0.0", "passport-local": "1.0.0", @@ -109,48 +109,48 @@ "passport-windowslive": "1.0.2", "pg": "7.3.0", "pg-hstore": "2.3.2", - "pg-promise": "6.5.2", - "pm2": "2.6.1", + "pg-promise": "6.10.1", + "pm2": "2.7.1", "pug": "2.0.0-rc.4", "read-chunk": "2.1.0", "remove-markdown": "0.2.2", - "request": "2.81.0", + "request": "2.83.0", "search-index-adder": "0.3.9", "search-index-searcher": "0.2.10", "semver": "5.4.1", - "sequelize": "4.8.2", - "serve-favicon": "2.4.3", + "sequelize": "4.11.5", + "serve-favicon": "2.4.5", "simplemde": "1.11.2", - "stopword": "0.1.7", + "stopword": "0.1.8", "stream-to-promise": "2.2.0", "tar": "4.0.1", "through2": "2.0.3", - "validator": "8.2.0", + "validator": "9.0.0", "validator-as-promised": "1.0.2", "winston": "2.3.1", - "yargs": "8.0.2" + "yargs": "9.0.1" }, "devDependencies": { "@glimpse/glimpse": "0.22.15", - "@panter/vue-i18next": "0.5.1", + "@panter/vue-i18next": "0.6.1", "apollo-client": "^1.9.3", "babel-cli": "6.26.0", - "babel-jest": "21.0.2", + "babel-jest": "21.2.0", "babel-plugin-transform-object-assign": "6.22.0", "babel-preset-es2015": "6.24.1", "brace": "0.10.0", "colors": "1.1.2", "consolidate": "0.14.5", - "eslint": "4.6.1", + "eslint": "4.8.0", "eslint-config-standard": "10.2.1", "eslint-plugin-import": "2.7.0", - "eslint-plugin-node": "5.1.1", + "eslint-plugin-node": "5.2.0", "eslint-plugin-promise": "3.5.0", "eslint-plugin-standard": "3.0.1", - "fuse-box": "^2.2.31", + "fuse-box": "2.2.31", "graphql-tag": "^2.4.2", - "i18next-xhr-backend": "1.4.2", - "jest": "21.0.2", + "i18next-xhr-backend": "1.4.3", + "jest": "21.2.1", "jquery": "3.2.1", "jquery-contextmenu": "2.6.2", "jquery-simple-upload": "1.0.0", @@ -159,20 +159,20 @@ "lodash-cli": "4.17.4", "lodash-es": "4.17.4", "node-sass": "4.5.3", - "nodemon": "1.12.0", + "nodemon": "1.12.1", "pug-lint": "2.5.0", "twemoji-awesome": "1.0.6", - "typescript": "2.5.2", - "uglify-es": "3.0.28", - "vee-validate": "2.0.0-rc.14", - "vue": "2.4.2", + "typescript": "2.5.3", + "uglify-es": "3.1.2", + "vee-validate": "2.0.0-rc.18", + "vue": "2.4.4", "vue-clipboards": "1.1.0", - "vue-lodash": "1.0.3", + "vue-lodash": "1.0.4", "vue-material": "^0.7.5", "vue-resource": "1.3.4", - "vue-template-compiler": "2.4.2", + "vue-template-compiler": "2.4.4", "vue-template-es2015-compiler": "1.5.3", - "vuex": "2.4.0" + "vuex": "2.4.1" }, "jest": { "collectCoverage": false, diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index 99bbbf33..c6af303d 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -31,6 +31,14 @@ interface Base { # TYPES +type AuthenticationProvider { + id: String! + useForm: Boolean! + title: String! + props: [String] + config: String +} + type Comment implements Base { id: Int! createdAt: Date @@ -97,6 +105,12 @@ type Right implements Base { group: Group! } +type SearchResult { + path: String + title: String + tags: [String] +} + type Setting implements Base { id: Int! createdAt: Date @@ -139,12 +153,14 @@ type OperationResult { # Query (Read) type Query { + authentication(mode: String!): [AuthenticationProvider] comments(id: Int): [Comment] documents(id: Int, path: String): [Document] files(id: Int): [File] folders(id: Int, name: String): [Folder] groups(id: Int, name: String): [Group] rights(id: Int): [Right] + search(q: String, tags: [String]): [SearchResult] settings(key: String): [Setting] tags(key: String): [Tag] translations(locale: String!, namespace: String!): [Translation] diff --git a/yarn.lock b/yarn.lock index 28796802..d17a21c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -58,9 +58,9 @@ command-line-usage "^4.0.0" lodash "^4.15.0" -"@panter/vue-i18next@0.5.1": - version "0.5.1" - resolved "https://registry.yarnpkg.com/@panter/vue-i18next/-/vue-i18next-0.5.1.tgz#714bbeb62c25850231f2681ad11142d3c6e3c645" +"@panter/vue-i18next@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@panter/vue-i18next/-/vue-i18next-0.6.1.tgz#11228dd34e28db741c9c71ba90854afeb761b563" "@types/express-serve-static-core@*": version "4.0.49" @@ -137,9 +137,9 @@ abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" -abstract-leveldown@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" +abstract-leveldown@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.0.tgz#985052daf3d7d0ac0029dca8eb793f4cdd2a6834" dependencies: xtend "~4.0.0" @@ -169,6 +169,13 @@ accepts@~1.3.3: mime-types "~2.1.11" negotiator "0.6.1" +accepts@~1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" + dependencies: + mime-types "~2.1.16" + negotiator "0.6.1" + acorn-es7-plugin@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz#f2ee1f3228a90eead1245f9ab1922eb2e71d336b" @@ -231,6 +238,15 @@ ajv@^4.7.0, ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.1.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.3.tgz#c06f598778c44c6b161abafe3466b81ad1814ed2" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + json-schema-traverse "^0.3.0" + json-stable-stringify "^1.0.1" + ajv@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" @@ -325,10 +341,6 @@ anymatch@^1.3.0: arrify "^1.0.0" micromatch "^2.1.5" -ap@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" - apollo-client@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.9.3.tgz#37000b3c801f4571b7b089739e696a158896aeab" @@ -530,7 +542,11 @@ aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" -aws4@^1.2.1: +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" @@ -727,12 +743,12 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@21.0.2, babel-jest@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.0.2.tgz#817ea52c23f1c6c4b684d6960968416b6a9e9c6c" +babel-jest@21.2.0, babel-jest@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.2.0.tgz#2ce059519a9374a2c46f2455b6fbef5ad75d863e" dependencies: babel-plugin-istanbul "^4.0.0" - babel-preset-jest "^21.0.2" + babel-preset-jest "^21.2.0" babel-messages@^6.23.0: version "6.23.0" @@ -754,9 +770,13 @@ babel-plugin-istanbul@^4.0.0: istanbul-lib-instrument "^1.7.2" test-exclude "^4.1.1" -babel-plugin-jest-hoist@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.0.2.tgz#cfdce5bca40d772a056cb8528ad159c7bb4bb03d" +babel-plugin-jest-hoist@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.2.0.tgz#2cef637259bd4b628a6cace039de5fcd14dbb006" + +babel-plugin-syntax-object-rest-spread@^6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" @@ -990,11 +1010,12 @@ babel-preset-es2015@6.24.1: babel-plugin-transform-es2015-unicode-regex "^6.24.1" babel-plugin-transform-regenerator "^6.24.1" -babel-preset-jest@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.0.2.tgz#9db25def2329f49eace3f5ea0de42a0b898d12cc" +babel-preset-jest@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.2.0.tgz#ff9d2bce08abd98e8a36d9a8a5189b9173b85638" dependencies: - babel-plugin-jest-hoist "^21.0.2" + babel-plugin-jest-hoist "^21.2.0" + babel-plugin-syntax-object-rest-spread "^6.13.0" babel-register@^6.24.1: version "6.24.1" @@ -1190,19 +1211,19 @@ bmp-js@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a" -body-parser@1.18.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.0.tgz#d3b224d467fa2ce8d43589c0245043267c093634" +body-parser@1.18.2: + version "1.18.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" dependencies: bytes "3.0.0" - content-type "~1.0.2" - debug "2.6.8" + content-type "~1.0.4" + debug "2.6.9" depd "~1.1.1" http-errors "~1.6.2" - iconv-lite "0.4.18" + iconv-lite "0.4.19" on-finished "~2.3.0" - qs "6.5.0" - raw-body "2.3.1" + qs "6.5.1" + raw-body "2.3.2" type-is "~1.6.15" body-parser@^1.14.2: @@ -1230,6 +1251,18 @@ boom@2.x.x: dependencies: hoek "2.x.x" +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + boxen@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.2.1.tgz#0f11e7fe344edb9397977fc13ede7f64d956481d" @@ -1291,9 +1324,9 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bull@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bull/-/bull-3.1.0.tgz#5cdf4ee8b9b72c17c5b257d745f62479c40ca016" +bull@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/bull/-/bull-3.2.0.tgz#4fd186c4dba46ceb1743108042abe4013a3dd036" dependencies: bluebird "^3.5.0" cron-parser "^2.4.1" @@ -1332,10 +1365,6 @@ bytes@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" -bytes@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a" - bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -1629,23 +1658,23 @@ commander@2.8.x: dependencies: graceful-readlink ">= 1.0.0" -compressible@~2.0.10: - version "2.0.10" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.10.tgz#feda1c7f7617912732b29bf8cf26252a20b9eecd" +compressible@~2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a" dependencies: - mime-db ">= 1.27.0 < 2" + mime-db ">= 1.29.0 < 2" -compression@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.0.tgz#030c9f198f1643a057d776a738e922da4373012d" +compression@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db" dependencies: - accepts "~1.3.3" - bytes "2.5.0" - compressible "~2.0.10" - debug "2.6.8" + accepts "~1.3.4" + bytes "3.0.0" + compressible "~2.0.11" + debug "2.6.9" on-headers "~1.0.1" safe-buffer "5.1.1" - vary "~1.1.1" + vary "~1.1.2" concat-map@0.0.1: version "0.0.1" @@ -1687,11 +1716,11 @@ connect-flash@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/connect-flash/-/connect-flash-0.1.1.tgz#d8630f26d95a7f851f9956b1e8cc6732f3b6aa30" -connect-redis@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/connect-redis/-/connect-redis-3.3.0.tgz#c9510c1a567ff710eb2510e6a7509fa92b2232df" +connect-redis@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/connect-redis/-/connect-redis-3.3.2.tgz#3706f9bfef1ec9b5d11c4b35b265de42c218b408" dependencies: - debug "^2.2.0" + debug "^3.1.0" redis "^2.1.0" console-control-strings@^1.0.0, console-control-strings@~1.1.0: @@ -1731,6 +1760,10 @@ content-type@~1.0.1, content-type@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + continuation-local-storage@^3.1.4: version "3.2.0" resolved "https://registry.yarnpkg.com/continuation-local-storage/-/continuation-local-storage-3.2.0.tgz#e19fc36b597090a5d4e4a3b2ea3ebc5e29694a24" @@ -1765,12 +1798,12 @@ cookie@^0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.2.4.tgz#a8c155aa7b9b2cf2c4d32ebc7b9a0aa288ccc6bd" -cookies@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.6.1.tgz#ef693b1bc6f01f567d46e2f504e9c15fb70cba90" +cookies@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b" dependencies: - depd "~1.1.0" - keygrip "~1.0.0" + depd "~1.1.1" + keygrip "~1.0.2" core-js@^2.4.0: version "2.4.1" @@ -1814,13 +1847,6 @@ cron@1.2.1: dependencies: moment-timezone "^0.5.x" -cross-env@^3.1.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-3.2.4.tgz#9e0585f277864ed421ce756f81a980ff0d698aba" - dependencies: - cross-spawn "^5.1.0" - is-windows "^1.0.0" - cross-spawn@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" @@ -1849,6 +1875,12 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" @@ -1900,15 +1932,27 @@ de-indent@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" -debug@*, debug@2.6.8, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6, debug@^2.6.3, debug@^2.6.8: +debug@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e" + dependencies: + ms "2.0.0" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.4.5, debug@^2.6.3, debug@^2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: ms "2.0.0" -debug@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e" +debug@^3, debug@^3.0, debug@^3.0.1, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" @@ -2284,9 +2328,9 @@ eslint-plugin-import@2.7.0: minimatch "^3.0.3" read-pkg-up "^2.0.0" -eslint-plugin-node@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.1.1.tgz#a7ed956e780c22aef6afd1116005acd82f26eac6" +eslint-plugin-node@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.0.tgz#e1efca04a385516cff3f2f04027ce8c5ae6db749" dependencies: ignore "^3.3.3" minimatch "^3.0.4" @@ -2308,19 +2352,19 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@4.6.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.6.1.tgz#ddc7fc7fd70bf93205b0b3449bb16a1e9e7d4950" +eslint@4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.8.0.tgz#229ef0e354e0e61d837c7a80fdfba825e199815e" dependencies: ajv "^5.2.0" babel-code-frame "^6.22.0" chalk "^2.1.0" concat-stream "^1.6.0" cross-spawn "^5.1.0" - debug "^2.6.8" + debug "^3.0.1" doctrine "^2.0.0" eslint-scope "^3.7.1" - espree "^3.5.0" + espree "^3.5.1" esquery "^1.0.0" estraverse "^4.2.0" esutils "^2.0.2" @@ -2341,7 +2385,7 @@ eslint@4.6.1: natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^4.0.0" + pluralize "^7.0.0" progress "^2.0.0" require-uncached "^1.0.3" semver "^5.3.0" @@ -2350,9 +2394,9 @@ eslint@4.6.1: table "^4.0.1" text-table "~0.2.0" -espree@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d" +espree@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.1.tgz#0c988b8ab46db53100a1954ae4ba995ddd27d87e" dependencies: acorn "^5.1.1" acorn-jsx "^3.0.0" @@ -2398,6 +2442,10 @@ etag@~1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051" +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + event-stream@~3.3.0: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" @@ -2480,16 +2528,16 @@ expand-template@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a" -expect@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-21.0.2.tgz#b34abf0635ec9d6aea1ce7edb4722afe86c4a38f" +expect@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-21.2.1.tgz#003ac2ac7005c3c29e73b38a272d4afadd6d1d7b" dependencies: ansi-styles "^3.2.0" - jest-diff "^21.0.2" - jest-get-type "^21.0.2" - jest-matcher-utils "^21.0.2" - jest-message-util "^21.0.2" - jest-regex-util "^21.0.2" + jest-diff "^21.2.1" + jest-get-type "^21.2.0" + jest-matcher-utils "^21.2.1" + jest-message-util "^21.2.1" + jest-regex-util "^21.2.0" express-brute-redis@0.0.1: version "0.0.1" @@ -2513,52 +2561,54 @@ express-brute@~0.4.2: memcached "~0.2.4" underscore "~1.5.1" -express-session@1.15.5: - version "1.15.5" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.5.tgz#f49a18227263b316f6f8544da5fee25a540259ec" +express-session@1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.6.tgz#47b4160c88f42ab70fe8a508e31cbff76757ab0a" dependencies: cookie "0.3.1" cookie-signature "1.0.6" crc "3.4.4" - debug "2.6.8" + debug "2.6.9" depd "~1.1.1" on-headers "~1.0.1" - parseurl "~1.3.1" - uid-safe "~2.1.4" - utils-merge "1.0.0" + parseurl "~1.3.2" + uid-safe "~2.1.5" + utils-merge "1.0.1" -express@4.15.4: - version "4.15.4" - resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1" +express@4.16.1: + version "4.16.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.1.tgz#6b33b560183c9b253b7b62144df33a4654ac9ed0" dependencies: - accepts "~1.3.3" + accepts "~1.3.4" array-flatten "1.1.1" + body-parser "1.18.2" content-disposition "0.5.2" - content-type "~1.0.2" + content-type "~1.0.4" cookie "0.3.1" cookie-signature "1.0.6" - debug "2.6.8" + debug "2.6.9" depd "~1.1.1" encodeurl "~1.0.1" escape-html "~1.0.3" - etag "~1.8.0" - finalhandler "~1.0.4" - fresh "0.5.0" + etag "~1.8.1" + finalhandler "1.1.0" + fresh "0.5.2" merge-descriptors "1.0.1" methods "~1.1.2" on-finished "~2.3.0" - parseurl "~1.3.1" + parseurl "~1.3.2" path-to-regexp "0.1.7" - proxy-addr "~1.1.5" - qs "6.5.0" + proxy-addr "~2.0.2" + qs "6.5.1" range-parser "~1.2.0" - send "0.15.4" - serve-static "1.12.4" - setprototypeof "1.0.3" + safe-buffer "5.1.1" + send "0.16.1" + serve-static "1.13.1" + setprototypeof "1.1.0" statuses "~1.3.1" type-is "~1.6.15" - utils-merge "1.0.0" - vary "~1.1.1" + utils-merge "1.0.1" + vary "~1.1.2" express@^4.14.0: version "4.15.3" @@ -2623,7 +2673,7 @@ express@~4.13.1: utils-merge "1.0.0" vary "~1.0.1" -extend@^3.0.0, extend@~3.0.0: +extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -2683,14 +2733,10 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fclone@1.0.11: +fclone@1.0.11, fclone@^1: version "1.0.11" resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.11.tgz#10e85da38bfea7fc599341c296ee1d77266ee640" -fclone@1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.8.tgz#a0d4a73d983249978c0e0671a161520b996467eb" - feature-detect-es6@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/feature-detect-es6/-/feature-detect-es6-1.3.1.tgz#f888736af9cb0c91f55663bfa4762eb96ee7047f" @@ -2723,9 +2769,9 @@ file-system@^2.1.0, file-system@^2.1.1: file-match "^1.0.1" utils-extend "^1.0.4" -file-type@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.1.0.tgz#5a7dba98138fa0abec7afc43e5a9a0b2aac729f1" +file-type@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" file-type@^3.1.0: version "3.9.0" @@ -2765,23 +2811,23 @@ finalhandler@0.4.1: on-finished "~2.3.0" unpipe "~1.0.0" -finalhandler@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89" +finalhandler@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" dependencies: - debug "2.6.7" + debug "2.6.9" encodeurl "~1.0.1" escape-html "~1.0.3" on-finished "~2.3.0" - parseurl "~1.3.1" + parseurl "~1.3.2" statuses "~1.3.1" unpipe "~1.0.0" -finalhandler@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7" +finalhandler@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89" dependencies: - debug "2.6.8" + debug "2.6.7" encodeurl "~1.0.1" escape-html "~1.0.3" on-finished "~2.3.0" @@ -2870,10 +2916,22 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" +form-data@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + forwarded@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + fresh@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" @@ -2882,16 +2940,20 @@ fresh@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e" +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" -fs-extra@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880" +fs-extra@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b" dependencies: graceful-fs "^4.1.2" - jsonfile "^3.0.0" + jsonfile "^4.0.0" universalify "^0.1.0" fs-extra@^2.0.0: @@ -2998,13 +3060,9 @@ gaze@^1.0.0: dependencies: globule "^1.0.0" -generic-pool@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" - -generic-pool@^3.1.6: - version "3.1.7" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.1.7.tgz#dac22b2c7a7a04e41732f7d8d2d25a303c88f662" +generic-pool@^3.1.8: + version "3.1.8" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.1.8.tgz#09844b6545bc9177ec218bd35d4ad894c65be271" get-caller-file@^1.0.1: version "1.0.2" @@ -3187,9 +3245,9 @@ graphql-tag@^2.0.0, graphql-tag@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.4.2.tgz#6a63297d8522d03a2b72d26f1b239aab343840cd" -graphql-tools@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.2.tgz#ff791e91b78e05eec18a32716a7732bc7bf5cb4d" +graphql-tools@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.3.tgz#079bf4d157e46c0a0bae9fec117e0eea6e03ba2c" dependencies: deprecated-decorator "^0.1.6" uuid "^3.0.1" @@ -3205,13 +3263,7 @@ graphql-tools@^1.1.0: optionalDependencies: "@types/graphql" "^0.9.0" -graphql@0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.3.tgz#9934e2df28f17d397a85f83cb39d1d179bffef47" - dependencies: - iterall "^1.1.0" - -graphql@^0.10.0, graphql@^0.10.3: +graphql@0.10.5, graphql@^0.10.0, graphql@^0.10.3: version "0.10.5" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" dependencies: @@ -3235,6 +3287,10 @@ har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + har-validator@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" @@ -3242,6 +3298,13 @@ har-validator@~4.2.1: ajv "^4.9.1" har-schema "^1.0.5" +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -3292,6 +3355,15 @@ hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + he@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" @@ -3304,6 +3376,10 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" +hoek@4.x.x: + version "4.2.0" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + hogan.js@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" @@ -3372,11 +3448,19 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" -i18next-express-middleware@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.0.5.tgz#12dce7c553866e11c108943d46ce494baf982219" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +i18next-express-middleware@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.0.6.tgz#110782e9492931f35feffef434904847bf349128" dependencies: - cookies "0.6.1" + cookies "0.7.1" i18next-localstorage-cache@^1.1.1: version "1.1.1" @@ -3389,9 +3473,9 @@ i18next-node-fs-backend@1.0.0: js-yaml "3.5.4" json5 "0.5.0" -i18next-xhr-backend@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.2.tgz#7aa766292c46ca83ff6477bb55074b363a646a62" +i18next-xhr-backend@1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.3.tgz#d72f70536a3bf6a3892261dde352bc77d708886a" i18next@9.0.0: version "9.0.0" @@ -3405,7 +3489,11 @@ iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" -iconv-lite@0.4.18, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.18" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" @@ -3565,9 +3653,9 @@ ipaddr.js@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec" -ipaddr.js@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0" +ipaddr.js@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" is-arrayish@^0.2.1: version "0.2.1" @@ -3751,10 +3839,6 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -is-windows@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" - is@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" @@ -3861,15 +3945,15 @@ jackpot@>=0.0.6: dependencies: retry "0.6.0" -jest-changed-files@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.0.2.tgz#0a74f35cf2d3b7c8ef9ab4fac0a75409f81ec1b0" +jest-changed-files@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.2.0.tgz#5dbeecad42f5d88b482334902ce1cba6d9798d29" dependencies: throat "^4.0.0" -jest-cli@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.0.2.tgz#2e08af63d44fc21284ebf496cf71e381f3cc9786" +jest-cli@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.2.1.tgz#9c528b6629d651911138d228bdb033c157ec8c00" dependencies: ansi-escapes "^3.0.0" chalk "^2.0.1" @@ -3880,17 +3964,17 @@ jest-cli@^21.0.2: istanbul-lib-coverage "^1.0.1" istanbul-lib-instrument "^1.4.2" istanbul-lib-source-maps "^1.1.0" - jest-changed-files "^21.0.2" - jest-config "^21.0.2" - jest-environment-jsdom "^21.0.2" - jest-haste-map "^21.0.2" - jest-message-util "^21.0.2" - jest-regex-util "^21.0.2" - jest-resolve-dependencies "^21.0.2" - jest-runner "^21.0.2" - jest-runtime "^21.0.2" - jest-snapshot "^21.0.2" - jest-util "^21.0.2" + jest-changed-files "^21.2.0" + jest-config "^21.2.1" + jest-environment-jsdom "^21.2.1" + jest-haste-map "^21.2.0" + jest-message-util "^21.2.1" + jest-regex-util "^21.2.0" + jest-resolve-dependencies "^21.2.0" + jest-runner "^21.2.1" + jest-runtime "^21.2.1" + jest-snapshot "^21.2.1" + jest-util "^21.2.1" micromatch "^2.3.11" node-notifier "^5.0.2" pify "^3.0.0" @@ -3901,146 +3985,146 @@ jest-cli@^21.0.2: worker-farm "^1.3.1" yargs "^9.0.0" -jest-config@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.0.2.tgz#ea42b94f3c22ae4e4aa11c69f5b45e34e342199d" +jest-config@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.2.1.tgz#c7586c79ead0bcc1f38c401e55f964f13bf2a480" dependencies: chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^21.0.2" - jest-environment-node "^21.0.2" - jest-get-type "^21.0.2" - jest-jasmine2 "^21.0.2" - jest-regex-util "^21.0.2" - jest-resolve "^21.0.2" - jest-util "^21.0.2" - jest-validate "^21.0.2" - pretty-format "^21.0.2" - -jest-diff@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.0.2.tgz#751014f36ad5d505f6affce5542fde0e444ee50a" + jest-environment-jsdom "^21.2.1" + jest-environment-node "^21.2.1" + jest-get-type "^21.2.0" + jest-jasmine2 "^21.2.1" + jest-regex-util "^21.2.0" + jest-resolve "^21.2.0" + jest-util "^21.2.1" + jest-validate "^21.2.1" + pretty-format "^21.2.1" + +jest-diff@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.2.1.tgz#46cccb6cab2d02ce98bc314011764bb95b065b4f" dependencies: chalk "^2.0.1" diff "^3.2.0" - jest-get-type "^21.0.2" - pretty-format "^21.0.2" + jest-get-type "^21.2.0" + pretty-format "^21.2.1" -jest-docblock@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.0.2.tgz#66f69ddb440799fc32f91d0ac3d8d35e99e2032f" +jest-docblock@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" -jest-environment-jsdom@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.0.2.tgz#6f6ab5bd71970d1900fbd47a46701c0a07fa3be5" +jest-environment-jsdom@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.2.1.tgz#38d9980c8259b2a608ec232deee6289a60d9d5b4" dependencies: - jest-mock "^21.0.2" - jest-util "^21.0.2" + jest-mock "^21.2.0" + jest-util "^21.2.1" jsdom "^9.12.0" -jest-environment-node@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.0.2.tgz#4267ceb39551f8ecaed182ab882a93ef4d5de240" +jest-environment-node@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.2.1.tgz#98c67df5663c7fbe20f6e792ac2272c740d3b8c8" dependencies: - jest-mock "^21.0.2" - jest-util "^21.0.2" + jest-mock "^21.2.0" + jest-util "^21.2.1" -jest-get-type@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.0.2.tgz#304e6b816dd33cd1f47aba0597bcad258a509fc6" +jest-get-type@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23" -jest-haste-map@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.0.2.tgz#bd98bc6cd6f207eb029b2f5918da1a9347eb11b7" +jest-haste-map@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8" dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" - jest-docblock "^21.0.2" + jest-docblock "^21.2.0" micromatch "^2.3.11" sane "^2.0.0" worker-farm "^1.3.1" -jest-jasmine2@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.0.2.tgz#a368abb3a686def4d6e763509a265104943cd469" +jest-jasmine2@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.2.1.tgz#9cc6fc108accfa97efebce10c4308548a4ea7592" dependencies: chalk "^2.0.1" - expect "^21.0.2" + expect "^21.2.1" graceful-fs "^4.1.11" - jest-diff "^21.0.2" - jest-matcher-utils "^21.0.2" - jest-message-util "^21.0.2" - jest-snapshot "^21.0.2" + jest-diff "^21.2.1" + jest-matcher-utils "^21.2.1" + jest-message-util "^21.2.1" + jest-snapshot "^21.2.1" p-cancelable "^0.3.0" -jest-matcher-utils@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.0.2.tgz#eb6736a45b698546d71f7e1ffbbd36587eeb27bc" +jest-matcher-utils@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.2.1.tgz#72c826eaba41a093ac2b4565f865eb8475de0f64" dependencies: chalk "^2.0.1" - jest-get-type "^21.0.2" - pretty-format "^21.0.2" + jest-get-type "^21.2.0" + pretty-format "^21.2.1" -jest-message-util@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.0.2.tgz#81242e07d426ad54c15f3d7c55b072e9db7b39a9" +jest-message-util@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.2.1.tgz#bfe5d4692c84c827d1dcf41823795558f0a1acbe" dependencies: chalk "^2.0.1" micromatch "^2.3.11" slash "^1.0.0" -jest-mock@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.0.2.tgz#5e92902450e1ce78be3864cc4d50dbd5d1582fbd" +jest-mock@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.2.0.tgz#7eb0770e7317968165f61ea2a7281131534b3c0f" -jest-regex-util@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.0.2.tgz#06248c07b53ff444223ebe8e33a25bc051ac976f" +jest-regex-util@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.2.0.tgz#1b1e33e63143babc3e0f2e6c9b5ba1eb34b2d530" -jest-resolve-dependencies@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.0.2.tgz#c42cc371034023ac1a226a7a52f86233c8871938" +jest-resolve-dependencies@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.2.0.tgz#9e231e371e1a736a1ad4e4b9a843bc72bfe03d09" dependencies: - jest-regex-util "^21.0.2" + jest-regex-util "^21.2.0" -jest-resolve@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.0.2.tgz#57b2c20cbeca2357eb5e638d5c28beca7f38c3f8" +jest-resolve@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.2.0.tgz#068913ad2ba6a20218e5fd32471f3874005de3a6" dependencies: browser-resolve "^1.11.2" chalk "^2.0.1" is-builtin-module "^1.0.0" -jest-runner@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.0.2.tgz#1462d431d25f7744e8b5e03837bbf9e268dc8b15" - dependencies: - jest-config "^21.0.2" - jest-docblock "^21.0.2" - jest-haste-map "^21.0.2" - jest-jasmine2 "^21.0.2" - jest-message-util "^21.0.2" - jest-runtime "^21.0.2" - jest-util "^21.0.2" +jest-runner@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.2.1.tgz#194732e3e518bfb3d7cbfc0fd5871246c7e1a467" + dependencies: + jest-config "^21.2.1" + jest-docblock "^21.2.0" + jest-haste-map "^21.2.0" + jest-jasmine2 "^21.2.1" + jest-message-util "^21.2.1" + jest-runtime "^21.2.1" + jest-util "^21.2.1" pify "^3.0.0" throat "^4.0.0" worker-farm "^1.3.1" -jest-runtime@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.0.2.tgz#ce26ba06bcd5501991bd994b1eacc0c7c7913895" +jest-runtime@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.2.1.tgz#99dce15309c670442eee2ebe1ff53a3cbdbbb73e" dependencies: babel-core "^6.0.0" - babel-jest "^21.0.2" + babel-jest "^21.2.0" babel-plugin-istanbul "^4.0.0" chalk "^2.0.1" convert-source-map "^1.4.0" graceful-fs "^4.1.11" - jest-config "^21.0.2" - jest-haste-map "^21.0.2" - jest-regex-util "^21.0.2" - jest-resolve "^21.0.2" - jest-util "^21.0.2" + jest-config "^21.2.1" + jest-haste-map "^21.2.0" + jest-regex-util "^21.2.0" + jest-resolve "^21.2.0" + jest-util "^21.2.1" json-stable-stringify "^1.0.1" micromatch "^2.3.11" slash "^1.0.0" @@ -4048,43 +4132,43 @@ jest-runtime@^21.0.2: write-file-atomic "^2.1.0" yargs "^9.0.0" -jest-snapshot@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.0.2.tgz#5b8f4dd05c1759381db835451fba4bcd85a55611" +jest-snapshot@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.2.1.tgz#29e49f16202416e47343e757e5eff948c07fd7b0" dependencies: chalk "^2.0.1" - jest-diff "^21.0.2" - jest-matcher-utils "^21.0.2" + jest-diff "^21.2.1" + jest-matcher-utils "^21.2.1" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^21.0.2" + pretty-format "^21.2.1" -jest-util@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.0.2.tgz#3ee2380af25c414a39f07b23c84da6f2d5f1f76a" +jest-util@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.2.1.tgz#a274b2f726b0897494d694a6c3d6a61ab819bb78" dependencies: callsites "^2.0.0" chalk "^2.0.1" graceful-fs "^4.1.11" - jest-message-util "^21.0.2" - jest-mock "^21.0.2" - jest-validate "^21.0.2" + jest-message-util "^21.2.1" + jest-mock "^21.2.0" + jest-validate "^21.2.1" mkdirp "^0.5.1" -jest-validate@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.0.2.tgz#dd066b257bd102759c214747d73bed6bcfa4349d" +jest-validate@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7" dependencies: chalk "^2.0.1" - jest-get-type "^21.0.2" + jest-get-type "^21.2.0" leven "^2.1.0" - pretty-format "^21.0.2" + pretty-format "^21.2.1" -jest@21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/jest/-/jest-21.0.2.tgz#a5c9bdc9d4322ae672fe8cb3eaf25c268c5f04b2" +jest@21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-21.2.1.tgz#c964e0b47383768a1438e3ccf3c3d470327604e1" dependencies: - jest-cli "^21.0.2" + jest-cli "^21.2.1" jimp@0.2.28: version "0.2.28" @@ -4153,6 +4237,13 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +js-yaml@3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.5.4.tgz#f64f16dcd78beb9ce8361068e733ebe47b079179" @@ -4160,16 +4251,16 @@ js-yaml@3.5.4: argparse "^1.0.2" esprima "^2.6.0" -js-yaml@3.9.1, js-yaml@^3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" +js-yaml@^3.7.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.0.tgz#4ffbbf25c2ac963b8299dc74da7e3740de1c18ce" dependencies: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.7.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.0.tgz#4ffbbf25c2ac963b8299dc74da7e3740de1c18ce" +js-yaml@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4246,9 +4337,9 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" optionalDependencies: graceful-fs "^4.1.6" @@ -4260,13 +4351,12 @@ jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" -jsonwebtoken@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.0.0.tgz#7b241aa67c61b3d0b3e641254a9a6f5b66f550e8" +jsonwebtoken@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.0.1.tgz#50daef8d0a8c7de2cd06bc1013b75b04ccf3f0cf" dependencies: jws "^3.1.4" lodash.includes "^4.3.0" - lodash.isarray "^4.0.0" lodash.isboolean "^3.0.3" lodash.isinteger "^4.0.4" lodash.isnumber "^3.0.3" @@ -4309,9 +4399,9 @@ jws@^3.1.4: jwa "^1.1.4" safe-buffer "^5.0.1" -keygrip@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.1.tgz#b02fa4816eef21a8c4b35ca9e52921ffc89a30e9" +keygrip@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.2.tgz#ad3297c557069dea8bcfe7a4fa491b75c5ddeb91" kind-of@^3.0.2: version "3.2.2" @@ -4617,10 +4707,6 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" -lodash.isarray@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-4.0.0.tgz#2aca496b28c4ca6d726715313590c02e6ea34403" - lodash.isboolean@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" @@ -4809,9 +4895,9 @@ markdown-it-anchor@4.0.0: dependencies: string "^3.3.3" -markdown-it-attrs@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-1.1.0.tgz#6f5c7bc8d0c29e628ef335bcc1e0bf454d204f5d" +markdown-it-attrs@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-1.2.0.tgz#6baad67036a411483d5902c127d46ee229435484" markdown-it-emoji@1.4.0: version "1.4.0" @@ -4853,9 +4939,9 @@ marked@*: version "0.3.6" resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" -mathjax-node@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.2.0.tgz#538d01f85ca18b90f3cc6ce68c7caeed44bb9f7f" +mathjax-node@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/mathjax-node/-/mathjax-node-1.2.1.tgz#f4a0e272149104f2e00a3d268c81e42bee1324fd" dependencies: jsdom "7.0 - 9.12" mathjax "*" @@ -4885,11 +4971,11 @@ memcached@~0.2.4: hashring "0.0.x" jackpot ">=0.0.6" -memdown@1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.2.7.tgz#64f2d6b511724c016f3cbd5a40b84349da247b0f" +memdown@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.3.1.tgz#071499332e3a74b88c3d9551b0750d61fdf0c5b7" dependencies: - abstract-leveldown "2.6.3" + abstract-leveldown "2.7.0" functional-red-black-tree "^1.0.1" immediate "^3.2.3" inherits "~2.0.1" @@ -4940,19 +5026,15 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -"mime-db@>= 1.27.0 < 2": - version "1.29.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878" +"mime-db@>= 1.29.0 < 2", mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" mime-db@~1.27.0: version "1.27.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - -mime-types@2.1.17: +mime-types@2.1.17, mime-types@~2.1.16, mime-types@~2.1.17: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: @@ -4968,6 +5050,10 @@ mime@1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + mime@^1.3.4: version "1.3.6" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" @@ -5202,9 +5288,9 @@ node-version@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.0.0.tgz#1b9b9584a9a7f7a6123f215cd14a652bf21ab19e" -nodemon@1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.12.0.tgz#e538548a777340a19f855c4f087b7e528aa3feda" +nodemon@1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.12.1.tgz#996a56dc49d9f16bbf1b78a4de08f13634b3878d" dependencies: chokidar "^1.7.0" debug "^2.6.8" @@ -5295,7 +5381,7 @@ number-is-nan@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.1.tgz#7ae9b07b0ea804db7e25f05cb5fe4097d4e4949f" -oauth-sign@~0.8.1: +oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -5303,10 +5389,6 @@ oauth@0.9.x: version "0.9.15" resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" @@ -5528,6 +5610,10 @@ parseurl@^1.3.0, parseurl@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + passport-azure-ad-oauth2@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/passport-azure-ad-oauth2/-/passport-azure-ad-oauth2-0.0.4.tgz#1a09d8869efd4afd095116e228941961b3a5c120" @@ -5540,9 +5626,9 @@ passport-facebook@2.1.1: dependencies: passport-oauth2 "1.x.x" -passport-github2@0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/passport-github2/-/passport-github2-0.1.10.tgz#50a21c1e95b83113e4da32c81c2c1a64429bb5bd" +passport-github2@0.1.11: + version "0.1.11" + resolved "https://registry.yarnpkg.com/passport-github2/-/passport-github2-0.1.11.tgz#c92b56f3c38a44e766aac7e9e7c1384c5e93c999" dependencies: passport-oauth2 "1.x.x" @@ -5688,6 +5774,10 @@ performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + pg-connection-string@0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" @@ -5702,35 +5792,18 @@ pg-minify@~0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.5.3.tgz#aa09befa3cbe29fab6461bf819100e0471215011" -pg-pool@1.*: - version "1.8.0" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.8.0.tgz#f7ec73824c37a03f076f51bfdf70e340147c4f37" - dependencies: - generic-pool "2.4.3" - object-assign "4.1.0" - pg-pool@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257" -pg-promise@6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.5.2.tgz#84d18d8f14bd5a60bf8415d96c3c634e0d1745a2" +pg-promise@6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.10.1.tgz#56676a741ce5b7b9ee149070d7fd5c342555dff8" dependencies: manakin "~0.5.1" - pg "~6.4.2" + pg "~7.3.0" pg-minify "~0.5.3" - spex "~1.2.0" - -pg-types@1.*: - version "1.12.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" - dependencies: - ap "~0.2.0" - postgres-array "~1.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.0" - postgres-interval "^1.1.0" + spex "~2.0.0" pg-types@~1.12.1: version "1.12.1" @@ -5741,7 +5814,7 @@ pg-types@~1.12.1: postgres-date "~1.0.0" postgres-interval "^1.1.0" -pg@7.3.0: +pg@7.3.0, pg@~7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/pg/-/pg-7.3.0.tgz#275e27466e54a645f6b4a16f6acadf6b849ad83b" dependencies: @@ -5754,20 +5827,7 @@ pg@7.3.0: pgpass "1.x" semver "4.3.2" -pg@~6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.2.tgz#c364011060eac7a507a2ae063eb857ece910e27f" - dependencies: - buffer-writer "1.0.1" - js-string-escape "1.0.1" - packet-reader "0.3.1" - pg-connection-string "0.1.3" - pg-pool "1.*" - pg-types "1.*" - pgpass "1.*" - semver "4.3.2" - -pgpass@1.*, pgpass@1.x: +pgpass@1.x: version "1.0.2" resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" dependencies: @@ -5811,24 +5871,24 @@ pkginfo@0.2.x: version "0.2.3" resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.2.3.tgz#7239c42a5ef6c30b8f328439d9b9ff71042490f8" -pluralize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" -pm2-axon-rpc@0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/pm2-axon-rpc/-/pm2-axon-rpc-0.4.5.tgz#fb62e9a53f3e2b7bed1afe16e3b0d1b06fe8ba69" +pm2-axon-rpc@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pm2-axon-rpc/-/pm2-axon-rpc-0.5.0.tgz#ad08d6a27f580d5c7be4d7bf9dddff398f868994" dependencies: - debug "*" - fclone "1.0.8" + debug "^3.0" + fclone "^1" -pm2-axon@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/pm2-axon/-/pm2-axon-3.0.2.tgz#53de1d34edbf266d58f6b1dea2d8244c71ad24b9" +pm2-axon@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pm2-axon/-/pm2-axon-3.1.0.tgz#1b4527f3385e203adc1a5b0488bb52f0322731da" dependencies: amp "~0.3.1" amp-message "~0.1.1" - debug "~2.2.0" + debug "^3.0" escape-regexp "0.0.1" pm2-deploy@^0.3.5: @@ -5844,9 +5904,9 @@ pm2-multimeter@^0.1.2: dependencies: charm "~0.1.1" -pm2@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/pm2/-/pm2-2.6.1.tgz#a9c2fdb7bf1676655935eb4176239003fca5c8da" +pm2@2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/pm2/-/pm2-2.7.1.tgz#b7b8404d8bec587526fd58bc21feffea351bec15" dependencies: async "^2.5" blessed "^0.1.81" @@ -5855,7 +5915,7 @@ pm2@2.6.1: cli-table-redemption "^1.0.0" commander "2.11.0" cron "1.2.1" - debug "^2.6" + debug "^3.0" eventemitter2 "1.0.5" fclone "1.0.11" mkdirp "0.5.1" @@ -5863,26 +5923,26 @@ pm2@2.6.1: needle "1.6.0" nssocket "0.6.0" pidusage "^1.1.0" - pm2-axon "3.0.2" - pm2-axon-rpc "0.4.5" + pm2-axon "3.1.0" + pm2-axon-rpc "0.5.0" pm2-deploy "^0.3.5" pm2-multimeter "^0.1.2" - pmx "^1.2.0" + pmx "~1.5.0" promptly "2.2.0" semver "^5.3" shelljs "0.7.8" - source-map-support "^0.4.15" + source-map-support "^0.4.18" sprintf-js "1.1.1" vizion "^0.2" yamljs "0.3.0" optionalDependencies: gkt "https://tgz.pm2.io/gkt-1.0.0.tgz" -pmx@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pmx/-/pmx-1.2.0.tgz#712a9e1fdea53a9b061169cc7676b14838c87585" +pmx@~1.5.0: + version "1.5.4" + resolved "https://registry.yarnpkg.com/pmx/-/pmx-1.5.4.tgz#27d71c54e727b5186485545b9c70c21eabc81c0f" dependencies: - debug "^2.6" + debug "^3" json-stringify-safe "^5.0" vxx "^1.2.0" @@ -5951,9 +6011,9 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -pretty-format@^21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.0.2.tgz#76adcebd836c41ccd2e6b626e70f63050d2a3534" +pretty-format@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36" dependencies: ansi-regex "^3.0.0" ansi-styles "^3.2.0" @@ -6019,12 +6079,12 @@ proxy-addr@~1.1.4: forwarded "~0.1.0" ipaddr.js "1.3.0" -proxy-addr@~1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918" +proxy-addr@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" dependencies: - forwarded "~0.1.0" - ipaddr.js "1.4.0" + forwarded "~0.1.2" + ipaddr.js "1.5.2" prr@~0.0.0: version "0.0.0" @@ -6194,9 +6254,9 @@ qs@6.4.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -qs@6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" +qs@6.5.1, qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" random-bytes@~1.0.0: version "1.0.0" @@ -6217,13 +6277,13 @@ range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" -raw-body@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.1.tgz#30f95e2a67a14e2e4413d8d51fdd92c877e8f2ed" +raw-body@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" dependencies: bytes "3.0.0" http-errors "1.6.2" - iconv-lite "0.4.18" + iconv-lite "0.4.19" unpipe "1.0.0" raw-body@~2.2.0: @@ -6453,7 +6513,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2, request@2.81.0, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0: +request@2, request@^2.65.0, request@^2.67.0, request@^2.79.0, request@^2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" dependencies: @@ -6480,6 +6540,33 @@ request@2, request@2.81.0, request@^2.65.0, request@^2.67.0, request@^2.79.0, re tunnel-agent "^0.6.0" uuid "^3.0.0" +request@2.83.0: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -6516,12 +6603,11 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" -retry-as-promised@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-2.2.0.tgz#b0463d7fd3cf5b2fed64500ab6e8b8a49c5b8e6c" +retry-as-promised@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-2.3.1.tgz#f75059183f9730771c09bad1eed57537931cbc9d" dependencies: bluebird "^3.4.6" - cross-env "^3.1.2" debug "^2.2.0" retry@0.6.0: @@ -6566,10 +6652,6 @@ rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" -safe-buffer@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" - safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -6720,39 +6802,39 @@ send@0.15.3: range-parser "~1.2.0" statuses "~1.3.1" -send@0.15.4: - version "0.15.4" - resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9" +send@0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" dependencies: - debug "2.6.8" + debug "2.6.9" depd "~1.1.1" destroy "~1.0.4" encodeurl "~1.0.1" escape-html "~1.0.3" - etag "~1.8.0" - fresh "0.5.0" + etag "~1.8.1" + fresh "0.5.2" http-errors "~1.6.2" - mime "1.3.4" + mime "1.4.1" ms "2.0.0" on-finished "~2.3.0" range-parser "~1.2.0" statuses "~1.3.1" -sequelize@4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.8.2.tgz#d16a6e75e8b48303beab4787b946bf06f32f1a94" +sequelize@4.11.5: + version "4.11.5" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.11.5.tgz#2349994bc9027fdf05f45fa1e221ed5bc840c4b3" dependencies: bluebird "^3.4.6" cls-bluebird "^2.0.1" debug "^3.0.0" depd "^1.1.0" dottie "^2.0.0" - generic-pool "^3.1.6" + generic-pool "^3.1.8" inflection "1.12.0" lodash "^4.17.1" moment "^2.13.0" moment-timezone "^0.5.4" - retry-as-promised "^2.0.0" + retry-as-promised "^2.3.1" semver "^5.0.1" terraformer-wkt-parser "^1.1.2" toposort-class "^1.0.1" @@ -6760,15 +6842,15 @@ sequelize@4.8.2: validator "^8.0.0" wkx "^0.4.1" -serve-favicon@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.4.3.tgz#5986b17b0502642b641c21f818b1acce32025d23" +serve-favicon@2.4.5: + version "2.4.5" + resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.4.5.tgz#49d9a46863153a9240691c893d2b0e7d85d6d436" dependencies: - etag "~1.8.0" - fresh "0.5.0" + etag "~1.8.1" + fresh "0.5.2" ms "2.0.0" - parseurl "~1.3.1" - safe-buffer "5.0.1" + parseurl "~1.3.2" + safe-buffer "5.1.1" serve-static@1.12.3: version "1.12.3" @@ -6779,14 +6861,14 @@ serve-static@1.12.3: parseurl "~1.3.1" send "0.15.3" -serve-static@1.12.4: - version "1.12.4" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961" +serve-static@1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" dependencies: encodeurl "~1.0.1" escape-html "~1.0.3" - parseurl "~1.3.1" - send "0.15.4" + parseurl "~1.3.2" + send "0.16.1" serve-static@~1.10.2: version "1.10.3" @@ -6808,6 +6890,10 @@ setprototypeof@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -6880,12 +6966,24 @@ sntp@1.x.x: dependencies: hoek "2.x.x" +sntp@2.x.x: + version "2.0.2" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.0.2.tgz#5064110f0af85f7cfdb7d6b67a40028ce52b4b2b" + dependencies: + hoek "4.x.x" + source-map-support@^0.4.15, source-map-support@^0.4.2: version "0.4.15" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" dependencies: source-map "^0.5.6" +source-map-support@^0.4.18: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + source-map@0.4.x, source-map@^0.4.2, source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" @@ -6916,9 +7014,9 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" -spex@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/spex/-/spex-1.2.0.tgz#6264b3b8acbc444477f06dbb66d425c0ee1074c0" +spex@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spex/-/spex-2.0.0.tgz#63e1b8655159a32028eb6a237ffb0589e85f3c32" split@0.3: version "0.3.3" @@ -6972,9 +7070,9 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -stopword@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/stopword/-/stopword-0.1.7.tgz#4bf4f6bbb157f5ca43e4800559854943828563d6" +stopword@0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stopword/-/stopword-0.1.8.tgz#b583506b0218cb2966c77cc41cb92ffda8396eb9" stream-combiner@~0.0.4: version "0.0.4" @@ -7050,7 +7148,7 @@ string_decoder@~1.0.3: dependencies: safe-buffer "~5.1.0" -stringstream@~0.0.4: +stringstream@~0.0.4, stringstream@~0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -7298,6 +7396,12 @@ tough-cookie@^2.3.2, tough-cookie@~2.3.0: dependencies: punycode "^1.4.1" +tough-cookie@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + dependencies: + punycode "^1.4.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -7359,9 +7463,9 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34" +typescript@2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d" typical@^2.6.0, typical@^2.6.1: version "2.6.1" @@ -7375,9 +7479,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" -uglify-es@3.0.28: - version "3.0.28" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.0.28.tgz#1cdedbbcdb7865223065281ad7b2347629851d4b" +uglify-es@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.2.tgz#b22cfca950f0632092aff42bb46979d83b5ec6f5" dependencies: commander "~2.11.0" source-map "~0.5.1" @@ -7408,9 +7512,9 @@ uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" -uid-safe@~2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81" +uid-safe@~2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" dependencies: random-bytes "~1.0.0" @@ -7514,6 +7618,10 @@ utils-merge@1.0.0, utils-merge@1.x.x: version "1.0.0" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" @@ -7543,9 +7651,9 @@ validator-as-promised@1.0.2: lodash "^4.14.0" validator "^5.5.0" -validator@8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-8.2.0.tgz#3c1237290e37092355344fef78c231249dab77b9" +validator@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-9.0.0.tgz#6c1ef955e007af704adea86ae8a76da84a6c172e" validator@^5.5.0: version "5.7.0" @@ -7563,15 +7671,19 @@ vary@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + vasync@^1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/vasync/-/vasync-1.6.4.tgz#dfe93616ad0e7ae801b332a9d88bfc5cdc8e1d1f" dependencies: verror "1.6.0" -vee-validate@2.0.0-rc.14: - version "2.0.0-rc.14" - resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.14.tgz#ecbd3ddff33fa6a42ebb4a468c343e1eb5d2b38f" +vee-validate@2.0.0-rc.18: + version "2.0.0-rc.18" + resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-2.0.0-rc.18.tgz#30857abeb2ba87e52d3e66c09b35a78e66419527" verror@1.3.6: version "1.3.6" @@ -7609,9 +7721,9 @@ vue-clipboards@1.1.0: dependencies: clipboard "^1.7.1" -vue-lodash@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/vue-lodash/-/vue-lodash-1.0.3.tgz#777ef3e190a4cdde0d211a614e52a0b38659c13f" +vue-lodash@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vue-lodash/-/vue-lodash-1.0.4.tgz#99f4f2f5832ce0168c4d45618789288a638562cd" vue-material@^0.7.5: version "0.7.5" @@ -7623,9 +7735,9 @@ vue-resource@1.3.4: dependencies: got "^7.0.0" -vue-template-compiler@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.4.2.tgz#5a45d843f148b098f6c1d1e35ac20c4956d30ad1" +vue-template-compiler@2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.4.4.tgz#2cde3b704124985c27d50b5387c9691ba515fb57" dependencies: de-indent "^1.0.2" he "^1.1.0" @@ -7634,13 +7746,13 @@ vue-template-es2015-compiler@1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.3.tgz#22787de4e37ebd9339b74223bc467d1adee30545" -vue@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.4.2.tgz#a9855261f191c978cc0dc1150531b8d08149b58c" +vue@2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.4.4.tgz#ea9550b96a71465fd2b8b17b61673b3561861789" -vuex@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.4.0.tgz#e1d0430646282b40007fdd06ec6ae88a9f5a1e14" +vuex@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.4.1.tgz#7890b650ba8565b70937b4e7670577082dfe8bc1" vxx@^1.2.0: version "1.2.2" @@ -7887,9 +7999,9 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" -yargs@8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" +yargs@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c" dependencies: camelcase "^4.1.0" cliui "^3.2.0" From 501f0a9a536eba8b5edf7cfda443b359f0978c19 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 30 Sep 2017 23:47:14 -0400 Subject: [PATCH 25/33] feat: auth strategies over GraphQL + svg loading --- assets/svg/auth-icon-azure.svg | 9 ++++- assets/svg/auth-icon-local.svg | 8 +++++ client/js/app.js | 11 +++++- client/js/components/login.vue | 36 ++++++++++++++----- client/js/constants/graphql.js | 22 ++++++++++++ client/js/constants/index.js | 5 +++ client/js/modules/localization.js | 19 ++++------ client/scss/components/button.scss | 6 +++- client/scss/pages/_login.scss | 30 ++++++++++++++-- server/authentication/microsoft.js | 2 +- server/modules/graphql.js | 2 ++ server/schemas/resolvers-authentication.js | 40 ++++++++++++++++++++++ server/schemas/types.graphql | 3 +- 13 files changed, 165 insertions(+), 28 deletions(-) create mode 100644 assets/svg/auth-icon-local.svg create mode 100644 client/js/constants/graphql.js create mode 100644 client/js/constants/index.js create mode 100644 server/schemas/resolvers-authentication.js diff --git a/assets/svg/auth-icon-azure.svg b/assets/svg/auth-icon-azure.svg index cf13b912..13f1c52e 100644 --- a/assets/svg/auth-icon-azure.svg +++ b/assets/svg/auth-icon-azure.svg @@ -1 +1,8 @@ - \ No newline at end of file + + + + + + + + diff --git a/assets/svg/auth-icon-local.svg b/assets/svg/auth-icon-local.svg new file mode 100644 index 00000000..da2fe997 --- /dev/null +++ b/assets/svg/auth-icon-local.svg @@ -0,0 +1,8 @@ + + + + + diff --git a/client/js/app.js b/client/js/app.js index a42068a1..cd4f94c9 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -3,6 +3,8 @@ /* global siteConfig */ /* eslint-disable no-new */ +import CONSTANTS from './constants' + import Vue from 'vue' import VueResource from 'vue-resource' import VueClipboards from 'vue-clipboards' @@ -54,11 +56,18 @@ import contentViewComponent from './pages/content-view.component.js' import editorComponent from './components/editor.component.js' import sourceViewComponent from './pages/source-view.component.js' +// ==================================== +// Initialize Global Vars +// ==================================== + +window.wiki = null +window.CONSTANTS = CONSTANTS + // ==================================== // Initialize Apollo Client (GraphQL) // ==================================== -window.apollo = new ApolloClient({ +window.graphQL = new ApolloClient({ networkInterface: createBatchingNetworkInterface({ uri: window.location.protocol + '//' + window.location.host + siteConfig.path + '/graphql' }), diff --git a/client/js/components/login.vue b/client/js/components/login.vue index 9db5f58c..d725ce5a 100644 --- a/client/js/components/login.vue +++ b/client/js/components/login.vue @@ -7,11 +7,8 @@ | {{ error.title }} span {{ error.message }} .login-providers(v-show='strategies.length > 1') - button.is-active(:title='$t("auth:providers.local")') - i.nc-icon-outline.ui-1_database - span {{ $t('auth:providers.local') }} - button(v-for='strategy in strategies', @onclick='selectProvider(strategy.key, strategy.useForm)', :title='strategy.title') - //-!= strategy.icon + button(v-for='strategy in strategies', :class='{ "is-active": strategy.key === selectedStrategy }', @click='selectStrategy(strategy.key, strategy.useForm)', :title='strategy.title') + em(v-html='strategy.icon') span {{ strategy.title }} .login-frame h1 {{ siteTitle }} @@ -32,7 +29,8 @@ export default { data() { return { error: false, - strategies: [] + strategies: [], + selectedStrategy: 'local' } }, computed: { @@ -41,9 +39,31 @@ export default { } }, methods: { - selectProvider(key, useForm) { - + selectStrategy(key, useForm) { + this.selectedStrategy = key + if (!useForm) { + window.location.assign(siteConfig.path + '/login/' + key) + } + }, + refreshStrategies() { + graphQL.query({ + query: CONSTANTS.GRAPHQL.GQL_QUERY_AUTHENTICATION, + variables: { + mode: 'active' + } + }).then(resp => { + if (resp.data.authentication) { + this.strategies = resp.data.authentication + } else { + throw new Error('No authentication providers available!') + } + }).catch(err => { + console.error(err) + }) } + }, + mounted() { + this.refreshStrategies() } } diff --git a/client/js/constants/graphql.js b/client/js/constants/graphql.js new file mode 100644 index 00000000..e189cce7 --- /dev/null +++ b/client/js/constants/graphql.js @@ -0,0 +1,22 @@ +import gql from 'graphql-tag' + +export default { + GQL_QUERY_AUTHENTICATION: gql` + query($mode: String!) { + authentication(mode:$mode) { + key + useForm + title + icon + } + } + `, + GQL_QUERY_TRANSLATIONS: gql` + query($locale: String!, $namespace: String!) { + translations(locale:$locale, namespace:$namespace) { + key + value + } + } + ` +} diff --git a/client/js/constants/index.js b/client/js/constants/index.js new file mode 100644 index 00000000..56e9acc7 --- /dev/null +++ b/client/js/constants/index.js @@ -0,0 +1,5 @@ +import GRAPHQL from './graphql' + +export default { + GRAPHQL +} diff --git a/client/js/modules/localization.js b/client/js/modules/localization.js index cf696af1..2ac94cd7 100644 --- a/client/js/modules/localization.js +++ b/client/js/modules/localization.js @@ -1,11 +1,10 @@ import i18next from 'i18next' import i18nextXHR from 'i18next-xhr-backend' import i18nextCache from 'i18next-localstorage-cache' -import gql from 'graphql-tag' import VueI18Next from '@panter/vue-i18next' import loSet from 'lodash/set' -/* global siteConfig */ +/* global siteConfig, graphQL, CONSTANTS */ module.exports = { VueI18Next, @@ -19,16 +18,12 @@ module.exports = { parse: (data) => data, ajax: (url, opts, cb, data) => { let langParams = url.split('/') - console.info(langParams) - window.apollo.query({ - query: gql` - { - translations(locale:"${langParams[0]}", namespace:"${langParams[1]}") { - key - value - } - } - ` + graphQL.query({ + query: CONSTANTS.GRAPHQL.GQL_QUERY_TRANSLATIONS, + variables: { + locale: langParams[0], + namespace: langParams[1] + } }).then(resp => { let ns = {} if (resp.data.translations.length > 0) { diff --git a/client/scss/components/button.scss b/client/scss/components/button.scss index c53754a3..a02562b5 100644 --- a/client/scss/components/button.scss +++ b/client/scss/components/button.scss @@ -61,7 +61,11 @@ background-color: mc($color,'800'); color: #FFF; animation: none; - } + } + + &:focus { + box-shadow: inset 0 0 0 3px rgba(255,255,255, .4); + } } } diff --git a/client/scss/pages/_login.scss b/client/scss/pages/_login.scss index be4bd602..be90d44f 100644 --- a/client/scss/pages/_login.scss +++ b/client/scss/pages/_login.scss @@ -35,6 +35,7 @@ .login-frame { border-radius: 0 6px 6px 0; + border-left: none; } } @@ -104,6 +105,10 @@ align-items: center; transition: all .4s ease; + &:focus { + outline: none; + } + @include until($tablet) { justify-content: center; } @@ -114,12 +119,24 @@ &:first-child { border-top: none; + + &.is-active { + border-top: 1px solid rgba(255,255,255, .5); + } } &.is-active { - background-color: mc('grey', '100'); - background-image: radial-gradient(circle at top left, rgba(mc('grey', '200'),1) 0%,rgba(255,255,255,1) 100%); + background-image: linear-gradient(to right, rgba(255,255,255,1) 0%,rgba(255,255,255,.77) 100%); color: mc('light-blue', '700'); + cursor: default; + + &:hover { + background-color: transparent; + } + + svg path { + fill: mc('light-blue', '800'); + } } i { @@ -160,7 +177,8 @@ } &-frame { - background-image: radial-gradient(circle at top left, rgba(255,255,255,1) 5%,rgba(240,240,240,.6) 100%); + background-image: radial-gradient(circle at top center, rgba(255,255,255,1) 5%,rgba(255,255,255,.6) 100%); + border: 1px solid rgba(255,255,255, .5); border-radius: 6px; width: 400px; padding: 1rem; @@ -178,6 +196,7 @@ font-size: 2rem; font-weight: 600; color: mc('light-blue', '700'); + text-shadow: 1px 1px 0 #FFF; padding: 0; margin: 0; } @@ -186,6 +205,7 @@ font-size: 1.5rem; font-weight: 300; color: mc('grey', '700'); + text-shadow: 1px 1px 0 #FFF; padding: 0; margin: 0 0 25px 0; } @@ -200,6 +220,7 @@ border: 1px solid #FFF; border-radius: 3px; background-color: rgba(255,255,255,.9); + box-shadow: inset 0 0 0 3px rgba(255,255,255, .25); padding: 0 15px; height: 40px; margin: 0 0 10px 0; @@ -212,6 +233,9 @@ &:focus { outline: none; border-color: mc('light-blue','500'); + background-color: rgba(255,255,255,1); + box-shadow: inset 0 0 0 3px rgba(mc('light-blue','500'), .25); + color: mc('light-blue', '800'); } } diff --git a/server/authentication/microsoft.js b/server/authentication/microsoft.js index 20e3e1d9..b761aa41 100644 --- a/server/authentication/microsoft.js +++ b/server/authentication/microsoft.js @@ -14,7 +14,7 @@ module.exports = { useForm: false, props: ['clientId', 'clientSecret', 'callbackURL'], init (passport, conf) { - passport.use('windowslive', + passport.use('microsoft', new WindowsLiveStrategy({ clientID: conf.clientId, clientSecret: conf.clientSecret, diff --git a/server/modules/graphql.js b/server/modules/graphql.js index e625afe6..aa6a6f7d 100644 --- a/server/modules/graphql.js +++ b/server/modules/graphql.js @@ -10,6 +10,7 @@ const _ = require('lodash') const typeDefs = fs.readFileSync(path.join(wiki.SERVERPATH, 'schemas/types.graphql'), 'utf8') const DateScalar = require('../schemas/scalar-date') +const AuthenticationResolvers = require('../schemas/resolvers-authentication') const CommentResolvers = require('../schemas/resolvers-comment') const DocumentResolvers = require('../schemas/resolvers-document') const FileResolvers = require('../schemas/resolvers-file') @@ -21,6 +22,7 @@ const TranslationResolvers = require('../schemas/resolvers-translation') const UserResolvers = require('../schemas/resolvers-user') const resolvers = _.merge( + AuthenticationResolvers, CommentResolvers, DocumentResolvers, FileResolvers, diff --git a/server/schemas/resolvers-authentication.js b/server/schemas/resolvers-authentication.js new file mode 100644 index 00000000..572c9d37 --- /dev/null +++ b/server/schemas/resolvers-authentication.js @@ -0,0 +1,40 @@ +const _ = require('lodash') +const fs = require('fs-extra') +const path = require('path') + +/* global wiki */ + +module.exports = { + Query: { + authentication(obj, args, context, info) { + switch (args.mode) { + case 'active': + let strategies = _.chain(wiki.auth.strategies).map(str => { + return { + key: str.key, + title: str.title, + useForm: str.useForm + } + }).sortBy(['title']).value() + let localStrategy = _.remove(strategies, str => str.key === 'local') + return _.concat(localStrategy, strategies) + case 'all': + + break + default: + return null + } + } + }, + Mutation: {}, + AuthenticationProvider: { + icon (ap, args) { + return fs.readFileAsync(path.join(wiki.ROOTPATH, `assets/svg/auth-icon-${ap.key}.svg`), 'utf8').catch(err => { + if (err.code === 'ENOENT') { + return null + } + throw err + }) + } + } +} diff --git a/server/schemas/types.graphql b/server/schemas/types.graphql index c6af303d..a47305b4 100644 --- a/server/schemas/types.graphql +++ b/server/schemas/types.graphql @@ -32,10 +32,11 @@ interface Base { # TYPES type AuthenticationProvider { - id: String! + key: String! useForm: Boolean! title: String! props: [String] + icon: String config: String } From 2be7f71be86fb3f91fc34313fa42735f3bf67a04 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Fri, 6 Oct 2017 21:35:02 -0400 Subject: [PATCH 26/33] feat: fusebox updates + vue-component-plugin --- .babelrc | 20 + .eslintrc.json | 17 +- client/js/components/page-loader.vue | 27 +- package.json | 47 +-- server/modules/db.js | 47 ++- server/views/master.pug | 2 +- tools/fuse.js | 166 +++----- yarn.lock | 572 ++++++++++++++++++++------- 8 files changed, 610 insertions(+), 288 deletions(-) create mode 100644 .babelrc diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..06dfb47f --- /dev/null +++ b/.babelrc @@ -0,0 +1,20 @@ +{ + "comments": false, + "presets": [ + ["env", { + "targets": { + "browsers": [ + "last 6 Chrome major versions", + "last 6 Firefox major versions", + "last 4 Safari major versions", + "last 4 Edge major versions", + "last 3 iOS major versions", + "last 3 Android major versions", + "last 2 ChromeAndroid major versions", + "Explorer 11" + ] + } + }], + "stage-2" + ] +} diff --git a/.eslintrc.json b/.eslintrc.json index 283168f4..8bf80646 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,27 +1,14 @@ { - "extends": "standard", + "extends": "requarks", "env": { "node": true, "es6": true, "jest": true }, "globals": { - // Client "document": false, "navigator": false, "window": false, - "siteLang": false, - "socket": true, - "wikijs": true, - "FuseBox": false, - // Server - "appconfig": true, - "appdata": true, - "ROOTPATH": true, - "SERVERPATH": true, - "IS_DEBUG": true - }, - "rules": { - "space-before-function-paren": 0 + "FuseBox": false } } diff --git a/client/js/components/page-loader.vue b/client/js/components/page-loader.vue index 8f7071e3..e4171b6d 100644 --- a/client/js/components/page-loader.vue +++ b/client/js/components/page-loader.vue @@ -5,20 +5,19 @@ span {{ msg }} - diff --git a/package.json b/package.json index cb7a94a7..0a36dd6e 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "restart": "node wiki restart", "build": "node tools/fuse", "dev": "node tools/fuse -d", - "dev-configure": "node tools/fuse -c", "test": "jest" }, "bin": { @@ -37,11 +36,11 @@ "node": ">=6.11.1" }, "dependencies": { - "apollo-server-express": "1.1.2", + "apollo-server-express": "1.1.3", "auto-load": "3.0.0", "axios": "0.16.2", "bcryptjs-then": "1.0.1", - "bluebird": "3.5.0", + "bluebird": "3.5.1", "body-parser": "1.18.2", "bull": "3.2.0", "bunyan": "1.8.12", @@ -52,7 +51,7 @@ "connect-flash": "0.1.1", "connect-redis": "3.3.2", "cookie-parser": "1.4.3", - "diff2html": "2.3.0", + "diff2html": "2.3.1", "dotize": "^0.2.0", "execa": "0.8.0", "express": "4.16.1", @@ -61,15 +60,15 @@ "express-session": "1.15.6", "file-type": "6.2.0", "filesize.js": "1.0.2", - "follow-redirects": "1.2.4", + "follow-redirects": "1.2.5", "fs-extra": "4.0.2", "git-wrapper2-promise": "0.2.9", - "graphql": "0.11.6", - "graphql-tools": "1.2.3", + "graphql": "0.10.5", + "graphql-tools": "2.2.1", "highlight.js": "9.12.0", - "i18next": "9.0.0", - "i18next-express-middleware": "1.0.6", - "i18next-localstorage-cache": "^1.1.1", + "i18next": "9.0.1", + "i18next-express-middleware": "1.0.7", + "i18next-localstorage-cache": "1.1.1", "i18next-node-fs-backend": "1.0.0", "image-size": "0.6.1", "ioredis": "3.1.4", @@ -90,7 +89,7 @@ "markdown-it-mathjax": "2.0.0", "markdown-it-task-lists": "2.0.1", "mathjax-node": "1.2.1", - "memdown": "1.3.1", + "memdown": "1.4.1", "mime-types": "2.1.17", "moment": "2.18.1", "moment-timezone": "0.5.13", @@ -109,7 +108,7 @@ "passport-windowslive": "1.0.2", "pg": "7.3.0", "pg-hstore": "2.3.2", - "pg-promise": "6.10.1", + "pg-promise": "6.10.3", "pm2": "2.7.1", "pug": "2.0.0-rc.4", "read-chunk": "2.1.0", @@ -118,7 +117,7 @@ "search-index-adder": "0.3.9", "search-index-searcher": "0.2.10", "semver": "5.4.1", - "sequelize": "4.11.5", + "sequelize": "4.13.5", "serve-favicon": "2.4.5", "simplemde": "1.11.2", "stopword": "0.1.8", @@ -127,52 +126,56 @@ "through2": "2.0.3", "validator": "9.0.0", "validator-as-promised": "1.0.2", - "winston": "2.3.1", + "winston": "2.4.0", "yargs": "9.0.1" }, "devDependencies": { "@glimpse/glimpse": "0.22.15", "@panter/vue-i18next": "0.6.1", "apollo-client": "^1.9.3", + "autoprefixer": "7.1.5", "babel-cli": "6.26.0", "babel-jest": "21.2.0", - "babel-plugin-transform-object-assign": "6.22.0", + "babel-preset-env": "1.6.0", "babel-preset-es2015": "6.24.1", + "babel-preset-stage-2": "6.24.1", "brace": "0.10.0", "colors": "1.1.2", "consolidate": "0.14.5", "eslint": "4.8.0", + "eslint-config-requarks": "1.0.7", "eslint-config-standard": "10.2.1", "eslint-plugin-import": "2.7.0", "eslint-plugin-node": "5.2.0", "eslint-plugin-promise": "3.5.0", "eslint-plugin-standard": "3.0.1", - "fuse-box": "2.2.31", + "fuse-box": "2.3.3", "graphql-tag": "^2.4.2", "i18next-xhr-backend": "1.4.3", "jest": "21.2.1", "jquery": "3.2.1", "jquery-contextmenu": "2.6.2", "jquery-simple-upload": "1.0.0", - "jquery-smooth-scroll": "2.2.0", - "jquery-sticky": "1.0.4", - "lodash-cli": "4.17.4", - "lodash-es": "4.17.4", + "js-cookie": "2.1.4", "node-sass": "4.5.3", "nodemon": "1.12.1", + "postcss-selector-parser": "2.2.3", "pug-lint": "2.5.0", "twemoji-awesome": "1.0.6", "typescript": "2.5.3", - "uglify-es": "3.1.2", + "uglify-es": "3.1.3", "vee-validate": "2.0.0-rc.18", "vue": "2.4.4", "vue-clipboards": "1.1.0", + "vue-hot-reload-api": "2.1.1", "vue-lodash": "1.0.4", "vue-material": "^0.7.5", "vue-resource": "1.3.4", + "vue-simple-breakpoints": "1.0.2", "vue-template-compiler": "2.4.4", "vue-template-es2015-compiler": "1.5.3", - "vuex": "2.4.1" + "vuex": "2.4.1", + "vuex-persistedstate": "2.0.0" }, "jest": { "collectCoverage": false, diff --git a/server/modules/db.js b/server/modules/db.js index f459039e..17081b36 100644 --- a/server/modules/db.js +++ b/server/modules/db.js @@ -6,13 +6,53 @@ const fs = require('fs') const path = require('path') const _ = require('lodash') const Promise = require('bluebird') +const Sequelize = require('sequelize') +const Op = Sequelize.Op + +const operatorsAliases = { + $eq: Op.eq, + $ne: Op.ne, + $gte: Op.gte, + $gt: Op.gt, + $lte: Op.lte, + $lt: Op.lt, + $not: Op.not, + $in: Op.in, + $notIn: Op.notIn, + $is: Op.is, + $like: Op.like, + $notLike: Op.notLike, + $iLike: Op.iLike, + $notILike: Op.notILike, + $regexp: Op.regexp, + $notRegexp: Op.notRegexp, + $iRegexp: Op.iRegexp, + $notIRegexp: Op.notIRegexp, + $between: Op.between, + $notBetween: Op.notBetween, + $overlap: Op.overlap, + $contains: Op.contains, + $contained: Op.contained, + $adjacent: Op.adjacent, + $strictLeft: Op.strictLeft, + $strictRight: Op.strictRight, + $noExtendRight: Op.noExtendRight, + $noExtendLeft: Op.noExtendLeft, + $and: Op.and, + $or: Op.or, + $any: Op.any, + $all: Op.all, + $values: Op.values, + $col: Op.col +} /** * PostgreSQL DB module */ module.exports = { - Sequelize: require('sequelize'), + Sequelize, + Op: Sequelize.Op, /** * Initialize DB @@ -35,7 +75,8 @@ module.exports = { min: 0, idle: 10000 }, - logging: false + logging: false, + operatorsAliases }) // Attempt to connect and authenticate to DB @@ -43,7 +84,7 @@ module.exports = { self.inst.authenticate().then(() => { wiki.logger.info('Database (PostgreSQL) connection: OK') }).catch(err => { - wiki.logger.error('Failed to connect to MongoDB instance.') + wiki.logger.error('Failed to connect to PostgreSQL instance.') return err }) diff --git a/server/views/master.pug b/server/views/master.pug index e924fd32..31e52533 100644 --- a/server/views/master.pug +++ b/server/views/master.pug @@ -22,7 +22,7 @@ html var siteConfig = !{JSON.stringify(config.site)} //- JS / CSS - script(type='text/javascript', src=config.site.path + '/js/vendor.js') + script(type='text/javascript', src=config.site.path + '/js/libs.js') script(type='text/javascript', src=config.site.path + '/js/app.js') block head diff --git a/tools/fuse.js b/tools/fuse.js index ef404827..70aede3c 100644 --- a/tools/fuse.js +++ b/tools/fuse.js @@ -6,16 +6,15 @@ * Client & Server compiler / bundler / watcher */ +const autoprefixer = require('autoprefixer') const colors = require('colors/safe') const fsbx = require('fuse-box') const nodemon = require('nodemon') -const babel = require('babel-core') -const uglify = require('uglify-es') const fs = require('fs-extra') -// ====================================================== +// ------------------------------------------------------- // Parse cmd arguments -// ====================================================== +// ------------------------------------------------------- const args = require('yargs') .option('d', { @@ -23,30 +22,21 @@ const args = require('yargs') describe: 'Start in Developer mode', type: 'boolean' }) - .option('c', { - alias: 'dev-configure', - describe: 'Start in Configure Developer mode', - type: 'boolean' - }) .help('h') .alias('h', 'help') .argv -let mode = 'build' -const dev = args.d || args.c -if (args.d) { +const dev = args.dev + +if (dev) { console.info(colors.bgWhite.black(' Starting Fuse in DEVELOPER mode... ')) - mode = 'dev' -} else if (args.c) { - console.info(colors.bgWhite.black(' Starting Fuse in CONFIGURE DEVELOPER mode... ')) - mode = 'dev-configure' } else { console.info(colors.bgWhite.black(' Starting Fuse in BUILD mode... ')) } -// ====================================================== +// ------------------------------------------------------- // BUILD VARS -// ====================================================== +// ------------------------------------------------------- const ALIASES = { 'brace-ext-modelist': 'brace/ext/modelist.js', @@ -71,16 +61,31 @@ const SHIMS = { } } -// ====================================================== +// ------------------------------------------------------- // Global Tasks -// ====================================================== +// ------------------------------------------------------- console.info(colors.white('└── ') + colors.green('Running global tasks...')) let globalTasks = require('./fuse_tasks') -// ====================================================== -// Fuse Tasks -// ====================================================== +// ------------------------------------------------------- +// FUSEBOX PRODUCER +// ------------------------------------------------------- + +const babelrc = fs.readJsonSync('.babelrc') +const scssChain = [ + fsbx.SassPlugin({ + includePaths: ['node_modules'], + outputStyle: dev ? 'nested' : 'compressed' + }), + fsbx.PostCSS([ + autoprefixer({ + remove: false, + browsers: babelrc.presets[0][1].targets.browsers + }) + ]), + fsbx.CSSPlugin() +] globalTasks.then(() => { let fuse = fsbx.FuseBox.init({ @@ -91,101 +96,60 @@ globalTasks.then(() => { tsConfig: './tsconfig.json', plugins: [ fsbx.EnvPlugin({ NODE_ENV: (dev) ? 'development' : 'production' }), - fsbx.VuePlugin(), - ['.scss', fsbx.SassPlugin({ outputStyle: (dev) ? 'nested' : 'compressed' }), fsbx.CSSPlugin()], - fsbx.BabelPlugin({ comments: false, presets: ['es2015'] }), + fsbx.VueComponentPlugin({ + script: fsbx.BabelPlugin(babelrc), + template: fsbx.ConsolidatePlugin({ + engine: 'pug' + }), + style: scssChain + }), + scssChain, + fsbx.BabelPlugin(babelrc), fsbx.JSONPlugin() - /* !dev && fsbx.QuantumPlugin({ - target: 'browser', - uglify: true, - api: (core) => { - core.solveComputed('default/js/components/editor-codeblock.vue', { - mapping: '/js/ace/ace.js', - fn: (statement, core) => { - statement.setExpression(`'/js/ace/ace.js'`) - } - }) - core.solveComputed('default/js/components/editor.component.js', { - mapping: '/js/simplemde/simplemde.min.js', - fn: (statement, core) => { - statement.setExpression(`'/js/simplemde/simplemde.min.js'`) - } - }) - } - }) */ - // !dev && fsbx.UglifyESPlugin() ], debug: false, log: true }) - const bundleVendor = fuse.bundle('vendor').shim(SHIMS).instructions('~ index.js') // eslint-disable-line no-unused-vars - const bundleApp = fuse.bundle('app').instructions('!> [index.js]') - // const bundleApp = fuse.bundle('app').shim(SHIMS).instructions('> index.js') - const bundleSetup = fuse.bundle('configure').instructions('> configure.js') - - switch (mode) { - case 'dev': - bundleApp.hmr().watch() - fuse.dev({ httpServer: false }) - break - case 'dev-configure': - bundleSetup.watch() - break + // ------------------------------------------------------- + // FUSEBOX DEV + // ------------------------------------------------------- + + if (dev) { + fuse.dev({ + port: 5555, + httpServer: false + }) } + // ------------------------------------------------------- + // FUSEBOX BUNDLES + // ------------------------------------------------------- + + if (dev) { + fuse.bundle('libs').shim(SHIMS).instructions('~ index.js') + fuse.bundle('app').instructions('!> [index.js]').hmr({ reload: true }).watch() + } else { + fuse.bundle('bundle.min.js').shim(SHIMS).instructions('> index.js') + } + + // ------------------------------------------------------- + // FUSEBOX RUN + // ------------------------------------------------------- + fuse.run().then(() => { console.info(colors.green.bold('\nAssets compilation + bundling completed.')) if (dev) { nodemon({ - exec: (args.d) ? 'node server' : 'node wiki configure', - ignore: ['assets/', 'client/', 'data/', 'repo/', 'tests/'], + exec: 'node server', + ignore: ['assets/', 'client/', 'data/', 'repo/', 'tests/', 'tools/'], ext: 'js json graphql', - watch: (args.d) ? ['server'] : ['server/configure.js'], + watch: ['server'], env: { 'NODE_ENV': 'development' } }) - } else { - console.info(colors.yellow.bold('\nTranspiling vendor bundle...')) - let appCode = babel.transform(fs.readFileSync('./assets/js/app.js', 'utf8'), { - babelrc: false, - compact: false, - filename: 'app.js', - plugins: ['transform-object-assign'] - }).code - let vendorCode = babel.transform(fs.readFileSync('./assets/js/vendor.js', 'utf8'), { - babelrc: false, - comments: false, - compact: false, - filename: 'vendor.js', - plugins: [ - 'transform-es2015-arrow-functions', - 'transform-es2015-block-scoped-functions', - 'transform-es2015-block-scoping', - 'transform-es2015-classes', - 'transform-es2015-computed-properties', - 'transform-es2015-destructuring', - 'transform-es2015-duplicate-keys', - 'transform-es2015-for-of', - 'transform-es2015-function-name', - 'transform-es2015-literals', - 'transform-es2015-object-super', - 'transform-es2015-parameters', - 'transform-es2015-shorthand-properties', - 'transform-es2015-spread', - 'transform-es2015-sticky-regex', - 'transform-es2015-template-literals', - 'transform-es2015-typeof-symbol', - 'transform-es2015-unicode-regex' - ] - }).code - console.info(colors.yellow.bold('Minifing bundles...')) - fs.writeFileSync('./assets/js/vendor.js', uglify.minify(vendorCode).code, 'utf8') - fs.writeFileSync('./assets/js/app.js', uglify.minify(appCode).code, 'utf8') - fs.writeFileSync('./assets/js/configure.js', uglify.minify(fs.readFileSync('./assets/js/configure.js', 'utf8')).code, 'utf8') - console.info(colors.green.bold('\nBUILD SUCCEEDED.')) - return true } + return true }).catch(err => { console.error(colors.red(' X Bundle compilation failed! ' + err.message)) process.exit(1) diff --git a/yarn.lock b/yarn.lock index d17a21c4..6f134198 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,6 +83,10 @@ version "0.10.2" resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.10.2.tgz#d7c79acbaa17453b6681c80c34b38fcb10c4c08c" +"@types/graphql@^0.11.4": + version "0.11.5" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.11.5.tgz#e70f051e80b299be5b12f7e60d962f30c9596072" + "@types/graphql@^0.9.0": version "0.9.4" resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.4.tgz#cdeb6bcbef9b6c584374b81aa7f48ecf3da404fa" @@ -137,12 +141,6 @@ abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" -abstract-leveldown@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.0.tgz#985052daf3d7d0ac0029dca8eb793f4cdd2a6834" - dependencies: - xtend "~4.0.0" - abstract-leveldown@~2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.4.1.tgz#b3bfedb884eb693a12775f0c55e9f0a420ccee64" @@ -155,6 +153,12 @@ abstract-leveldown@~2.6.1: dependencies: xtend "~4.0.0" +abstract-leveldown@~2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.1.tgz#d14d344e93561199b9969238f01a56eafd9b58af" + dependencies: + xtend "~4.0.0" + accepts@~1.2.12: version "1.2.13" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" @@ -204,6 +208,12 @@ acorn-jsx@^4.0.1: dependencies: acorn "^5.0.3" +acorn-object-rest-spread@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/acorn-object-rest-spread/-/acorn-object-rest-spread-1.1.0.tgz#78699aefdd18ec3182caadadf52e2697c048f476" + dependencies: + acorn "^5.0.3" + acorn@^2.6.4: version "2.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" @@ -363,22 +373,30 @@ apollo-link-core@^0.5.0: graphql-tag "^2.4.2" zen-observable-ts "^0.4.4" -apollo-server-core@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.1.0.tgz#74c3bf4394e14eae7ab60b1d999a3c5b8aa94e9a" +apollo-link@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-0.7.0.tgz#a8f09069b31821c27285584264356b1b6e6be6f2" + dependencies: + apollo-utilities "^0.2.0-beta.0" + graphql "^0.11.3" + zen-observable-ts "^0.5.0" + +apollo-server-core@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.1.3.tgz#1c1f223ab96097e095969a3494e6408cefdc9689" dependencies: apollo-tracing "^0.0.7" -apollo-server-express@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.1.2.tgz#6933c77fe5dfb9a7f30dd393239ad9953a613cd9" +apollo-server-express@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.1.3.tgz#ccca554327458a91c9ff3216bb6998fccb6ad9e4" dependencies: - apollo-server-core "^1.1.0" - apollo-server-module-graphiql "^1.1.2" + apollo-server-core "^1.1.3" + apollo-server-module-graphiql "^1.1.3" -apollo-server-module-graphiql@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.2.tgz#49a154cf80e984acb082bd0096175b561e1bfbcc" +apollo-server-module-graphiql@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.3.tgz#cf59be3320fda301ef369660697486f172457abb" apollo-tracing@^0.0.7: version "0.0.7" @@ -386,6 +404,10 @@ apollo-tracing@^0.0.7: dependencies: graphql-tools "^1.1.0" +apollo-utilities@^0.2.0-beta.0: + version "0.2.0-beta.2" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-0.2.0-beta.2.tgz#95b61e00fa0cb67f6af65921484bca33114d55e1" + app-root-path@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-1.4.0.tgz#6335d865c9640d0fad99004e5a79232238e92dfa" @@ -522,10 +544,6 @@ async@^2.1.4, async@^2.3.0, async@^2.5: dependencies: lodash "^4.14.0" -async@~0.2.6: - version "0.2.10" - resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" - async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" @@ -538,6 +556,17 @@ auto-load@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/auto-load/-/auto-load-3.0.0.tgz#f3c91d15120a32c89524b420d7283584c72088aa" +autoprefixer@7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.5.tgz#d65d14b83c7cd1dd7bc801daa00557addf5a06b2" + dependencies: + browserslist "^2.5.0" + caniuse-lite "^1.0.30000744" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^6.0.13" + postcss-value-parser "^3.2.3" + aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -668,6 +697,22 @@ babel-generator@^6.26.0: source-map "^0.5.6" trim-right "^1.0.1" +babel-helper-bindify-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" @@ -686,6 +731,23 @@ babel-helper-define-map@^6.24.1: babel-types "^6.24.1" lodash "^4.2.0" +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-explode-class@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" + dependencies: + babel-helper-bindify-decorators "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" @@ -725,6 +787,16 @@ babel-helper-regex@^6.24.1: babel-types "^6.24.1" lodash "^4.2.0" +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" @@ -774,10 +846,73 @@ babel-plugin-jest-hoist@^21.2.0: version "21.2.0" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.2.0.tgz#2cef637259bd4b628a6cace039de5fcd14dbb006" -babel-plugin-syntax-object-rest-spread@^6.13.0: +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-async-generators@^6.5.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-decorators@^6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-generator-functions@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-generators "^6.5.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-class-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" + dependencies: + babel-helper-explode-class "^6.24.1" + babel-plugin-syntax-decorators "^6.13.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-types "^6.24.1" + babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" @@ -790,6 +925,16 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: dependencies: babel-runtime "^6.22.0" +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + babel-plugin-transform-es2015-block-scoping@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576" @@ -800,7 +945,7 @@ babel-plugin-transform-es2015-block-scoping@^6.24.1: babel-types "^6.24.1" lodash "^4.2.0" -babel-plugin-transform-es2015-classes@^6.24.1: +babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" dependencies: @@ -814,33 +959,33 @@ babel-plugin-transform-es2015-classes@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-computed-properties@^6.24.1: +babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-destructuring@^6.22.0: +babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-duplicate-keys@^6.24.1: +babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-plugin-transform-es2015-for-of@^6.22.0: +babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-function-name@^6.24.1: +babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" dependencies: @@ -854,7 +999,7 @@ babel-plugin-transform-es2015-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-modules-amd@^6.24.1: +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" dependencies: @@ -862,6 +1007,15 @@ babel-plugin-transform-es2015-modules-amd@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" +babel-plugin-transform-es2015-modules-commonjs@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe" @@ -871,7 +1025,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.24.1: babel-template "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-modules-systemjs@^6.24.1: +babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" dependencies: @@ -879,7 +1033,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-umd@^6.24.1: +babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" dependencies: @@ -887,14 +1041,14 @@ babel-plugin-transform-es2015-modules-umd@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-object-super@^6.24.1: +babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" -babel-plugin-transform-es2015-parameters@^6.24.1: +babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" dependencies: @@ -905,7 +1059,7 @@ babel-plugin-transform-es2015-parameters@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-shorthand-properties@^6.24.1: +babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" dependencies: @@ -918,7 +1072,7 @@ babel-plugin-transform-es2015-spread@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-sticky-regex@^6.24.1: +babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" dependencies: @@ -932,13 +1086,13 @@ babel-plugin-transform-es2015-template-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-typeof-symbol@^6.22.0: +babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-unicode-regex@^6.24.1: +babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" dependencies: @@ -946,12 +1100,27 @@ babel-plugin-transform-es2015-unicode-regex@^6.24.1: babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-object-assign@6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba" +babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" +babel-plugin-transform-object-rest-spread@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.26.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + babel-plugin-transform-regenerator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" @@ -981,6 +1150,41 @@ babel-polyfill@^6.26.0: core-js "^2.5.0" regenerator-runtime "^0.10.5" +babel-preset-env@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^2.1.2" + invariant "^2.2.2" + semver "^5.3.0" + babel-preset-es2015@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" @@ -1017,6 +1221,25 @@ babel-preset-jest@^21.2.0: babel-plugin-jest-hoist "^21.2.0" babel-plugin-syntax-object-rest-spread "^6.13.0" +babel-preset-stage-2@6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" + dependencies: + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-transform-class-properties "^6.24.1" + babel-plugin-transform-decorators "^6.24.1" + babel-preset-stage-3 "^6.24.1" + +babel-preset-stage-3@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-generator-functions "^6.24.1" + babel-plugin-transform-async-to-generator "^6.24.1" + babel-plugin-transform-exponentiation-operator "^6.24.1" + babel-plugin-transform-object-rest-spread "^6.22.0" + babel-register@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f" @@ -1203,7 +1426,11 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@3.5.0, bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@^3.5.0: +bluebird@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + +bluebird@^3.1.1, bluebird@^3.3.4, bluebird@^3.4.1, bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" @@ -1302,6 +1529,13 @@ browser-resolve@^1.11.2: dependencies: resolve "1.1.7" +browserslist@^2.1.2, browserslist@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.5.0.tgz#0ea00d22813a4dfae5786485225a9c584b3ef37c" + dependencies: + caniuse-lite "^1.0.30000744" + electron-to-chromium "^1.3.24" + bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -1406,6 +1640,10 @@ camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +caniuse-lite@^1.0.30000744: + version "1.0.30000744" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000744.tgz#860fa5c83ba34fe619397d607f30bb474821671b" + capture-stack-trace@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" @@ -1572,12 +1810,6 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -closure-compiler@0.2.12: - version "0.2.12" - resolved "https://registry.yarnpkg.com/closure-compiler/-/closure-compiler-0.2.12.tgz#6c3087cad12742c79e47f0ce50e87af91cf8e171" - dependencies: - google-closure-compiler "20150901.x" - cls-bluebird@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/cls-bluebird/-/cls-bluebird-2.0.1.tgz#c259a480ae02c0e506134307bb13db30446ee2e7" @@ -1938,7 +2170,7 @@ debug@2.6.7: dependencies: ms "2.0.0" -debug@2.6.9: +debug@2.6.9, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -2066,11 +2298,11 @@ dicer@0.2.5, dicer@^0.2.5: readable-stream "1.1.x" streamsearch "0.1.2" -diff2html@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/diff2html/-/diff2html-2.3.0.tgz#375fb0783ca8fa90307749399bc9c75eb7cf6580" +diff2html@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/diff2html/-/diff2html-2.3.1.tgz#8bf7f351607826e217446163cab6da52c560e0ab" dependencies: - diff "^3.2.0" + diff "^3.3.1" hogan.js "^3.0.2" whatwg-fetch "^2.0.3" @@ -2078,6 +2310,10 @@ diff@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9" +diff@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + docproc@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/docproc/-/docproc-1.0.1.tgz#12f572e0f0eec1fa0985094e7042308f09a8e8d5" @@ -2218,6 +2454,10 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" +electron-to-chromium@^1.3.24: + version "1.3.24" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz#9b7b88bb05ceb9fa016a177833cc2dde388f21b6" + emitter-listener@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.0.1.tgz#b2499ea6e58230a52c268d5df261eecd9f10fe97" @@ -2295,6 +2535,10 @@ escodegen@^1.6.1, escodegen@^1.8.1: optionalDependencies: source-map "~0.2.0" +eslint-config-requarks@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/eslint-config-requarks/-/eslint-config-requarks-1.0.7.tgz#d2f1495ace70d5c88961c8bec4741efddd03458a" + eslint-config-standard@10.2.1: version "10.2.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" @@ -2868,6 +3112,10 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" +flatten@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" + flexbuffer@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/flexbuffer/-/flexbuffer-0.0.6.tgz#039fdf23f8823e440c38f3277e6fef1174215b30" @@ -2878,7 +3126,13 @@ fliplog@^0.3.13: dependencies: chain-able "^1.0.1" -follow-redirects@1.2.4, follow-redirects@^1.2.3: +follow-redirects@1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.5.tgz#ffd3e14cbdd5eaa72f61b6368c1f68516c2a26cc" + dependencies: + debug "^2.6.9" + +follow-redirects@^1.2.3: version "1.2.4" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea" dependencies: @@ -3003,14 +3257,15 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -fuse-box@^2.2.31: - version "2.2.31" - resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.31.tgz#36d267a6c6a79952a9c1fb7d1643c1949a6d42f5" +fuse-box@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.3.3.tgz#0d3e551c7617f37886df75c57e67df6fe05ea0db" dependencies: acorn "^5.0.3" acorn-es7 "^0.1.0" acorn-es7-plugin "^1.1.7" acorn-jsx "^4.0.1" + acorn-object-rest-spread "^1.1.0" ansi "^0.3.1" app-root-path "^2.0.1" base64-img "^1.0.3" @@ -3122,17 +3377,6 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -3190,10 +3434,6 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" -google-closure-compiler@20150901.x: - version "20150901.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler/-/google-closure-compiler-20150901.0.0.tgz#3d01c6cade65790a9bfb4e30b2158b7635acbade" - got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -3245,14 +3485,15 @@ graphql-tag@^2.0.0, graphql-tag@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.4.2.tgz#6a63297d8522d03a2b72d26f1b239aab343840cd" -graphql-tools@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-1.2.3.tgz#079bf4d157e46c0a0bae9fec117e0eea6e03ba2c" +graphql-tools@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-2.2.1.tgz#ff4d73d3e52e09b38b3f2f4ed53c29d4baa122b1" dependencies: + apollo-link "^0.7.0" deprecated-decorator "^0.1.6" - uuid "^3.0.1" + uuid "^3.1.0" optionalDependencies: - "@types/graphql" "^0.9.0" + "@types/graphql" "^0.11.4" graphql-tools@^1.1.0: version "1.2.1" @@ -3269,6 +3510,12 @@ graphql@0.10.5, graphql@^0.10.0, graphql@^0.10.3: dependencies: iterall "^1.1.0" +graphql@^0.11.3: + version "0.11.7" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6" + dependencies: + iterall "1.1.3" + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -3456,13 +3703,13 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -i18next-express-middleware@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.0.6.tgz#110782e9492931f35feffef434904847bf349128" +i18next-express-middleware@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.0.7.tgz#7909233f4e6e94b5bd4964a114247dc8d6f3f839" dependencies: cookies "0.7.1" -i18next-localstorage-cache@^1.1.1: +i18next-localstorage-cache@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/i18next-localstorage-cache/-/i18next-localstorage-cache-1.1.1.tgz#575256cc35e8cb2d88148f754766fdd2d24bb1b7" @@ -3477,9 +3724,9 @@ i18next-xhr-backend@1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.3.tgz#d72f70536a3bf6a3892261dde352bc77d708886a" -i18next@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-9.0.0.tgz#a89ab0481b5b6b3964f55b12f03de9063d8f4500" +i18next@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-9.0.1.tgz#8b8a55d017c1e256df9700ded277d47c53cd833b" iconv-lite@0.4.13: version "0.4.13" @@ -3535,6 +3782,10 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + inflection@1.12.0: version "1.12.0" resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" @@ -3935,6 +4186,10 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +iterall@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9" + iterall@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.1.tgz#f7f0af11e9a04ec6426260f5019d9fcca4d50214" @@ -4205,19 +4460,7 @@ jquery-simple-upload@1.0.0: dependencies: jquery ">=1.7.0" -jquery-smooth-scroll@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/jquery-smooth-scroll/-/jquery-smooth-scroll-2.2.0.tgz#87dc1add84168b7f466b3cdaeeb81c803fd22a2a" - dependencies: - jquery ">=1.7.0" - -jquery-sticky@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/jquery-sticky/-/jquery-sticky-1.0.4.tgz#2fe8d03dc904685340daa12cbdd1ca0c921b09ac" - dependencies: - jquery "*" - -jquery@*, jquery@3.2.1, jquery@>=1.7.0: +jquery@3.2.1, jquery@>=1.7.0: version "3.2.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787" @@ -4225,6 +4468,10 @@ js-base64@^2.1.8: version "2.1.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" +js-cookie@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.1.4.tgz#da4ec503866f149d164cf25f579ef31015025d8d" + js-string-escape@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -4591,17 +4838,7 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash-cli@4.17.4: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash-cli/-/lodash-cli-4.17.4.tgz#23b727cd0e91e28484fafda1521900a8a811df81" - dependencies: - closure-compiler "0.2.12" - glob "7.1.1" - lodash "4.17.4" - semver "5.3.0" - uglify-js "2.7.5" - -lodash-es@4.17.4, lodash-es@^4.2.1: +lodash-es@^4.2.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" @@ -4971,15 +5208,16 @@ memcached@~0.2.4: hashring "0.0.x" jackpot ">=0.0.6" -memdown@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.3.1.tgz#071499332e3a74b88c3d9551b0750d61fdf0c5b7" +memdown@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" dependencies: - abstract-leveldown "2.7.0" + abstract-leveldown "~2.7.1" functional-red-black-tree "^1.0.1" immediate "^3.2.3" inherits "~2.0.1" ltgt "~2.2.0" + safe-buffer "~5.1.1" meow@^3.7.0: version "3.7.0" @@ -5341,6 +5579,10 @@ normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + notp@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/notp/-/notp-2.0.3.tgz#a9fd11e25cfe1ccb39fc6689544ee4c10ef9a577" @@ -5373,6 +5615,10 @@ nth-check@~1.0.1: dependencies: boolbase "~1.0.0" +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -5401,6 +5647,10 @@ object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" +object-path@^0.11.2: + version "0.11.4" + resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -5796,9 +6046,9 @@ pg-pool@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257" -pg-promise@6.10.1: - version "6.10.1" - resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.10.1.tgz#56676a741ce5b7b9ee149070d7fd5c342555dff8" +pg-promise@6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/pg-promise/-/pg-promise-6.10.3.tgz#1818d515f08757b6a1898ef2301438cfa4a3dcd7" dependencies: manakin "~0.5.1" pg "~7.3.0" @@ -5950,6 +6200,18 @@ pngjs@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.2.0.tgz#fc9fcea1a8a375da54a51148019d5abd41dbabde" +postcss-selector-parser@2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-value-parser@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + postcss@^6.0.1: version "6.0.8" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.8.tgz#89067a9ce8b11f8a84cbc5117efc30419a0857b3" @@ -5958,6 +6220,14 @@ postcss@^6.0.1: source-map "^0.5.6" supports-color "^4.2.0" +postcss@^6.0.13: + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.13.tgz#b9ecab4ee00c89db3ec931145bd9590bbf3f125f" + dependencies: + chalk "^2.1.0" + source-map "^0.6.1" + supports-color "^4.4.0" + postgres-array@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" @@ -6453,6 +6723,14 @@ regenerator-transform@0.9.11: babel-types "^6.19.0" private "^0.1.6" +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + regex-cache@^0.4.2: version "0.4.3" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" @@ -6820,9 +7098,9 @@ send@0.16.1: range-parser "~1.2.0" statuses "~1.3.1" -sequelize@4.11.5: - version "4.11.5" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.11.5.tgz#2349994bc9027fdf05f45fa1e221ed5bc840c4b3" +sequelize@4.13.5: + version "4.13.5" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.13.5.tgz#f3a397858c2821da5384e51b4eb98a9ff65ecb16" dependencies: bluebird "^3.4.6" cls-bluebird "^2.0.1" @@ -6932,6 +7210,10 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +simple-breakpoints@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/simple-breakpoints/-/simple-breakpoints-1.1.2.tgz#2a690bb989228bc1f80acf802785f61f53ed6b92" + simple-get@^1.4.2: version "1.4.3" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb" @@ -6994,6 +7276,10 @@ source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, sour version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -7204,6 +7490,12 @@ supports-color@^4.0.0, supports-color@^4.2.0: dependencies: has-flag "^2.0.0" +supports-color@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + dependencies: + has-flag "^2.0.0" + symbol-observable@^1.0.2, symbol-observable@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" @@ -7479,22 +7771,13 @@ uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" -uglify-es@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.2.tgz#b22cfca950f0632092aff42bb46979d83b5ec6f5" +uglify-es@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.3.tgz#a21eeb149cb120a1f8302563689e19496550780b" dependencies: commander "~2.11.0" source-map "~0.5.1" -uglify-js@2.7.5: - version "2.7.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" - dependencies: - async "~0.2.6" - source-map "~0.5.1" - uglify-to-browserify "~1.0.0" - yargs "~3.10.0" - uglify-js@^2.6, uglify-js@^2.6.1: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" @@ -7538,6 +7821,10 @@ underscore@~1.5.1: version "1.5.2" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.5.2.tgz#1335c5e4f5e6d33bbb4b006ba8c86a00f556de08" +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" @@ -7721,6 +8008,10 @@ vue-clipboards@1.1.0: dependencies: clipboard "^1.7.1" +vue-hot-reload-api@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.1.1.tgz#1ba6712166182fd651753804b9d8d8d02d855579" + vue-lodash@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/vue-lodash/-/vue-lodash-1.0.4.tgz#99f4f2f5832ce0168c4d45618789288a638562cd" @@ -7735,6 +8026,12 @@ vue-resource@1.3.4: dependencies: got "^7.0.0" +vue-simple-breakpoints@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/vue-simple-breakpoints/-/vue-simple-breakpoints-1.0.2.tgz#87aae092f853c7f26e6b99950385f108ccf399c9" + dependencies: + simple-breakpoints "^1.1.1" + vue-template-compiler@2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.4.4.tgz#2cde3b704124985c27d50b5387c9691ba515fb57" @@ -7750,6 +8047,13 @@ vue@2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/vue/-/vue-2.4.4.tgz#ea9550b96a71465fd2b8b17b61673b3561861789" +vuex-persistedstate@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/vuex-persistedstate/-/vuex-persistedstate-2.0.0.tgz#b84f530da4679bdf694c5ddf65c23033aa79b1bb" + dependencies: + lodash.merge "^4.6.0" + object-path "^0.11.2" + vuex@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.4.1.tgz#7890b650ba8565b70937b4e7670577082dfe8bc1" @@ -7846,9 +8150,9 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -winston@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119" +winston@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee" dependencies: async "~1.0.0" colors "1.0.x" @@ -8066,6 +8370,10 @@ zen-observable-ts@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.4.4.tgz#c244c71eaebef79a985ccf9895bc90307a6e9712" +zen-observable-ts@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.5.0.tgz#c5021e7ac486fc281f6126d574673cfb6daf0069" + zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" From c26fae2edefd140a0f723238dfc669f763ed0839 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 7 Oct 2017 22:44:35 -0400 Subject: [PATCH 27/33] feat: Kernel module --- package.json | 13 +- server/index.js | 39 +--- server/init.js | 90 -------- server/master.js | 18 +- server/models/user.js | 11 +- server/modules/config.js | 5 +- server/modules/db.js | 12 +- server/modules/kernel.js | 91 ++++++++ server/modules/queue.js | 2 +- server/worker.js | 2 - tools/fuse_tasks.js | 21 -- wiki.js | 78 +++++-- yarn.lock | 442 +++++++-------------------------------- 13 files changed, 264 insertions(+), 560 deletions(-) delete mode 100644 server/init.js create mode 100644 server/modules/kernel.js diff --git a/package.json b/package.json index 0a36dd6e..f48d48e9 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "bcryptjs-then": "1.0.1", "bluebird": "3.5.1", "body-parser": "1.18.2", - "bull": "3.2.0", + "bull": "3.3.0", "bunyan": "1.8.12", "cheerio": "1.0.0-rc.2", "child-process-promise": "2.2.1", @@ -66,7 +66,7 @@ "graphql": "0.10.5", "graphql-tools": "2.2.1", "highlight.js": "9.12.0", - "i18next": "9.0.1", + "i18next": "9.1.0", "i18next-express-middleware": "1.0.7", "i18next-localstorage-cache": "1.1.1", "i18next-node-fs-backend": "1.0.0", @@ -76,7 +76,6 @@ "js-yaml": "3.10.0", "jsonwebtoken": "8.0.1", "klaw": "2.1.0", - "levelup": "1.3.9", "lodash": "4.17.4", "markdown-it": "8.4.0", "markdown-it-abbr": "1.0.4", @@ -89,7 +88,6 @@ "markdown-it-mathjax": "2.0.0", "markdown-it-task-lists": "2.0.1", "mathjax-node": "1.2.1", - "memdown": "1.4.1", "mime-types": "2.1.17", "moment": "2.18.1", "moment-timezone": "0.5.13", @@ -106,21 +104,19 @@ "passport-local": "1.0.0", "passport-slack": "0.0.7", "passport-windowslive": "1.0.2", - "pg": "7.3.0", + "pg": "6.4.2", "pg-hstore": "2.3.2", "pg-promise": "6.10.3", "pm2": "2.7.1", "pug": "2.0.0-rc.4", + "qr-image": "3.2.0", "read-chunk": "2.1.0", "remove-markdown": "0.2.2", "request": "2.83.0", - "search-index-adder": "0.3.9", - "search-index-searcher": "0.2.10", "semver": "5.4.1", "sequelize": "4.13.5", "serve-favicon": "2.4.5", "simplemde": "1.11.2", - "stopword": "0.1.8", "stream-to-promise": "2.2.0", "tar": "4.0.1", "through2": "2.0.3", @@ -135,6 +131,7 @@ "apollo-client": "^1.9.3", "autoprefixer": "7.1.5", "babel-cli": "6.26.0", + "babel-core": "6.26.0", "babel-jest": "21.2.0", "babel-preset-env": "1.6.0", "babel-preset-es2015": "6.24.1", diff --git a/server/index.js b/server/index.js index 30ea6e2c..e74f5c2b 100644 --- a/server/index.js +++ b/server/index.js @@ -1,5 +1,3 @@ -'use strict' - // =========================================== // Wiki.js // Licensed under AGPLv3 @@ -13,7 +11,8 @@ let wiki = { IS_MASTER: cluster.isMaster, ROOTPATH: process.cwd(), SERVERPATH: path.join(process.cwd(), 'server'), - configSvc: require('./modules/config') + configSvc: require('./modules/config'), + kernel: require('./modules/kernel') } global.wiki = wiki @@ -38,37 +37,7 @@ wiki.logger = require('./modules/logger').init() wiki.db = require('./modules/db').init() // ---------------------------------------- -// Start Cluster +// Start Kernel // ---------------------------------------- -const numCPUs = require('os').cpus().length -let numWorkers = (wiki.config.workers > 0) ? wiki.config.workers : numCPUs -if (numWorkers > numCPUs) { - numWorkers = numCPUs -} - -if (cluster.isMaster) { - wiki.logger.info('=======================================') - wiki.logger.info('= Wiki.js =============================') - wiki.logger.info('=======================================') - - require('./master').then(() => { - // -> Create background workers - for (let i = 0; i < numWorkers; i++) { - cluster.fork() - } - - // -> Queue post-init tasks - - wiki.queue.uplClearTemp.add({}, { - repeat: { cron: '*/15 * * * *' } - }) - }) - - cluster.on('exit', (worker, code, signal) => { - wiki.logger.info(`Background Worker #${worker.id} was terminated.`) - }) -} else { - wiki.logger.info(`Background Worker #${cluster.worker.id} is initializing...`) - require('./worker') -} +wiki.kernel.init() diff --git a/server/init.js b/server/init.js deleted file mode 100644 index 95b3ed52..00000000 --- a/server/init.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict' - -const Promise = require('bluebird') -const fs = Promise.promisifyAll(require('fs-extra')) -const pm2 = Promise.promisifyAll(require('pm2')) -const ora = require('ora') -const path = require('path') - -const ROOTPATH = process.cwd() - -module.exports = { - /** - * Detect the most appropriate start mode - */ - startDetect: function () { - if (process.env.WIKI_JS_HEROKU) { - return this.startInHerokuMode() - } else { - return this.startInBackgroundMode() - } - }, - /** - * Start in background mode - */ - startInBackgroundMode: function () { - let spinner = ora('Initializing...').start() - return fs.emptyDirAsync(path.join(ROOTPATH, './logs')).then(() => { - return pm2.connectAsync().then(() => { - return pm2.startAsync({ - name: 'wiki', - script: 'server', - cwd: ROOTPATH, - output: path.join(ROOTPATH, './logs/wiki-output.log'), - error: path.join(ROOTPATH, './logs/wiki-error.log'), - minUptime: 5000, - maxRestarts: 5 - }).then(() => { - spinner.succeed('Wiki.js has started successfully.') - }).finally(() => { - pm2.disconnect() - }) - }) - }).catch(err => { - spinner.fail(err) - process.exit(1) - }) - }, - /** - * Start in Heroku mode - */ - startInHerokuMode: function () { - console.warn('Incorrect command on Heroku, use instead: node server') - process.exit(1) - }, - /** - * Stop Wiki.js process(es) - */ - stop () { - let spinner = ora('Shutting down Wiki.js...').start() - return pm2.connectAsync().then(() => { - return pm2.stopAsync('wiki').then(() => { - spinner.succeed('Wiki.js has stopped successfully.') - }).finally(() => { - pm2.disconnect() - }) - }).catch(err => { - spinner.fail(err) - process.exit(1) - }) - }, - /** - * Restart Wiki.js process(es) - */ - restart: function () { - let self = this - return self.stop().delay(1000).then(() => { - self.startDetect() - }) - }, - /** - * Start the web-based configuration wizard - * - * @param {Number} port Port to bind the HTTP server on - */ - configure (port) { - port = port || 3000 - let spinner = ora('Initializing interactive setup...').start() - require('./configure')(port, spinner) - } -} diff --git a/server/master.js b/server/master.js index f4350edf..4d8a450c 100644 --- a/server/master.js +++ b/server/master.js @@ -1,17 +1,6 @@ -'use strict' - /* global wiki */ -const Promise = require('bluebird') - -wiki.redis = require('./modules/redis').init() -wiki.queue = require('./modules/queue').init() - -module.exports = Promise.join( - wiki.db.onReady, - wiki.configSvc.loadFromDb(), - wiki.queue.clean() -).then(() => { +module.exports = () => { // ---------------------------------------- // Load global modules // ---------------------------------------- @@ -194,7 +183,4 @@ module.exports = Promise.join( }) return true -}).catch(err => { - wiki.logger.error(err) - process.exit(1) -}) +} diff --git a/server/models/user.js b/server/models/user.js index 4d740b39..a73425d8 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -19,7 +19,7 @@ module.exports = (sequelize, DataTypes) => { } }, provider: { - type: DataTypes.ENUM(wiki.data.authProviders), + type: DataTypes.STRING, allowNull: false }, providerId: { @@ -37,6 +37,15 @@ module.exports = (sequelize, DataTypes) => { role: { type: DataTypes.ENUM('admin', 'user', 'guest'), allowNull: false + }, + tfaIsActive: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + tfaSecret: { + type: DataTypes.STRING, + allowNull: true } }, { timestamps: true, diff --git a/server/modules/config.js b/server/modules/config.js index 5884b8cf..d18da9fa 100644 --- a/server/modules/config.js +++ b/server/modules/config.js @@ -75,13 +75,14 @@ module.exports = { } } }).then(results => { - if (_.isArray(results) && results.length > 0) { + if (_.isArray(results) && results.length === subsets.length) { results.forEach(result => { wiki.config[result.key] = result.config }) return true } else { - return Promise.reject(new Error('Invalid DB Configuration result set')) + wiki.logger.warn('DB Configuration is empty or incomplete.') + return false } }) } diff --git a/server/modules/db.js b/server/modules/db.js index 17081b36..34fc02e3 100644 --- a/server/modules/db.js +++ b/server/modules/db.js @@ -75,7 +75,7 @@ module.exports = { min: 0, idle: 10000 }, - logging: false, + logging: log => { wiki.logger.log('verbose', log) }, operatorsAliases }) @@ -92,10 +92,10 @@ module.exports = { fs .readdirSync(dbModelsPath) - .filter(function (file) { + .filter(file => { return (file.indexOf('.') !== 0 && file.indexOf('_') !== 0) }) - .forEach(function (file) { + .forEach(file => { let modelName = _.upperFirst(_.camelCase(_.split(file, '.')[0])) self[modelName] = self.inst.import(path.join(dbModelsPath, file)) }) @@ -110,8 +110,8 @@ module.exports = { // -> Sync DB Schemas syncSchemas() { return self.inst.sync({ - force: false, - logging: false + force: true, + logging: log => { wiki.logger.log('verbose', log) } }) }, // -> Set Connection App Name @@ -129,7 +129,7 @@ module.exports = { // Perform init tasks - self.onReady = Promise.each(initTasksQueue, t => t()) + self.onReady = Promise.each(initTasksQueue, t => t()).return(true) return self } diff --git a/server/modules/kernel.js b/server/modules/kernel.js new file mode 100644 index 00000000..48e1659f --- /dev/null +++ b/server/modules/kernel.js @@ -0,0 +1,91 @@ +const cluster = require('cluster') +const Promise = require('bluebird') +const _ = require('lodash') + +/* global wiki */ + +module.exports = { + numWorkers: 1, + workers: [], + init() { + if (cluster.isMaster) { + wiki.logger.info('=======================================') + wiki.logger.info('= Wiki.js =============================') + wiki.logger.info('=======================================') + + wiki.redis = require('./redis').init() + wiki.queue = require('./queue').init() + + this.setWorkerLimit() + this.bootMaster() + } else { + this.bootWorker() + } + }, + /** + * Pre-Master Boot Sequence + */ + preBootMaster() { + return Promise.mapSeries([ + () => { return wiki.db.onReady }, + () => { return wiki.configSvc.loadFromDb() }, + () => { return wiki.queue.clean() } + ], fn => { return fn() }) + }, + /** + * Boot Master Process + */ + bootMaster() { + this.preBootMaster().then(sequenceResults => { + if (_.every(sequenceResults, rs => rs === true)) { + this.postBootMaster() + } else { + wiki.logger.info('Starting configuration manager...') + require('../configure')() + } + return true + }).catch(err => { + wiki.logger.error(err) + process.exit(1) + }) + }, + /** + * Post-Master Boot Sequence + */ + postBootMaster() { + require('../master')().then(() => { + _.times(this.numWorker, this.spawnWorker) + + wiki.queue.uplClearTemp.add({}, { + repeat: { cron: '*/15 * * * *' } + }) + }) + + cluster.on('exit', (worker, code, signal) => { + wiki.logger.info(`Background Worker #${worker.id} was terminated.`) + }) + }, + /** + * Boot Worker Process + */ + bootWorker() { + wiki.logger.info(`Background Worker #${cluster.worker.id} is initializing...`) + require('../worker') + }, + /** + * Spawn new Worker process + */ + spawnWorker() { + this.workers.push(cluster.fork()) + }, + /** + * Set Worker count based on config + system capabilities + */ + setWorkerLimit() { + const numCPUs = require('os').cpus().length + this.numWorkers = (wiki.config.workers > 0) ? wiki.config.workers : numCPUs + if (this.numWorkers > numCPUs) { + this.numWorkers = numCPUs + } + } +} diff --git a/server/modules/queue.js b/server/modules/queue.js index e7612ee3..4bbb6dc0 100644 --- a/server/modules/queue.js +++ b/server/modules/queue.js @@ -30,7 +30,7 @@ module.exports = { }) }).then(() => { wiki.logger.info('Purging old queue jobs: OK') - }).catch(err => { + }).return(true).catch(err => { wiki.logger.error(err) }) } diff --git a/server/worker.js b/server/worker.js index 0028f755..6ca90eba 100644 --- a/server/worker.js +++ b/server/worker.js @@ -1,5 +1,3 @@ -'use strict' - /* global wiki */ const Promise = require('bluebird') diff --git a/tools/fuse_tasks.js b/tools/fuse_tasks.js index e5160a6c..c9d0ee03 100644 --- a/tools/fuse_tasks.js +++ b/tools/fuse_tasks.js @@ -65,27 +65,6 @@ module.exports = Promise.mapSeries([ } }) }, - /** - * i18n - */ - () => { - console.info(colors.white(' └── ') + colors.green('Copying i18n client files...')) - return fs.ensureDirAsync('./assets/js/i18n').then(() => { - return fs.readJsonAsync('./server/locales/en/browser.json').then(enContent => { - return fs.readdirAsync('./server/locales').then(langs => { - return Promise.map(langs, lang => { - console.info(colors.white(' ' + lang + '.json')) - let outputPath = path.join('./assets/js/i18n', lang + '.json') - return fs.readJsonAsync(path.join('./server/locales', lang + 'browser.json'), 'utf8').then((content) => { - return fs.outputJsonAsync(outputPath, _.defaultsDeep(content, enContent)) - }).catch(err => { // eslint-disable-line handle-callback-err - return fs.outputJsonAsync(outputPath, enContent) - }) - }) - }) - }) - }) - }, /** * Delete Fusebox cache */ diff --git a/wiki.js b/wiki.js index faa38b0d..4f14f1bb 100644 --- a/wiki.js +++ b/wiki.js @@ -1,13 +1,72 @@ #!/usr/bin/env node -'use strict' // =========================================== // Wiki.js -// 1.0.1 +// 2.0 // Licensed under AGPLv3 // =========================================== -const init = require('./server/init') +const Promise = require('bluebird') +const fs = Promise.promisifyAll(require('fs-extra')) +const pm2 = Promise.promisifyAll(require('pm2')) +const ora = require('ora') +const path = require('path') + +const ROOTPATH = process.cwd() + +const init = { + /** + * Start in background mode + */ + start () { + let spinner = ora('Initializing...').start() + return fs.emptyDirAsync(path.join(ROOTPATH, './logs')).then(() => { + return pm2.connectAsync().then(() => { + return pm2.startAsync({ + name: 'wiki', + script: 'server', + cwd: ROOTPATH, + output: path.join(ROOTPATH, './logs/wiki-output.log'), + error: path.join(ROOTPATH, './logs/wiki-error.log'), + minUptime: 5000, + maxRestarts: 5 + }).then(() => { + spinner.succeed('Wiki.js has started successfully.') + }).finally(() => { + pm2.disconnect() + }) + }) + }).catch(err => { + spinner.fail(err) + process.exit(1) + }) + }, + /** + * Stop Wiki.js process(es) + */ + stop () { + let spinner = ora('Shutting down Wiki.js...').start() + return pm2.connectAsync().then(() => { + return pm2.stopAsync('wiki').then(() => { + spinner.succeed('Wiki.js has stopped successfully.') + }).finally(() => { + pm2.disconnect() + }) + }).catch(err => { + spinner.fail(err) + process.exit(1) + }) + }, + /** + * Restart Wiki.js process(es) + */ + restart: function () { + let self = this + return self.stop().delay(1000).then(() => { + self.startDetect() + }) + } +} require('yargs') // eslint-disable-line no-unused-expressions .usage('Usage: node $0 [args]') @@ -16,7 +75,7 @@ require('yargs') // eslint-disable-line no-unused-expressions alias: ['boot', 'init'], desc: 'Start Wiki.js process', handler: argv => { - init.startDetect() + init.start() } }) .command({ @@ -35,18 +94,9 @@ require('yargs') // eslint-disable-line no-unused-expressions init.restart() } }) - .command({ - command: 'configure [port]', - alias: ['config', 'conf', 'cfg', 'setup'], - desc: 'Configure Wiki.js using the web-based setup wizard', - builder: (yargs) => yargs.default('port', 3000), - handler: argv => { - init.configure(argv.port) - } - }) .recommendCommands() .demandCommand(1, 'You must provide one of the accepted commands above.') .help() .version() - .epilogue('Read the docs at https://wiki.requarks.io') + .epilogue('Read the docs at https://docs.requarks.io/wiki') .argv diff --git a/yarn.lock b/yarn.lock index 6f134198..7e8baa6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -126,13 +126,6 @@ "@types/express-serve-static-core" "*" "@types/mime" "*" -JSONStream@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a" - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - abab@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d" @@ -141,24 +134,6 @@ abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" -abstract-leveldown@~2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.4.1.tgz#b3bfedb884eb693a12775f0c55e9f0a420ccee64" - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.1.tgz#f9014a5669b746418e145168dea49a044ae15900" - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.1.tgz#d14d344e93561199b9969238f01a56eafd9b58af" - dependencies: - xtend "~4.0.0" - accepts@~1.2.12: version "1.2.13" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" @@ -538,7 +513,7 @@ async@1.5, async@^1.4.0, async@^1.5: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.1.4, async@^2.3.0, async@^2.5: +async@^2.1.4, async@^2.5: version "2.5.0" resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d" dependencies: @@ -623,6 +598,30 @@ babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" +babel-core@6.26.0, babel-core@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + babel-core@^6.0.0, babel-core@^6.24.1: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" @@ -647,30 +646,6 @@ babel-core@^6.0.0, babel-core@^6.24.1: slash "^1.0.0" source-map "^0.5.0" -babel-core@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.0" - debug "^2.6.8" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.7" - slash "^1.0.0" - source-map "^0.5.6" - babel-generator@^6.18.0, babel-generator@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" @@ -1402,20 +1377,10 @@ binary-extensions@^1.0.0: version "1.8.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" -bindings@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" - bisection@: version "0.0.3" resolved "https://registry.yarnpkg.com/bisection/-/bisection-0.0.3.tgz#9891d506d86ec7d50910c5157bb592dbb03f33db" -bl@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" - dependencies: - readable-stream "^2.0.5" - blessed@^0.1.81: version "0.1.81" resolved "https://registry.yarnpkg.com/blessed/-/blessed-0.1.81.tgz#f962d687ec2c369570ae71af843256e6d0ca1129" @@ -1558,9 +1523,9 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bull@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/bull/-/bull-3.2.0.tgz#4fd186c4dba46ceb1743108042abe4013a3dd036" +bull@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/bull/-/bull-3.3.0.tgz#79fc48f0ab6c63cc10fc053adfec4ddcbbc5dd44" dependencies: bluebird "^3.5.0" cron-parser "^2.4.1" @@ -1579,7 +1544,7 @@ bunyan@1.8.12: mv "~2" safe-json-stringify "~1" -bunyan@^1.8.1, bunyan@^1.8.10, bunyan@^1.8.3: +bunyan@^1.8.3: version "1.8.10" resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.10.tgz#201fedd26c7080b632f416072f53a90b9a52981c" optionalDependencies: @@ -2228,12 +2193,6 @@ default-require-extensions@^1.0.0: dependencies: strip-bom "^2.0.0" -deferred-leveldown@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.1.tgz#5d25c3310f5fe909946f6240dc9f90dd109a71ef" - dependencies: - abstract-leveldown "~2.4.0" - define-properties@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" @@ -2314,14 +2273,6 @@ diff@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" -docproc@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/docproc/-/docproc-1.0.1.tgz#12f572e0f0eec1fa0985094e7042308f09a8e8d5" - dependencies: - pumpify "^1.3.5" - term-frequency "^0.0.15" - term-vector "^0.1.2" - doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -2417,15 +2368,6 @@ duplexer@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" -duplexify@^3.1.2: - version "3.5.0" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604" - dependencies: - end-of-stream "1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - eachr@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/eachr/-/eachr-3.2.0.tgz#2c35e43ea086516f7997cf80b7aa64d55a4a4484" @@ -2474,18 +2416,6 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" -end-of-stream@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e" - dependencies: - once "~1.3.0" - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" - dependencies: - once "^1.4.0" - end-of-stream@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07" @@ -2496,7 +2426,7 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -errno@^0.1.4, errno@~0.1.1: +errno@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" dependencies: @@ -2768,10 +2698,6 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -expand-template@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.0.3.tgz#6c303323177a62b1b22c070279f7861287b69b1a" - expect@^21.2.1: version "21.2.1" resolved "https://registry.yarnpkg.com/expect/-/expect-21.2.1.tgz#003ac2ac7005c3c29e73b38a272d4afadd6d1d7b" @@ -2963,10 +2889,6 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fast-future@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fast-future/-/fast-future-1.0.2.tgz#8435a9aaa02d79248d17d704e76259301d99280a" - fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -3315,6 +3237,10 @@ gaze@^1.0.0: dependencies: globule "^1.0.0" +generic-pool@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" + generic-pool@^3.1.8: version "3.1.8" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.1.8.tgz#09844b6545bc9177ec218bd35d4ad894c65be271" @@ -3356,10 +3282,6 @@ git-wrapper2-promise@0.2.9: dependencies: child-process-promise "^1.1.0" -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - "gkt@https://tgz.pm2.io/gkt-1.0.0.tgz": version "1.0.0" resolved "https://tgz.pm2.io/gkt-1.0.0.tgz#405502b007f319c3f47175c4474527300f2ab5ad" @@ -3724,9 +3646,9 @@ i18next-xhr-backend@1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-1.4.3.tgz#d72f70536a3bf6a3892261dde352bc77d708886a" -i18next@9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-9.0.1.tgz#8b8a55d017c1e256df9700ded277d47c53cd833b" +i18next@9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-9.1.0.tgz#408005fe262a990c8d93946a6de0c77bba11667b" iconv-lite@0.4.13: version "0.4.13" @@ -3760,10 +3682,6 @@ image-size@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.1.tgz#98122a562d59dcc097ef1b2c8191866eb8f5d663" -immediate@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -3850,10 +3768,6 @@ interpret@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" -intersect-arrays-to-stream@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/intersect-arrays-to-stream/-/intersect-arrays-to-stream-0.0.3.tgz#fc0318953e872f12a12f3d33d04f4e7630e59f3b" - invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" @@ -4594,10 +4508,6 @@ jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - jsonwebtoken@8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.0.1.tgz#50daef8d0a8c7de2cd06bc1013b75b04ccf3f0cf" @@ -4726,63 +4636,6 @@ lego-api@^1.0.7: dependencies: chain-able "^3.0.0" -level-codec@~6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-6.1.0.tgz#f5df0a99582f76dac43855151ab6f4e4d0d60045" - -level-codec@~7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.0.tgz#c755b68d0d44ffa0b1cba044b8f81a55a14ad39b" - -level-errors@^1.0.3, level-errors@~1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.4.tgz#3585e623974c737a93755492a43c0267cda4425f" - dependencies: - errno "~0.1.1" - -level-iterator-stream@~1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -leveldown@^1.6.0, leveldown@^1.7.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-1.7.2.tgz#5e3467bb27ee246a4a7b8dbd8fb2b16206a6eb8b" - dependencies: - abstract-leveldown "~2.6.1" - bindings "~1.2.1" - fast-future "~1.0.2" - nan "~2.6.1" - prebuild-install "^2.1.0" - -levelup@1.3.9: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" - -levelup@^1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.8.tgz#fb442c488efbea1043f7eb9929a792a74fbd1da6" - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~6.1.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.1.0" - xtend "~4.0.0" - leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" @@ -4932,10 +4785,6 @@ lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" -lodash.intersection@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.intersection/-/lodash.intersection-4.4.0.tgz#0a11ba631d0e95c23c7f2f4cbb9a692ed178e705" - lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -4952,7 +4801,7 @@ lodash.isempty@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" -lodash.isequal@^4.0.0, lodash.isequal@^4.1.3: +lodash.isequal@^4.0.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -5028,22 +4877,6 @@ lodash.shuffle@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.shuffle/-/lodash.shuffle-4.2.0.tgz#145b5053cf875f6f5c2a33f48b6e9948c6ec7b4b" -lodash.sortedindexof@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lodash.sortedindexof/-/lodash.sortedindexof-4.1.0.tgz#7b661d2f86f55668770802d56baa8f02d6620f3c" - -lodash.spread@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.spread/-/lodash.spread-4.2.1.tgz#07bf5569e83b40534f7361d954a9fab02da5d4fc" - -lodash.union@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - lodash.values@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" @@ -5094,10 +4927,6 @@ lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.0.2: pseudomap "^1.0.2" yallist "^2.1.2" -ltgt@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.0.tgz#b65ba5fcb349a29924c8e333f7c6a5562f2e4842" - make-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" @@ -5208,17 +5037,6 @@ memcached@~0.2.4: hashring "0.0.x" jackpot ">=0.0.6" -memdown@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -5397,7 +5215,7 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" -nan@^2.3.0, nan@^2.3.2, nan@^2.3.3, nan@~2.6.1: +nan@^2.3.0, nan@^2.3.2, nan@^2.3.3: version "2.6.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" @@ -5428,10 +5246,6 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -ngraminator@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/ngraminator/-/ngraminator-0.0.1.tgz#29cfd699df6970f42de9b2f0bdc7f4b60fad6f8e" - node-2fa@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/node-2fa/-/node-2fa-1.1.2.tgz#5bc5691474afe35ae6b3b76459b98b7c20c7158c" @@ -5439,10 +5253,6 @@ node-2fa@1.1.2: notp "^2.0.3" thirty-two "0.0.2" -node-abi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.1.0.tgz#50ad834affcf17440e12bfc5f9ba0946f572d10c" - node-fetch@1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" @@ -5541,10 +5351,6 @@ nodemon@1.12.1: undefsafe "0.0.3" update-notifier "^2.2.0" -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - nopt@1.0.10, nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" @@ -5593,7 +5399,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.1, npmlog@^4.0.2: +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -5635,6 +5441,10 @@ oauth@0.9.x: version "0.9.15" resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" @@ -5668,7 +5478,7 @@ on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" -once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: +once@^1.3.0, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -5735,7 +5545,7 @@ ora@1.3.0: cli-spinners "^1.0.0" log-symbols "^1.0.2" -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -6042,6 +5852,13 @@ pg-minify@~0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.5.3.tgz#aa09befa3cbe29fab6461bf819100e0471215011" +pg-pool@1.*: + version "1.8.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.8.0.tgz#f7ec73824c37a03f076f51bfdf70e340147c4f37" + dependencies: + generic-pool "2.4.3" + object-assign "4.1.0" + pg-pool@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257" @@ -6055,7 +5872,7 @@ pg-promise@6.10.3: pg-minify "~0.5.3" spex "~2.0.0" -pg-types@~1.12.1: +pg-types@1.*, pg-types@~1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.1.tgz#d64087e3903b58ffaad279e7595c52208a14c3d2" dependencies: @@ -6064,7 +5881,20 @@ pg-types@~1.12.1: postgres-date "~1.0.0" postgres-interval "^1.1.0" -pg@7.3.0, pg@~7.3.0: +pg@6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.2.tgz#c364011060eac7a507a2ae063eb857ece910e27f" + dependencies: + buffer-writer "1.0.1" + js-string-escape "1.0.1" + packet-reader "0.3.1" + pg-connection-string "0.1.3" + pg-pool "1.*" + pg-types "1.*" + pgpass "1.*" + semver "4.3.2" + +pg@~7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/pg/-/pg-7.3.0.tgz#275e27466e54a645f6b4a16f6acadf6b849ad83b" dependencies: @@ -6077,7 +5907,7 @@ pg@7.3.0, pg@~7.3.0: pgpass "1.x" semver "4.3.2" -pgpass@1.x: +pgpass@1.*, pgpass@1.x: version "1.0.2" resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" dependencies: @@ -6246,25 +6076,6 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" -prebuild-install@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.2.0.tgz#55934756a32bac8747390ca44ff663cee8b99b69" - dependencies: - expand-template "^1.0.2" - github-from-package "0.0.0" - minimist "^1.2.0" - mkdirp "^0.5.1" - node-abi "^2.0.0" - noop-logger "^0.1.1" - npmlog "^4.0.1" - os-homedir "^1.0.1" - pump "^1.0.1" - rc "^1.1.6" - simple-get "^1.4.2" - tar-fs "^1.13.0" - tunnel-agent "^0.6.0" - xtend "4.0.1" - precond@0.2: version "0.2.3" resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" @@ -6360,10 +6171,6 @@ prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - ps-tree@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" @@ -6493,21 +6300,6 @@ pug@2.0.0-rc.4: pug-runtime "^2.0.3" pug-strip-comments "^1.0.2" -pump@^1.0.0, pump@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51" - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b" - dependencies: - duplexify "^3.1.2" - inherits "^2.0.1" - pump "^1.0.0" - punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -6516,6 +6308,10 @@ q@^1.1.2: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" +qr-image@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/qr-image/-/qr-image-3.2.0.tgz#9fa8295beae50c4a149cf9f909a1db464a8672e8" + qs@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" @@ -6620,7 +6416,7 @@ read@^1.0.4: dependencies: mute-stream "~0.0.4" -readable-stream@1.1.x, readable-stream@^1.0.33: +readable-stream@1.1.x: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" dependencies: @@ -6629,7 +6425,7 @@ readable-stream@1.1.x, readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -6972,36 +6768,6 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -search-index-adder@0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/search-index-adder/-/search-index-adder-0.3.9.tgz#a94b5fc5b27f1827c43eab599c760dcc4c29599d" - dependencies: - JSONStream "^1.2.1" - async "^2.3.0" - bunyan "^1.8.10" - docproc "^1.0.0" - levelup "^1.3.8" - pumpify "^1.3.5" - optionalDependencies: - leveldown "^1.7.1" - -search-index-searcher@0.2.10: - version "0.2.10" - resolved "https://registry.yarnpkg.com/search-index-searcher/-/search-index-searcher-0.2.10.tgz#3b52b8bb643065883997dfce57c6c792ec551cb0" - dependencies: - bunyan "^1.8.1" - intersect-arrays-to-stream "^0.0.3" - levelup "^1.3.8" - lodash.difference "^4.5.0" - lodash.intersection "^4.4.0" - lodash.sortedindexof "^4.1.0" - lodash.spread "^4.2.1" - lodash.union "^4.6.0" - lodash.uniq "^4.5.0" - ngraminator "0.0.1" - optionalDependencies: - leveldown "^1.6.0" - select@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" @@ -7020,14 +6786,10 @@ semver@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" -semver@5.4.1, semver@^5.4.1, semver@~5.4.1: +semver@5.4.1, semver@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" -semver@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19" - send@0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/send/-/send-0.13.1.tgz#a30d5f4c82c8a9bae9ad00a1d9b1bdbe6f199ed7" @@ -7214,14 +6976,6 @@ simple-breakpoints@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/simple-breakpoints/-/simple-breakpoints-1.1.2.tgz#2a690bb989228bc1f80acf802785f61f53ed6b92" -simple-get@^1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb" - dependencies: - once "^1.3.1" - unzip-response "^1.0.0" - xtend "^4.0.0" - simple-lru-cache@0.0.x: version "0.0.2" resolved "https://registry.yarnpkg.com/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz#d59cc3a193c1a5d0320f84ee732f6e4713e511dd" @@ -7356,20 +7110,12 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -stopword@0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stopword/-/stopword-0.1.8.tgz#b583506b0218cb2966c77cc41cb92ffda8396eb9" - stream-combiner@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" dependencies: duplexer "~0.1.1" -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - stream-to-array@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" @@ -7525,15 +7271,6 @@ table@^4.0.1: slice-ansi "0.0.4" string-width "^2.0.0" -tar-fs@^1.13.0: - version "1.15.3" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.15.3.tgz#eccf935e941493d8151028e636e51ce4c3ca7f20" - dependencies: - chownr "^1.0.1" - mkdirp "^0.5.1" - pump "^1.0.0" - tar-stream "^1.1.2" - tar-pack@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" @@ -7547,15 +7284,6 @@ tar-pack@^3.4.0: tar "^2.2.1" uid-number "^0.0.6" -tar-stream@^1.1.2: - version "1.5.4" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016" - dependencies: - bl "^1.0.0" - end-of-stream "^1.0.0" - readable-stream "^2.0.0" - xtend "^4.0.0" - tar@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/tar/-/tar-4.0.1.tgz#3f5b2e5289db30c2abe4c960f43d0d9fff96aaf0" @@ -7574,22 +7302,12 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" -term-frequency@^0.0.15: - version "0.0.15" - resolved "https://registry.yarnpkg.com/term-frequency/-/term-frequency-0.0.15.tgz#ff4aeaff2ac31ee1096b5c685852816a5da676e7" - term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" dependencies: execa "^0.7.0" -term-vector@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/term-vector/-/term-vector-0.1.2.tgz#774e7e44aef2274b3b1d8a2441981f99d0f7e0aa" - dependencies: - lodash.isequal "^4.1.3" - terraformer-wkt-parser@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz#336a0c8fc82094a5aff83288f69aedecd369bf0c" @@ -7638,7 +7356,7 @@ through2@2.0.3: readable-stream "^2.1.5" xtend "~4.0.1" -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1: +through@2, through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -7839,10 +7557,6 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" -unzip-response@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" - unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" @@ -8268,7 +7982,7 @@ xmlbuilder@^4.1.0: dependencies: lodash "^4.0.0" -xtend@4.0.1, xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From c94e2d5700724cd2dc3a4735bbe95e9cf1b567e2 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sun, 8 Oct 2017 17:21:36 -0400 Subject: [PATCH 28/33] feat: config-manager component --- client/configure.js | 4 - client/js/app.js | 2 + .../js/components/config-manager.component.js | 304 ++++++++++++++++++ client/js/components/editor-video.vue | 6 +- client/scss/app.scss | 1 + client/scss/components/button.scss | 6 +- client/scss/components/config-manager.scss | 61 ++++ server/app/data.yml | 11 + server/configure.js | 83 ++--- server/models/_relations.js | 2 - server/models/comment.js | 2 - server/models/document.js | 2 - server/models/file.js | 2 - server/models/folder.js | 2 - server/models/group.js | 2 - server/models/right.js | 2 - server/models/setting.js | 2 - server/models/tag.js | 2 - server/models/user.js | 2 - server/modules/auth.js | 2 - server/modules/config.js | 6 +- server/modules/db.js | 2 +- server/views/configure/index.pug | 106 +++--- server/views/master.pug | 2 +- 24 files changed, 461 insertions(+), 155 deletions(-) delete mode 100644 client/configure.js create mode 100644 client/js/components/config-manager.component.js create mode 100644 client/scss/components/config-manager.scss diff --git a/client/configure.js b/client/configure.js deleted file mode 100644 index 714ff901..00000000 --- a/client/configure.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict' - -require('./scss/configure.scss') -require('./js/configure.js') diff --git a/client/js/app.js b/client/js/app.js index cd4f94c9..ced4fcbc 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -52,6 +52,7 @@ import adminEditUserComponent from './pages/admin-edit-user.component.js' import adminProfileComponent from './pages/admin-profile.component.js' import adminSettingsComponent from './pages/admin-settings.component.js' import adminThemeComponent from './pages/admin-theme.component.js' +import configManagerComponent from './components/config-manager.component.js' import contentViewComponent from './pages/content-view.component.js' import editorComponent from './components/editor.component.js' import sourceViewComponent from './pages/source-view.component.js' @@ -94,6 +95,7 @@ Vue.component('adminSettings', adminSettingsComponent) Vue.component('adminTheme', adminThemeComponent) Vue.component('anchor', anchorComponent) Vue.component('colorPicker', colorPickerComponent) +Vue.component('configManager', configManagerComponent) Vue.component('contentView', contentViewComponent) Vue.component('editor', editorComponent) Vue.component('editorCodeblock', editorCodeblockComponent) diff --git a/client/js/components/config-manager.component.js b/client/js/components/config-manager.component.js new file mode 100644 index 00000000..50b8cedc --- /dev/null +++ b/client/js/components/config-manager.component.js @@ -0,0 +1,304 @@ +'use strict' + +/* global siteConfig */ + +import VeeValidate from 'vee-validate' +import axios from 'axios' + +Vue.use(VeeValidate, { + enableAutoClasses: true, + classNames: { + touched: 'is-touched', // the control has been blurred + untouched: 'is-untouched', // the control hasn't been blurred + valid: 'is-valid', // model is valid + invalid: 'is-invalid', // model is invalid + pristine: 'is-pristine', // control has not been interacted with + dirty: 'is-dirty' // control has been interacted with + } +}) + +export default { + name: 'configManager', + data() { + return { + loading: false, + state: 'welcome', + syscheck: { + ok: false, + error: '', + results: [] + }, + dbcheck: { + ok: false, + error: '' + }, + gitcheck: { + ok: false, + error: '' + }, + final: { + ok: false, + error: '', + results: [] + }, + conf: { + title: siteConfig.title || 'Wiki', + host: siteConfig.host || 'http://', + port: siteConfig.port || 80, + lang: siteConfig.lang || 'en', + public: (siteConfig.public === true), + db: siteConfig.db || 'mongodb://localhost:27017/wiki', + pathData: './data', + pathRepo: './repo', + gitUseRemote: (siteConfig.git !== false), + gitUrl: '', + gitBranch: 'master', + gitAuthType: 'ssh', + gitAuthSSHKey: '', + gitAuthUser: '', + gitAuthPass: '', + gitAuthSSL: true, + gitShowUserEmail: true, + gitServerEmail: '', + adminEmail: '', + adminPassword: '', + adminPasswordConfirm: '' + }, + considerations: { + https: false, + port: false, + localhost: false + } + } + }, + computed: { + currentProgress: function () { + let perc = '0%' + switch (this.state) { + case 'welcome': + perc = '0%' + break + case 'syscheck': + perc = (this.syscheck.ok) ? '15%' : '5%' + break + case 'general': + perc = '20%' + break + case 'considerations': + perc = '30%' + break + case 'db': + perc = '35%' + break + case 'dbcheck': + perc = (this.dbcheck.ok) ? '50%' : '40%' + break + case 'paths': + perc = '55%' + break + case 'git': + perc = '60%' + break + case 'gitcheck': + perc = (this.gitcheck.ok) ? '75%' : '65%' + break + case 'admin': + perc = '80%' + break + } + return perc + } + }, + mounted: function () { + /* if (appconfig.paths) { + this.conf.pathData = appconfig.paths.data || './data' + this.conf.pathRepo = appconfig.paths.repo || './repo' + } + if (appconfig.git !== false && _.isPlainObject(appconfig.git)) { + this.conf.gitUrl = appconfig.git.url || '' + this.conf.gitBranch = appconfig.git.branch || 'master' + this.conf.gitShowUserEmail = (appconfig.git.showUserEmail !== false) + this.conf.gitServerEmail = appconfig.git.serverEmail || '' + if (_.isPlainObject(appconfig.git.auth)) { + this.conf.gitAuthType = appconfig.git.auth.type || 'ssh' + this.conf.gitAuthSSHKey = appconfig.git.auth.privateKey || '' + this.conf.gitAuthUser = appconfig.git.auth.username || '' + this.conf.gitAuthPass = appconfig.git.auth.password || '' + this.conf.gitAuthSSL = (appconfig.git.auth.sslVerify !== false) + } + } */ + }, + methods: { + proceedToWelcome: function (ev) { + this.state = 'welcome' + this.loading = false + }, + proceedToSyscheck: function (ev) { + let self = this + this.state = 'syscheck' + this.loading = true + self.syscheck = { + ok: false, + error: '', + results: [] + } + + this.$helpers._.delay(() => { + axios.post('/syscheck').then(resp => { + if (resp.data.ok === true) { + self.syscheck.ok = true + self.syscheck.results = resp.data.results + } else { + self.syscheck.ok = false + self.syscheck.error = resp.data.error + } + self.loading = false + self.$nextTick() + }).catch(err => { + window.alert(err.message) + }) + }, 1000) + }, + proceedToGeneral: function (ev) { + let self = this + self.state = 'general' + self.loading = false + self.$nextTick(() => { + self.$validator.validateAll('general') + }) + }, + proceedToConsiderations: function (ev) { + this.considerations = { + https: !this.$helpers._.startsWith(this.conf.host, 'https'), + port: false, // TODO + localhost: this.$helpers._.includes(this.conf.host, 'localhost') + } + this.state = 'considerations' + this.loading = false + }, + proceedToDb: function (ev) { + let self = this + self.state = 'db' + self.loading = false + self.$nextTick(() => { + self.$validator.validateAll('db') + }) + }, + proceedToDbcheck: function (ev) { + let self = this + this.state = 'dbcheck' + this.loading = true + self.dbcheck = { + ok: false, + error: '' + } + + this.$helpers._.delay(() => { + axios.post('/dbcheck', { + db: self.conf.db + }).then(resp => { + if (resp.data.ok === true) { + self.dbcheck.ok = true + } else { + self.dbcheck.ok = false + self.dbcheck.error = resp.data.error + } + self.loading = false + self.$nextTick() + }).catch(err => { + window.alert(err.message) + }) + }, 1000) + }, + proceedToPaths: function (ev) { + let self = this + self.state = 'paths' + self.loading = false + self.$nextTick(() => { + self.$validator.validateAll('paths') + }) + }, + proceedToGit: function (ev) { + let self = this + self.state = 'git' + self.loading = false + self.$nextTick(() => { + self.$validator.validateAll('git') + }) + }, + proceedToGitCheck: function (ev) { + let self = this + this.state = 'gitcheck' + this.loading = true + self.gitcheck = { + ok: false, + results: [], + error: '' + } + + this.$helpers._.delay(() => { + axios.post('/gitcheck', self.conf).then(resp => { + if (resp.data.ok === true) { + self.gitcheck.ok = true + self.gitcheck.results = resp.data.results + } else { + self.gitcheck.ok = false + self.gitcheck.error = resp.data.error + } + self.loading = false + self.$nextTick() + }).catch(err => { + window.alert(err.message) + }) + }, 1000) + }, + proceedToAdmin: function (ev) { + let self = this + self.state = 'admin' + self.loading = false + self.$nextTick(() => { + self.$validator.validateAll('admin') + }) + }, + proceedToFinal: function (ev) { + let self = this + self.state = 'final' + self.loading = true + self.final = { + ok: false, + error: '', + results: [] + } + + this.$helpers._.delay(() => { + axios.post('/finalize', self.conf).then(resp => { + if (resp.data.ok === true) { + self.final.ok = true + self.final.results = resp.data.results + } else { + self.final.ok = false + self.final.error = resp.data.error + } + self.loading = false + self.$nextTick() + }).catch(err => { + window.alert(err.message) + }) + }, 1000) + }, + finish: function (ev) { + let self = this + self.state = 'restart' + + this.$helpers._.delay(() => { + axios.post('/restart', {}).then(resp => { + this.$helpers._.delay(() => { + window.location.assign(self.conf.host) + }, 30000) + }).catch(err => { + window.alert(err.message) + }) + }, 1000) + } + } +} diff --git a/client/js/components/editor-video.vue b/client/js/components/editor-video.vue index 38e9fef8..50e998ed 100644 --- a/client/js/components/editor-video.vue +++ b/client/js/components/editor-video.vue @@ -34,9 +34,9 @@