Skip to content

Commit

Permalink
Merge pull request #1557 from hackmdio/release/2.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jackycute authored Jul 20, 2020
2 parents 89a0de4 + fad1947 commit 3e75445
Show file tree
Hide file tree
Showing 88 changed files with 2,090 additions and 244 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ public/uploads/*
!public/uploads/.gitkeep
/.nyc_output
/coverage/

.vscode/settings.json
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v10.20.1
6 changes: 6 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,18 @@ models.sequelize.sync().then(function () {
} else {
throw new Error('server still not ready after db synced')
}
}).catch(err => {
logger.error('Can\'t sync database')
logger.error(err.stack)
logger.error('Process will exit now.')
process.exit(1)
})

// log uncaught exception
process.on('uncaughtException', function (err) {
logger.error('An uncaught exception has occured.')
logger.error(err)
console.error(err)
logger.error('Process will exit now.')
process.exit(1)
})
Expand Down
7 changes: 5 additions & 2 deletions deployments/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ services:
- "database-data:/var/lib/postgresql/data"
restart: always
codimd:
# you can use image or custom build below
image: nabo.codimd.dev/hackmdio/hackmd:2.0.0
# you can use image or custom build below,
# if you need CJK character with exported PDF files,
# please change the image tag with `cjk` postfix version
image: nabo.codimd.dev/hackmdio/hackmd:2.1.0
# image: nabo.codimd.dev/hackmdio/hackmd:2.1.0-cjk
# build:
# context: ..
# dockerfile: ./deployments/Dockerfile
Expand Down
4 changes: 2 additions & 2 deletions lib/auth/gitlab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ const gitlabAuthStrategy = new GitlabStrategy({
callbackURL: config.serverURL + '/auth/gitlab/callback'
}, passportGeneralCallback)

if (process.env['https_proxy']) {
const httpsProxyAgent = new HttpsProxyAgent(process.env['https_proxy'])
if (process.env.https_proxy) {
const httpsProxyAgent = new HttpsProxyAgent(process.env.https_proxy)
gitlabAuthStrategy._oauth2.setAgent(httpsProxyAgent)
}

Expand Down
4 changes: 2 additions & 2 deletions lib/history/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function historyPost (req, res) {
if (req.isAuthenticated()) {
var noteId = req.params.noteId
if (!noteId) {
if (typeof req.body['history'] === 'undefined') return response.errorBadRequest(req, res)
if (typeof req.body.history === 'undefined') return response.errorBadRequest(req, res)
if (config.debug) { logger.info('SERVER received history from [' + req.user.id + ']: ' + req.body.history) }
try {
var history = JSON.parse(req.body.history)
Expand All @@ -147,7 +147,7 @@ function historyPost (req, res) {
return response.errorBadRequest(req, res)
}
} else {
if (typeof req.body['pinned'] === 'undefined') return response.errorBadRequest(req, res)
if (typeof req.body.pinned === 'undefined') return response.errorBadRequest(req, res)
getHistory(req.user.id, function (err, history) {
if (err) return response.errorInternalError(req, res)
if (!history) return response.errorNotFound(req, res)
Expand Down
46 changes: 44 additions & 2 deletions lib/imageRouter/filesystem.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
'use strict'

const crypto = require('crypto')
const fs = require('fs')
const URL = require('url').URL
const path = require('path')

const config = require('../config')
const logger = require('../logger')

/**
* generate a random filename for uploaded image
*/
function randomFilename () {
const buf = crypto.randomBytes(16)
return `upload_${buf.toString('hex')}`
}

/**
* pick a filename not exist in filesystem
* maximum attempt 5 times
*/
function pickFilename (defaultFilename) {
let retryCounter = 5
let filename = defaultFilename
const extname = path.extname(defaultFilename)
while (retryCounter-- > 0) {
if (fs.existsSync(path.join(config.uploadsPath, filename))) {
filename = `${randomFilename()}${extname}`
continue
}
return filename
}
throw new Error('file exists.')
}

