diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/config/default.js | 6 | ||||
-rw-r--r-- | lib/config/environment.js | 3 | ||||
-rw-r--r-- | lib/config/index.js | 17 | ||||
-rw-r--r-- | lib/config/utils.js | 33 | ||||
-rw-r--r-- | lib/logger.js | 36 | ||||
-rw-r--r-- | lib/migrations/20150702001020-update-to-0_3_1.js | 2 | ||||
-rw-r--r-- | lib/migrations/20160112220142-note-add-lastchange.js | 2 | ||||
-rw-r--r-- | lib/migrations/20160420180355-note-add-alias.js | 2 | ||||
-rw-r--r-- | lib/migrations/20160515114000-user-add-tokens.js | 2 | ||||
-rw-r--r-- | lib/migrations/20160607060246-support-revision.js | 2 | ||||
-rw-r--r-- | lib/migrations/20160703062241-support-authorship.js | 2 | ||||
-rw-r--r-- | lib/migrations/20161009040430-support-delete-note.js | 2 | ||||
-rw-r--r-- | lib/migrations/20161201050312-support-email-signin.js | 2 | ||||
-rw-r--r-- | lib/models/index.js | 1 | ||||
-rw-r--r-- | lib/models/user.js | 2 | ||||
-rwxr-xr-x | lib/ot/editor-socketio-server.js | 10 | ||||
-rw-r--r-- | lib/realtime.js | 5 | ||||
-rw-r--r-- | lib/response.js | 5 | ||||
-rw-r--r-- | lib/web/auth/oauth2/index.js | 8 | ||||
-rw-r--r-- | lib/web/imageRouter/filesystem.js | 2 | ||||
-rw-r--r-- | lib/web/statusRouter.js | 2 |
21 files changed, 104 insertions, 42 deletions
diff --git a/lib/config/default.js b/lib/config/default.js index c3ada982..d7a8f471 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -1,10 +1,13 @@ 'use strict' +const os = require('os') + module.exports = { domain: '', urlPath: '', host: '0.0.0.0', port: 3000, + loglevel: 'info', urlAddPort: false, allowOrigin: ['localhost'], useSSL: false, @@ -29,6 +32,7 @@ module.exports = { allowAnonymous: true, allowAnonymousEdits: false, allowFreeURL: false, + forbiddenNoteIDs: ['robots.txt', 'favicon.ico', 'api'], defaultPermission: 'editable', dbURL: '', db: {}, @@ -39,7 +43,7 @@ module.exports = { dhParamPath: '', // other path viewPath: './public/views', - tmpPath: './tmp', + tmpPath: os.tmpdir(), defaultNotePath: './public/default.md', docsPath: './public/docs', uploadsPath: './public/uploads', diff --git a/lib/config/environment.js b/lib/config/environment.js index 6737637c..a57fe0db 100644 --- a/lib/config/environment.js +++ b/lib/config/environment.js @@ -3,11 +3,13 @@ const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils') module.exports = { + sourceURL: process.env.CMD_SOURCE_URL, domain: process.env.CMD_DOMAIN, urlPath: process.env.CMD_URL_PATH, host: process.env.CMD_HOST, port: toIntegerConfig(process.env.CMD_PORT), path: process.env.CMD_PATH, + loglevel: process.env.CMD_LOGLEVEL, urlAddPort: toBooleanConfig(process.env.CMD_URL_ADDPORT), useSSL: toBooleanConfig(process.env.CMD_USESSL), hsts: { @@ -26,6 +28,7 @@ module.exports = { allowAnonymous: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS), allowAnonymousEdits: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_EDITS), allowFreeURL: toBooleanConfig(process.env.CMD_ALLOW_FREEURL), + forbiddenNoteIDs: toArrayConfig(process.env.CMD_FORBIDDEN_NOTE_IDS), defaultPermission: process.env.CMD_DEFAULT_PERMISSION, dbURL: process.env.CMD_DB_URL, sessionSecret: process.env.CMD_SESSION_SECRET, diff --git a/lib/config/index.js b/lib/config/index.js index 501fdca3..c1005b0b 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -8,6 +8,7 @@ const {merge} = require('lodash') const deepFreeze = require('deep-freeze') const {Environment, Permission} = require('./enum') const logger = require('../logger') +const {getGitCommit, getGitHubURL} = require('./utils') const appRootPath = path.resolve(__dirname, '../../') const env = process.env.NODE_ENV || Environment.development @@ -16,11 +17,17 @@ const debugConfig = { } // Get version string from package.json -const {version} = require(path.join(appRootPath, 'package.json')) +const {version, repository} = require(path.join(appRootPath, 'package.json')) + +const commitID = getGitCommit(appRootPath) +const sourceURL = getGitHubURL(repository.url, commitID || version) +const fullversion = commitID ? `${version}-${commitID}` : version const packageConfig = { version: version, - minimumCompatibleVersion: '0.5.0' + minimumCompatibleVersion: '0.5.0', + fullversion: fullversion, + sourceURL: sourceURL } const configFilePath = path.resolve(appRootPath, process.env.CMD_CONFIG_FILE || @@ -38,6 +45,12 @@ merge(config, require('./hackmdEnvironment')) merge(config, require('./environment')) merge(config, require('./dockerSecret')) +if (['debug', 'verbose', 'info', 'warn', 'error'].includes(config.loglevel)) { + logger.level = config.loglevel +} else { + logger.error('Selected loglevel %s doesn\'t exist, using default level \'debug\'. Available options: debug, verbose, info, warn, error', config.loglevel) +} + // load LDAP CA if (config.ldap.tlsca) { let ca = config.ldap.tlsca.split(',') diff --git a/lib/config/utils.js b/lib/config/utils.js index b2406cf1..9646f8c0 100644 --- a/lib/config/utils.js +++ b/lib/config/utils.js @@ -1,5 +1,8 @@ 'use strict' +const fs = require('fs') +const path = require('path') + exports.toBooleanConfig = function toBooleanConfig (configValue) { if (configValue && typeof configValue === 'string') { return (configValue === 'true') @@ -20,3 +23,33 @@ exports.toIntegerConfig = function toIntegerConfig (configValue) { } return configValue } + +exports.getGitCommit = function getGitCommit (repodir) { + if (!fs.existsSync(repodir + '/.git/HEAD')) { + return undefined + } + let reference = fs.readFileSync(repodir + '/.git/HEAD', 'utf8') + if (reference.startsWith('ref: ')) { + reference = reference.substr(5).replace('\n', '') + reference = fs.readFileSync(path.resolve(repodir + '/.git', reference), 'utf8') + } + reference = reference.replace('\n', '') + return reference +} + +exports.getGitHubURL = function getGitHubURL (repo, reference) { + // if it's not a github reference, we handle handle that anyway + if (!repo.startsWith('https://github.com') && !repo.startsWith('git@github.com')) { + return repo + } + if (repo.startsWith('git@github.com') || repo.startsWith('ssh://git@github.com')) { + repo = repo.replace(/^(ssh:\/\/)?git@github.com:/, 'https://github.com/') + } + + if (repo.endsWith('.git')) { + repo = repo.replace(/\.git$/, '/') + } else if (!repo.endsWith('/')) { + repo = repo + '/' + } + return repo + 'tree/' + reference +} diff --git a/lib/logger.js b/lib/logger.js index f8b3895c..5ef1860a 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -1,23 +1,27 @@ 'use strict' -const winston = require('winston') +const {createLogger, format, transports} = require('winston') -class Logger extends winston.Logger { - // Implement stream.writable.write interface - write (chunk) { - this.info(chunk) - } -} - -module.exports = new Logger({ +const logger = createLogger({ + level: 'debug', + format: format.combine( + format.uncolorize(), + format.timestamp(), + format.align(), + format.splat(), + format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`) + ), transports: [ - new winston.transports.Console({ - level: 'debug', - handleExceptions: true, - json: false, - colorize: false, - timestamp: true + new transports.Console({ + handleExceptions: true }) ], - emitErrs: true, exitOnError: false }) + +logger.stream = { + write: function (message, encoding) { + logger.info(message) + } +} + +module.exports = logger diff --git a/lib/migrations/20150702001020-update-to-0_3_1.js b/lib/migrations/20150702001020-update-to-0_3_1.js index eb18211f..e1a88661 100644 --- a/lib/migrations/20150702001020-update-to-0_3_1.js +++ b/lib/migrations/20150702001020-update-to-0_3_1.js @@ -21,7 +21,7 @@ module.exports = { defaultValue: 0 }) }).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'shortid'" || error.message === 'column "shortid" of relation "Notes" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: shortid' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'shortid'" || error.message === 'column "shortid" of relation "Notes" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/migrations/20160112220142-note-add-lastchange.js b/lib/migrations/20160112220142-note-add-lastchange.js index 682337c9..87e3ff19 100644 --- a/lib/migrations/20160112220142-note-add-lastchange.js +++ b/lib/migrations/20160112220142-note-add-lastchange.js @@ -8,7 +8,7 @@ module.exports = { type: Sequelize.DATE }) }).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'lastchangeuserId'" || error.message === 'column "lastchangeuserId" of relation "Notes" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: lastchangeuserId' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'lastchangeuserId'" || error.message === 'column "lastchangeuserId" of relation "Notes" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/migrations/20160420180355-note-add-alias.js b/lib/migrations/20160420180355-note-add-alias.js index 6cc1337e..45d53e69 100644 --- a/lib/migrations/20160420180355-note-add-alias.js +++ b/lib/migrations/20160420180355-note-add-alias.js @@ -8,7 +8,7 @@ module.exports = { indicesType: 'UNIQUE' }) }).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'alias'" || error.message === 'column "alias" of relation "Notes" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: alias' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'alias'" || error.message === 'column "alias" of relation "Notes" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/migrations/20160515114000-user-add-tokens.js b/lib/migrations/20160515114000-user-add-tokens.js index 8bf6d11f..435ae9cb 100644 --- a/lib/migrations/20160515114000-user-add-tokens.js +++ b/lib/migrations/20160515114000-user-add-tokens.js @@ -4,7 +4,7 @@ module.exports = { return queryInterface.addColumn('Users', 'accessToken', Sequelize.STRING).then(function () { return queryInterface.addColumn('Users', 'refreshToken', Sequelize.STRING) }).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'accessToken'" || error.message === 'column "accessToken" of relation "Users" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: accessToken' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'accessToken'" || error.message === 'column "accessToken" of relation "Users" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/migrations/20160607060246-support-revision.js b/lib/migrations/20160607060246-support-revision.js index 465a09fa..547f89b8 100644 --- a/lib/migrations/20160607060246-support-revision.js +++ b/lib/migrations/20160607060246-support-revision.js @@ -16,7 +16,7 @@ module.exports = { updatedAt: Sequelize.DATE }) }).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'savedAt'" || error.message === 'column "savedAt" of relation "Notes" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: savedAt' | error.message === "ER_DUP_FIELDNAME: Duplicate column name 'savedAt'" || error.message === 'column "savedAt" of relation "Notes" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/migrations/20160703062241-support-authorship.js b/lib/migrations/20160703062241-support-authorship.js index ccdfeb3e..f452b1a7 100644 --- a/lib/migrations/20160703062241-support-authorship.js +++ b/lib/migrations/20160703062241-support-authorship.js @@ -17,7 +17,7 @@ module.exports = { updatedAt: Sequelize.DATE }) }).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'authorship'" || error.message === 'column "authorship" of relation "Notes" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: authorship' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'authorship'" || error.message === 'column "authorship" of relation "Notes" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/migrations/20161009040430-support-delete-note.js b/lib/migrations/20161009040430-support-delete-note.js index 39e6f7fb..56a336ac 100644 --- a/lib/migrations/20161009040430-support-delete-note.js +++ b/lib/migrations/20161009040430-support-delete-note.js @@ -2,7 +2,7 @@ module.exports = { up: function (queryInterface, Sequelize) { return queryInterface.addColumn('Notes', 'deletedAt', Sequelize.DATE).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'deletedAt'" || error.message === 'column "deletedAt" of relation "Notes" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: deletedAt' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'deletedAt'" || error.message === 'column "deletedAt" of relation "Notes" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/migrations/20161201050312-support-email-signin.js b/lib/migrations/20161201050312-support-email-signin.js index 0a8a832d..26bc09ea 100644 --- a/lib/migrations/20161201050312-support-email-signin.js +++ b/lib/migrations/20161201050312-support-email-signin.js @@ -10,7 +10,7 @@ module.exports = { } }) }).catch(function (error) { - if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'email'" || error.message === 'column "email" of relation "Users" already exists') { + if (error.message === 'SQLITE_ERROR: duplicate column name: email' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'email'" || error.message === 'column "email" of relation "Users" already exists') { console.log('Migration has already run… ignoring.') } else { throw error diff --git a/lib/models/index.js b/lib/models/index.js index 0a44ca87..ef70475e 100644 --- a/lib/models/index.js +++ b/lib/models/index.js @@ -25,6 +25,7 @@ if (config.dbURL) { // https://github.com/sequelize/sequelize/issues/6485 function stripNullByte (value) { value = '' + value + // eslint-disable-next-line no-control-regex return value ? value.replace(/\u0000/g, '') : value } sequelize.stripNullByte = stripNullByte diff --git a/lib/models/user.js b/lib/models/user.js index 1bd8c745..2ebf6d06 100644 --- a/lib/models/user.js +++ b/lib/models/user.js @@ -50,7 +50,7 @@ module.exports = function (sequelize, DataTypes) { }, { instanceMethods: { verifyPassword: function (attempt) { - if (scrypt.verifyKdfSync(new Buffer(this.password, 'hex'), attempt)) { + if (scrypt.verifyKdfSync(Buffer.from(this.password, 'hex'), attempt)) { return this } else { return false diff --git a/lib/ot/editor-socketio-server.js b/lib/ot/editor-socketio-server.js index 7b204539..5014ac8d 100755 --- a/lib/ot/editor-socketio-server.js +++ b/lib/ot/editor-socketio-server.js @@ -44,7 +44,7 @@ EditorSocketIOServer.prototype.addClient = function (socket) { socket.origin = 'operation'; self.mayWrite(socket, function (mayWrite) { if (!mayWrite) { - console.log("User doesn't have the right to edit."); + logger.info("User doesn't have the right to edit."); return; } try { @@ -71,14 +71,14 @@ EditorSocketIOServer.prototype.addClient = function (socket) { socket.origin = 'selection'; self.mayWrite(socket, function (mayWrite) { if (!mayWrite) { - console.log("User doesn't have the right to edit."); + logger.info("User doesn't have the right to edit."); return; } self.updateSelection(socket, obj && Selection.fromJSON(obj)); }); }); socket.on('disconnect', function () { - //console.log("Disconnect"); + logger.debug("Disconnect"); socket.leave(self.docId); self.onDisconnect(socket); /* @@ -106,7 +106,7 @@ EditorSocketIOServer.prototype.onOperation = function (socket, revision, operati var clientId = socket.id; var wrappedPrime = this.receiveOperation(revision, wrapped); if(!wrappedPrime) return; - //console.log("new operation: " + JSON.stringify(wrapped)); + logger.debug("new operation: " + JSON.stringify(wrapped)); this.getClient(clientId).selection = wrappedPrime.meta; revision = this.operations.length; socket.emit('ack', revision); @@ -161,4 +161,4 @@ EditorSocketIOServer.prototype.onDisconnect = function (socket) { socket.broadcast.to(this.docId).emit('client_left', clientId); }; -module.exports = EditorSocketIOServer;
\ No newline at end of file +module.exports = EditorSocketIOServer; diff --git a/lib/realtime.js b/lib/realtime.js index f6c62d4e..d04ffdc2 100644 --- a/lib/realtime.js +++ b/lib/realtime.js @@ -242,6 +242,7 @@ function getStatus (callback) { } }) models.User.count().then(function (regcount) { + // eslint-disable-next-line standard/no-callback-literal return callback ? callback({ onlineNotes: Object.keys(notes).length, onlineUsers: Object.keys(users).length, @@ -283,7 +284,7 @@ function extractNoteIdFromSocket (socket) { if (!referer) { return false } - var hostUrl = url.parse(referer) + var hostUrl = url.URL.parse(referer) var noteId = config.urlPath ? hostUrl.pathname.slice(config.urlPath.length + 1, hostUrl.pathname.length).split('/')[1] : hostUrl.pathname.split('/')[1] return noteId } else { @@ -887,7 +888,7 @@ function connection (socket) { // check version socket.on('version', function () { socket.emit('version', { - version: config.version, + version: config.fullversion, minimumCompatibleVersion: config.minimumCompatibleVersion }) }) diff --git a/lib/response.js b/lib/response.js index 3cbd3203..b94f473a 100644 --- a/lib/response.js +++ b/lib/response.js @@ -157,7 +157,7 @@ function findNote (req, res, callback, include) { include: include || null }).then(function (note) { if (!note) { - if (config.allowFreeURL && noteId) { + if (config.allowFreeURL && noteId && !config.forbiddenNoteIDs.includes(noteId)) { req.alias = noteId return newNote(req, res) } else { @@ -423,6 +423,9 @@ function publishNoteActions (req, res, next) { findNote(req, res, function (note) { var action = req.params.action switch (action) { + case 'download': + actionDownload(req, res, note) + break case 'edit': res.redirect(config.serverURL + '/' + (note.alias ? note.alias : models.Note.encodeNoteId(note.id))) break diff --git a/lib/web/auth/oauth2/index.js b/lib/web/auth/oauth2/index.js index f2a3132d..b9160f6e 100644 --- a/lib/web/auth/oauth2/index.js +++ b/lib/web/auth/oauth2/index.js @@ -2,13 +2,13 @@ const Router = require('express').Router const passport = require('passport') -const OAuth2Strategy = require('passport-oauth2').Strategy +const { Strategy, InternalOAuthError } = require('passport-oauth2') const config = require('../../../config') const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') let oauth2Auth = module.exports = Router() -class OAuth2CustomStrategy extends OAuth2Strategy { +class OAuth2CustomStrategy extends Strategy { constructor (options, verify) { options.customHeaders = options.customHeaders || {} super(options, verify) @@ -22,7 +22,7 @@ class OAuth2CustomStrategy extends OAuth2Strategy { var json if (err) { - return done(new passport.InternalOAuthError('Failed to fetch user profile', err)) + return done(new InternalOAuthError('Failed to fetch user profile', err)) } try { @@ -67,7 +67,7 @@ OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) { var json if (err) { - return done(new passport.InternalOAuthError('Failed to fetch user profile', err)) + return done(new InternalOAuthError('Failed to fetch user profile', err)) } try { diff --git a/lib/web/imageRouter/filesystem.js b/lib/web/imageRouter/filesystem.js index 8c432b0c..a2f8700d 100644 --- a/lib/web/imageRouter/filesystem.js +++ b/lib/web/imageRouter/filesystem.js @@ -16,5 +16,5 @@ exports.uploadImage = function (imagePath, callback) { return } - callback(null, url.resolve(config.serverURL + '/uploads/', path.basename(imagePath))) + callback(null, url.URL.resolve(config.serverURL + '/uploads/', path.basename(imagePath))) } diff --git a/lib/web/statusRouter.js b/lib/web/statusRouter.js index fb2609ea..2b9cb65f 100644 --- a/lib/web/statusRouter.js +++ b/lib/web/statusRouter.js @@ -96,7 +96,7 @@ statusRouter.get('/config', function (req, res) { domain: config.domain, urlpath: config.urlPath, debug: config.debug, - version: config.version, + version: config.fullversion, DROPBOX_APP_KEY: config.dropbox.appKey, allowedUploadMimeTypes: config.allowedUploadMimeTypes } |