summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/config/default.js6
-rw-r--r--lib/config/environment.js3
-rw-r--r--lib/config/index.js17
-rw-r--r--lib/config/utils.js33
-rw-r--r--lib/logger.js36
-rw-r--r--lib/migrations/20150702001020-update-to-0_3_1.js2
-rw-r--r--lib/migrations/20160112220142-note-add-lastchange.js2
-rw-r--r--lib/migrations/20160420180355-note-add-alias.js2
-rw-r--r--lib/migrations/20160515114000-user-add-tokens.js2
-rw-r--r--lib/migrations/20160607060246-support-revision.js2
-rw-r--r--lib/migrations/20160703062241-support-authorship.js2
-rw-r--r--lib/migrations/20161009040430-support-delete-note.js2
-rw-r--r--lib/migrations/20161201050312-support-email-signin.js2
-rw-r--r--lib/models/index.js1
-rw-r--r--lib/models/user.js2
-rwxr-xr-xlib/ot/editor-socketio-server.js10
-rw-r--r--lib/realtime.js5
-rw-r--r--lib/response.js5
-rw-r--r--lib/web/auth/oauth2/index.js8
-rw-r--r--lib/web/imageRouter/filesystem.js2
-rw-r--r--lib/web/statusRouter.js2
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
}