exports.uploadImage = function (imagePath, callback) {
if (!imagePath || typeof imagePath !== 'string') {
callback(new Error('Image path is missing or wrong'), null)
Expand All @@ -16,11 +45,24 @@ exports.uploadImage = function (imagePath, callback) {
return
}

let filename = path.basename(imagePath)
try {
filename = pickFilename(path.basename(imagePath))
} catch (e) {
return callback(e, null)
}

try {
fs.copyFileSync(imagePath, path.join(config.uploadsPath, filename))
} catch (e) {
return callback(e, null)
}

let url
try {
url = (new URL(path.basename(imagePath), config.serverURL + '/uploads/')).href
url = (new URL(filename, config.serverURL + '/uploads/')).href
} catch (e) {
url = config.serverURL + '/uploads/' + path.basename(imagePath)
url = config.serverURL + '/uploads/' + filename
}

callback(null, url)
Expand Down
7 changes: 3 additions & 4 deletions lib/imageRouter/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict'

const fs = require('fs')
const Router = require('express').Router
const formidable = require('formidable')

Expand All @@ -15,10 +16,6 @@ imageRouter.post('/uploadimage', function (req, res) {

form.keepExtensions = true

if (config.imageUploadType === 'filesystem') {
form.uploadDir = config.uploadsPath
}

form.parse(req, function (err, fields, files) {
if (err || !files.image || !files.image.path) {
response.errorForbidden(req, res)
Expand All @@ -29,6 +26,8 @@ imageRouter.post('/uploadimage', function (req, res) {

const uploadProvider = require('./' + config.imageUploadType)
uploadProvider.uploadImage(files.image.path, function (err, url) {
// remove temporary upload file, and ignore any error
fs.unlink(files.image.path, () => {})
if (err !== null) {
logger.error(err)
return res.status(500).end('upload image error')
Expand Down
7 changes: 6 additions & 1 deletion lib/models/note.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,13 @@ module.exports = function (sequelize, DataTypes) {
Note.extractNoteTags = function (meta, $) {
var tags = []
var rawtags = []
var metaTags
if (meta.tags && (typeof meta.tags === 'string' || typeof meta.tags === 'number')) {
var metaTags = ('' + meta.tags).split(',')
metaTags = ('' + meta.tags).split(',')
} else if (meta.tags && (Array.isArray(meta.tags))) {
metaTags = meta.tags
}
if (metaTags) {
for (let i = 0; i < metaTags.length; i++) {
var text = metaTags[i].trim()
if (text) rawtags.push(text)
Expand Down
47 changes: 45 additions & 2 deletions lib/note/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

const config = require('../config')
const logger = require('../logger')

const { Note, User } = require('../models')

const { newCheckViewPermission, errorForbidden, responseCodiMD, errorNotFound } = require('../response')
const { newCheckViewPermission, errorForbidden, responseCodiMD, errorNotFound, errorInternalError } = require('../response')
const { updateHistory } = require('../history')
const { actionPublish, actionSlide, actionInfo, actionDownload, actionPDF, actionGist, actionRevision, actionPandoc } = require('./noteActions')

Expand Down Expand Up @@ -121,6 +120,7 @@ async function showPublishNote (req, res) {
const data = {
title: title,
description: meta.description || (markdown ? Note.generateDescription(markdown) : null),
image: meta.image,
viewcount: note.viewcount,
createtime: createTime,
updatetime: updateTime,
Expand Down Expand Up @@ -190,6 +190,49 @@ async function noteActions (req, res) {
}
}

async function getMyNoteList (userId, callback) {
const myNotes = await Note.findAll({
where: {
ownerId: userId
}
})
if (!myNotes) {
return callback(null, null)
}
try {
const myNoteList = myNotes.map(note => ({
id: Note.encodeNoteId(note.id),
text: note.title,
tags: Note.parseNoteInfo(note.content).tags,
createdAt: note.createdAt,
lastchangeAt: note.lastchangeAt,
shortId: note.shortid
}))
if (config.debug) {
logger.info('Parse myNoteList success: ' + userId)
}
return callback(null, myNoteList)
} catch (err) {
logger.error('Parse myNoteList failed')
return callback(err, null)
}
}

function listMyNotes (req, res) {
if (req.isAuthenticated()) {
getMyNoteList(req.user.id, (err, myNoteList) => {
if (err) return errorInternalError(req, res)
if (!myNoteList) return errorNotFound(req, res)
res.send({
myNotes: myNoteList
})
})
} else {
return errorForbidden(req, res)
}
}

exports.showNote = showNote
exports.showPublishNote = showPublishNote
exports.noteActions = noteActions
exports.listMyNotes = listMyNotes
2 changes: 2 additions & 0 deletions lib/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ appRouter.get('/s/:shortid/:action', response.publishNoteActions)
appRouter.get('/p/:shortid', response.showPublishSlide)
// publish slide actions
appRouter.get('/p/:shortid/:action', response.publishSlideActions)
// gey my note list
appRouter.get('/api/notes/myNotes', noteController.listMyNotes)
// get note by id
appRouter.get('/:noteId', wrap(noteController.showNote))
// note actions
Expand Down
Loading

0 comments on commit 3e75445

Please sign in to comment.