mirror of https://github.com/status-im/codimd.git
feat: merge all route to single file
Signed-off-by: BoHong Li <raccoon@hackmd.io>
This commit is contained in:
parent
80859f6cf7
commit
68fcf35c70
8
app.js
8
app.js
|
@ -206,13 +206,7 @@ app.locals.enableDropBoxSave = config.isDropboxEnable
|
|||
app.locals.enableGitHubGist = config.isGitHubEnable
|
||||
app.locals.enableGitlabSnippets = config.isGitlabSnippetsEnable
|
||||
|
||||
app.use(require('./lib/web/baseRouter'))
|
||||
app.use(require('./lib/web/statusRouter'))
|
||||
app.use(require('./lib/web/auth'))
|
||||
app.use(require('./lib/web/historyRouter'))
|
||||
app.use(require('./lib/web/userRouter'))
|
||||
app.use(require('./lib/web/imageRouter'))
|
||||
app.use(require('./lib/web/noteRouter'))
|
||||
app.use(require('./lib/web/routes').router)
|
||||
|
||||
// response not found if no any route matxches
|
||||
app.get('*', function (req, res) {
|
||||
|
|
|
@ -14,7 +14,7 @@ const get = require('lodash/get')
|
|||
// core
|
||||
const config = require('./config')
|
||||
const logger = require('./logger')
|
||||
const history = require('./history')
|
||||
const history = require('./web/history')
|
||||
const models = require('./models')
|
||||
|
||||
// ot
|
||||
|
@ -247,59 +247,62 @@ async function _updateNoteAsync (note) {
|
|||
}
|
||||
|
||||
// TODO: test it
|
||||
function getStatus (callback) {
|
||||
models.Note.count().then(function (notecount) {
|
||||
var distinctaddresses = []
|
||||
var regaddresses = []
|
||||
var distinctregaddresses = []
|
||||
Object.keys(users).forEach(function (key) {
|
||||
var user = users[key]
|
||||
if (!user) return
|
||||
let found = false
|
||||
for (let i = 0; i < distinctaddresses.length; i++) {
|
||||
if (user.address === distinctaddresses[i]) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
distinctaddresses.push(user.address)
|
||||
}
|
||||
if (user.login) {
|
||||
regaddresses.push(user.address)
|
||||
function getStatus () {
|
||||
return models.Note.count()
|
||||
.then(function (notecount) {
|
||||
var distinctaddresses = []
|
||||
var regaddresses = []
|
||||
var distinctregaddresses = []
|
||||
Object.keys(users).forEach(function (key) {
|
||||
var user = users[key]
|
||||
if (!user) return
|
||||
let found = false
|
||||
for (let i = 0; i < distinctregaddresses.length; i++) {
|
||||
if (user.address === distinctregaddresses[i]) {
|
||||
for (let i = 0; i < distinctaddresses.length; i++) {
|
||||
if (user.address === distinctaddresses[i]) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
distinctregaddresses.push(user.address)
|
||||
distinctaddresses.push(user.address)
|
||||
}
|
||||
}
|
||||
})
|
||||
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,
|
||||
distinctOnlineUsers: distinctaddresses.length,
|
||||
notesCount: notecount,
|
||||
registeredUsers: regcount,
|
||||
onlineRegisteredUsers: regaddresses.length,
|
||||
distinctOnlineRegisteredUsers: distinctregaddresses.length,
|
||||
isConnectionBusy: connectProcessQueue.lock,
|
||||
connectionSocketQueueLength: connectProcessQueue.queue.length,
|
||||
isDisconnectBusy: disconnectProcessQueue.lock,
|
||||
disconnectSocketQueueLength: disconnectProcessQueue.queue.length
|
||||
}) : null
|
||||
if (user.login) {
|
||||
regaddresses.push(user.address)
|
||||
let found = false
|
||||
for (let i = 0; i < distinctregaddresses.length; i++) {
|
||||
if (user.address === distinctregaddresses[i]) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
distinctregaddresses.push(user.address)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return models.User.count()
|
||||
.then(function (regcount) {
|
||||
return {
|
||||
onlineNotes: Object.keys(notes).length,
|
||||
onlineUsers: Object.keys(users).length,
|
||||
distinctOnlineUsers: distinctaddresses.length,
|
||||
notesCount: notecount,
|
||||
registeredUsers: regcount,
|
||||
onlineRegisteredUsers: regaddresses.length,
|
||||
distinctOnlineRegisteredUsers: distinctregaddresses.length,
|
||||
isConnectionBusy: connectProcessQueue.lock,
|
||||
connectionSocketQueueLength: connectProcessQueue.queue.length,
|
||||
isDisconnectBusy: disconnectProcessQueue.lock,
|
||||
disconnectSocketQueueLength: disconnectProcessQueue.queue.length
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
return logger.error('count user failed: ' + err)
|
||||
})
|
||||
}).catch(function (err) {
|
||||
return logger.error('count user failed: ' + err)
|
||||
return logger.error('count note failed: ' + err)
|
||||
})
|
||||
}).catch(function (err) {
|
||||
return logger.error('count note failed: ' + err)
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: test it
|
||||
|
|
|
@ -14,9 +14,10 @@ const config = require('./config')
|
|||
const logger = require('./logger')
|
||||
const models = require('./models')
|
||||
const utils = require('./utils')
|
||||
const history = require('./history')
|
||||
const history = require('./web/history')
|
||||
|
||||
// public
|
||||
exports.responseError = responseError
|
||||
exports.errorForbidden = errorForbidden
|
||||
exports.errorNotFound = errorNotFound
|
||||
exports.errorBadRequest = errorBadRequest
|
||||
|
@ -33,6 +34,7 @@ exports.publishNoteActions = publishNoteActions
|
|||
exports.publishSlideActions = publishSlideActions
|
||||
exports.githubActions = githubActions
|
||||
exports.gitlabActions = gitlabActions
|
||||
exports.checkViewPermission = checkViewPermission
|
||||
|
||||
function errorForbidden (res) {
|
||||
const { req } = res
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const Router = require('express').Router
|
||||
|
||||
const response = require('../response')
|
||||
|
||||
const baseRouter = module.exports = Router()
|
||||
|
||||
// get index
|
||||
baseRouter.get('/', response.showIndex)
|
||||
// get 403 forbidden
|
||||
baseRouter.get('/403', function (req, res) {
|
||||
response.errorForbidden(res)
|
||||
})
|
||||
// get 404 not found
|
||||
baseRouter.get('/404', function (req, res) {
|
||||
response.errorNotFound(res)
|
||||
})
|
||||
// get 500 internal error
|
||||
baseRouter.get('/500', function (req, res) {
|
||||
response.errorInternalError(res)
|
||||
})
|
|
@ -0,0 +1,21 @@
|
|||
'use strict'
|
||||
|
||||
const config = require('../../config')
|
||||
const { responseError } = require('../../response')
|
||||
|
||||
exports.errorForbidden = (req, res) => {
|
||||
if (req.user) {
|
||||
return responseError(res, '403', 'Forbidden', 'oh no.')
|
||||
}
|
||||
|
||||
req.flash('error', 'You are not allowed to access this page. Maybe try logging in?')
|
||||
res.redirect(config.serverURL + '/')
|
||||
}
|
||||
|
||||
exports.errorNotFound = (req, res) => {
|
||||
responseError(res, '404', 'Not Found', 'oops.')
|
||||
}
|
||||
|
||||
exports.errorInternalError = (req, res) => {
|
||||
responseError(res, '500', 'Internal Error', 'wtf.')
|
||||
}
|
|
@ -4,10 +4,10 @@
|
|||
var LZString = require('@hackmd/lz-string')
|
||||
|
||||
// core
|
||||
var config = require('./config')
|
||||
var logger = require('./logger')
|
||||
var response = require('./response')
|
||||
var models = require('./models')
|
||||
var config = require('../../config')
|
||||
var logger = require('../../logger')
|
||||
var response = require('../../response')
|
||||
var models = require('../../models')
|
||||
|
||||
function getHistory (userid, callback) {
|
||||
models.User.findOne({
|
|
@ -1,18 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const Router = require('express').Router
|
||||
|
||||
const { urlencodedParser } = require('./utils')
|
||||
const history = require('../history')
|
||||
const historyRouter = module.exports = Router()
|
||||
|
||||
// get history
|
||||
historyRouter.get('/history', history.historyGet)
|
||||
// post history
|
||||
historyRouter.post('/history', urlencodedParser, history.historyPost)
|
||||
// post history by note id
|
||||
historyRouter.post('/history/:noteId', urlencodedParser, history.historyPost)
|
||||
// delete history
|
||||
historyRouter.delete('/history', history.historyDelete)
|
||||
// delete history by note id
|
||||
historyRouter.delete('/history/:noteId', history.historyDelete)
|
|
@ -0,0 +1,38 @@
|
|||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const config = require('../../config')
|
||||
const { User } = require('../../models')
|
||||
const logger = require('../../logger')
|
||||
|
||||
exports.showIndex = async (req, res) => {
|
||||
const isLogin = req.isAuthenticated()
|
||||
const deleteToken = ''
|
||||
|
||||
const data = {
|
||||
signin: isLogin,
|
||||
infoMessage: req.flash('info'),
|
||||
errorMessage: req.flash('error'),
|
||||
privacyStatement: fs.existsSync(path.join(config.docsPath, 'privacy.md')),
|
||||
termsOfUse: fs.existsSync(path.join(config.docsPath, 'terms-of-use.md')),
|
||||
deleteToken: deleteToken
|
||||
}
|
||||
|
||||
if (!isLogin) {
|
||||
return res.render('index.ejs', data)
|
||||
}
|
||||
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
})
|
||||
if (user) {
|
||||
data.deleteToken = user.deleteToken
|
||||
return res.render('index.ejs', data)
|
||||
}
|
||||
|
||||
logger.error(`error: user not found with id ${req.user.id}`)
|
||||
return res.render('index.ejs', data)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const Router = require('express').Router
|
||||
|
||||
const response = require('../response')
|
||||
|
||||
const { markdownParser } = require('./utils')
|
||||
|
||||
const noteRouter = module.exports = Router()
|
||||
|
||||
// get new note
|
||||
noteRouter.get('/new', response.newNote)
|
||||
// post new note with content
|
||||
noteRouter.post('/new', markdownParser, response.newNote)
|
||||
// get publish note
|
||||
noteRouter.get('/s/:shortid', response.showPublishNote)
|
||||
// publish note actions
|
||||
noteRouter.get('/s/:shortid/:action', response.publishNoteActions)
|
||||
// get publish slide
|
||||
noteRouter.get('/p/:shortid', response.showPublishSlide)
|
||||
// publish slide actions
|
||||
noteRouter.get('/p/:shortid/:action', response.publishSlideActions)
|
||||
// get note by id
|
||||
noteRouter.get('/:noteId', response.showNote)
|
||||
// note actions
|
||||
noteRouter.get('/:noteId/:action', response.noteActions)
|
||||
// note actions with action id
|
||||
noteRouter.get('/:noteId/:action/:actionId', response.noteActions)
|
|
@ -0,0 +1,80 @@
|
|||
'use strict'
|
||||
|
||||
const { Router } = require('express')
|
||||
|
||||
const { wrap, urlencodedParser, markdownParser } = require('./utils')
|
||||
|
||||
// load controller
|
||||
const indexController = require('./homepage')
|
||||
const errorPageController = require('./errorPage')
|
||||
const statusController = require('./status')
|
||||
const historyController = require('./history')
|
||||
const userController = require('./user')
|
||||
const response = require('../response')
|
||||
const appRouter = Router()
|
||||
|
||||
// register route
|
||||
|
||||
// get index
|
||||
appRouter.get('/', wrap(indexController.showIndex))
|
||||
|
||||
// ----- error page -----
|
||||
// get 403 forbidden
|
||||
appRouter.get('/403', errorPageController.errorForbidden)
|
||||
// get 404 not found
|
||||
appRouter.get('/404', errorPageController.errorNotFound)
|
||||
// get 500 internal error
|
||||
appRouter.get('/500', errorPageController.errorInternalError)
|
||||
|
||||
appRouter.get('/status', wrap(statusController.getStatus))
|
||||
appRouter.get('/config', statusController.getConfig)
|
||||
|
||||
// register auth module
|
||||
appRouter.use(require('./auth'))
|
||||
|
||||
// get history
|
||||
appRouter.get('/history', historyController.historyGet)
|
||||
// post history
|
||||
appRouter.post('/history', urlencodedParser, historyController.historyPost)
|
||||
// post history by note id
|
||||
appRouter.post('/history/:noteId', urlencodedParser, historyController.historyPost)
|
||||
// delete history
|
||||
appRouter.delete('/history', historyController.historyDelete)
|
||||
// delete history by note id
|
||||
appRouter.delete('/history/:noteId', historyController.historyDelete)
|
||||
|
||||
// user
|
||||
// get me info
|
||||
appRouter.get('/me', wrap(userController.getMe))
|
||||
|
||||
// delete the currently authenticated user
|
||||
appRouter.get('/me/delete/:token?', wrap(userController.deleteUser))
|
||||
|
||||
// export the data of the authenticated user
|
||||
appRouter.get('/me/export', userController.exportMyData)
|
||||
|
||||
appRouter.get('/user/:username/avatar.svg', userController.getMyAvatar)
|
||||
|
||||
// register image upload module
|
||||
appRouter.use(require('./imageRouter'))
|
||||
|
||||
// get new note
|
||||
appRouter.get('/new', response.newNote)
|
||||
// post new note with content
|
||||
appRouter.post('/new', markdownParser, response.newNote)
|
||||
// get publish note
|
||||
appRouter.get('/s/:shortid', response.showPublishNote)
|
||||
// publish note actions
|
||||
appRouter.get('/s/:shortid/:action', response.publishNoteActions)
|
||||
// get publish slide
|
||||
appRouter.get('/p/:shortid', response.showPublishSlide)
|
||||
// publish slide actions
|
||||
appRouter.get('/p/:shortid/:action', response.publishSlideActions)
|
||||
// get note by id
|
||||
appRouter.get('/:noteId', response.showNote)
|
||||
// note actions
|
||||
appRouter.get('/:noteId/:action', response.noteActions)
|
||||
// note actions with action id
|
||||
appRouter.get('/:noteId/:action/:actionId', response.noteActions)
|
||||
|
||||
exports.router = appRouter
|
|
@ -0,0 +1,35 @@
|
|||
'use strict'
|
||||
|
||||
const realtime = require('../../realtime')
|
||||
const config = require('../../config')
|
||||
|
||||
exports.getStatus = async (req, res) => {
|
||||
const data = await realtime.getStatus()
|
||||
|
||||
res.set({
|
||||
'Cache-Control': 'private', // only cache by client
|
||||
'X-Robots-Tag': 'noindex, nofollow', // prevent crawling
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
res.send(data)
|
||||
}
|
||||
|
||||
exports.getConfig = (req, res) => {
|
||||
const data = {
|
||||
domain: config.domain,
|
||||
urlpath: config.urlPath,
|
||||
debug: config.debug,
|
||||
version: config.fullversion,
|
||||
plantumlServer: config.plantuml.server,
|
||||
DROPBOX_APP_KEY: config.dropbox.appKey,
|
||||
allowedUploadMimeTypes: config.allowedUploadMimeTypes,
|
||||
defaultUseHardbreak: config.defaultUseHardbreak,
|
||||
linkifyHeaderStyle: config.linkifyHeaderStyle
|
||||
}
|
||||
res.set({
|
||||
'Cache-Control': 'private', // only cache by client
|
||||
'X-Robots-Tag': 'noindex, nofollow', // prevent crawling
|
||||
'Content-Type': 'application/javascript'
|
||||
})
|
||||
res.render('../js/lib/common/constant.ejs', data)
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const Router = require('express').Router
|
||||
|
||||
const response = require('../response')
|
||||
const realtime = require('../realtime')
|
||||
const config = require('../config')
|
||||
const models = require('../models')
|
||||
const logger = require('../logger')
|
||||
|
||||
const { urlencodedParser } = require('./utils')
|
||||
|
||||
const statusRouter = module.exports = Router()
|
||||
|
||||
// get status
|
||||
statusRouter.get('/status', function (req, res, next) {
|
||||
realtime.getStatus(function (data) {
|
||||
res.set({
|
||||
'Cache-Control': 'private', // only cache by client
|
||||
'X-Robots-Tag': 'noindex, nofollow', // prevent crawling
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
res.send(data)
|
||||
})
|
||||
})
|
||||
|
||||
statusRouter.get('/config', function (req, res) {
|
||||
var data = {
|
||||
domain: config.domain,
|
||||
urlpath: config.urlPath,
|
||||
debug: config.debug,
|
||||
version: config.fullversion,
|
||||
plantumlServer: config.plantuml.server,
|
||||
DROPBOX_APP_KEY: config.dropbox.appKey,
|
||||
allowedUploadMimeTypes: config.allowedUploadMimeTypes,
|
||||
defaultUseHardbreak: config.defaultUseHardbreak,
|
||||
linkifyHeaderStyle: config.linkifyHeaderStyle
|
||||
}
|
||||
res.set({
|
||||
'Cache-Control': 'private', // only cache by client
|
||||
'X-Robots-Tag': 'noindex, nofollow', // prevent crawling
|
||||
'Content-Type': 'application/javascript'
|
||||
})
|
||||
res.render('../js/lib/common/constant.ejs', data)
|
||||
})
|
|
@ -0,0 +1,121 @@
|
|||
'use strict'
|
||||
|
||||
const archiver = require('archiver')
|
||||
const async = require('async')
|
||||
|
||||
const response = require('../../response')
|
||||
const config = require('../../config')
|
||||
const models = require('../../models')
|
||||
const logger = require('../../logger')
|
||||
const { generateAvatar } = require('../../letter-avatars')
|
||||
|
||||
exports.getMe = async (req, res) => {
|
||||
if (!req.isAuthenticated()) {
|
||||
res.status(401).send({
|
||||
status: 'forbidden'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await models.User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
})
|
||||
|
||||
if (!user) {
|
||||
return response.errorNotFound(res)
|
||||
}
|
||||
const profile = models.User.getProfile(user)
|
||||
|
||||
res.send({
|
||||
status: 'ok',
|
||||
id: req.user.id,
|
||||
name: profile.name,
|
||||
photo: profile.photo
|
||||
})
|
||||
}
|
||||
|
||||
exports.deleteUser = async (req, res) => {
|
||||
if (!req.isAuthenticated()) {
|
||||
return response.errorForbidden(res)
|
||||
}
|
||||
|
||||
const user = await models.User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
})
|
||||
|
||||
if (!user) {
|
||||
return response.errorNotFound(res)
|
||||
}
|
||||
|
||||
if (user.deleteToken !== req.params.token) {
|
||||
return response.errorForbidden(res)
|
||||
}
|
||||
|
||||
await user.destroy()
|
||||
return res.redirect(config.serverURL + '/')
|
||||
}
|
||||
|
||||
exports.exportMyData = (req, res) => {
|
||||
if (!req.isAuthenticated()) {
|
||||
return response.errorForbidden(res)
|
||||
}
|
||||
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 3 } // Sets the compression level.
|
||||
})
|
||||
|
||||
res.setHeader('Content-Type', 'application/zip')
|
||||
res.attachment('archive.zip')
|
||||
archive.pipe(res)
|
||||
archive.on('error', function (err) {
|
||||
logger.error('export user data failed: ' + err)
|
||||
return response.errorInternalError(res)
|
||||
})
|
||||
|
||||
models.User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
}).then(function (user) {
|
||||
models.Note.findAll({
|
||||
where: {
|
||||
ownerId: user.id
|
||||
}
|
||||
}).then(function (notes) {
|
||||
const filenames = {}
|
||||
async.each(notes, function (note, callback) {
|
||||
const basename = note.title.replace(/\//g, '-') // Prevent subdirectories
|
||||
let filename
|
||||
let suffix = 0
|
||||
do {
|
||||
const separator = suffix === 0 ? '' : '-'
|
||||
filename = basename + separator + suffix + '.md'
|
||||
suffix++
|
||||
} while (filenames[filename])
|
||||
filenames[filename] = true
|
||||
|
||||
logger.debug('Write: ' + filename)
|
||||
archive.append(Buffer.from(note.content), { name: filename, date: note.lastchangeAt })
|
||||
callback(null, null)
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return response.errorInternalError(res)
|
||||
}
|
||||
|
||||
archive.finalize()
|
||||
})
|
||||
})
|
||||
}).catch(function (err) {
|
||||
logger.error('export user data failed: ' + err)
|
||||
return response.errorInternalError(res)
|
||||
})
|
||||
}
|
||||
|
||||
exports.getMyAvatar = (req, res) => {
|
||||
res.setHeader('Content-Type', 'image/svg+xml')
|
||||
res.setHeader('Cache-Control', 'public, max-age=86400')
|
||||
res.send(generateAvatar(req.params.username))
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const archiver = require('archiver')
|
||||
const async = require('async')
|
||||
const Router = require('express').Router
|
||||
|
||||
const response = require('../response')
|
||||
const config = require('../config')
|
||||
const models = require('../models')
|
||||
const logger = require('../logger')
|
||||
const { generateAvatar } = require('../letter-avatars')
|
||||
|
||||
const UserRouter = module.exports = Router()
|
||||
|
||||
// get me info
|
||||
UserRouter.get('/me', function (req, res) {
|
||||
if (req.isAuthenticated()) {
|
||||
models.User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
}).then(function (user) {
|
||||
if (!user) { return response.errorNotFound(res) }
|
||||
var profile = models.User.getProfile(user)
|
||||
res.send({
|
||||
status: 'ok',
|
||||
id: req.user.id,
|
||||
name: profile.name,
|
||||
photo: profile.photo
|
||||
})
|
||||
}).catch(function (err) {
|
||||
logger.error('read me failed: ' + err)
|
||||
return response.errorInternalError(res)
|
||||
})
|
||||
} else {
|
||||
res.status(401).send({
|
||||
status: 'forbidden'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// delete the currently authenticated user
|
||||
UserRouter.get('/me/delete/:token?', function (req, res) {
|
||||
if (req.isAuthenticated()) {
|
||||
models.User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
}).then(function (user) {
|
||||
if (!user) {
|
||||
return response.errorNotFound(res)
|
||||
}
|
||||
if (user.deleteToken === req.params.token) {
|
||||
user.destroy().then(function () {
|
||||
res.redirect(config.serverURL + '/')
|
||||
})
|
||||
} else {
|
||||
return response.errorForbidden(res)
|
||||
}
|
||||
}).catch(function (err) {
|
||||
logger.error('delete user failed: ' + err)
|
||||
return response.errorInternalError(res)
|
||||
})
|
||||
} else {
|
||||
return response.errorForbidden(res)
|
||||
}
|
||||
})
|
||||
|
||||
// export the data of the authenticated user
|
||||
UserRouter.get('/me/export', function (req, res) {
|
||||
if (req.isAuthenticated()) {
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 3 } // Sets the compression level.
|
||||
})
|
||||
res.setHeader('Content-Type', 'application/zip')
|
||||
res.attachment('archive.zip')
|
||||
archive.pipe(res)
|
||||
archive.on('error', function (err) {
|
||||
logger.error('export user data failed: ' + err)
|
||||
return response.errorInternalError(res)
|
||||
})
|
||||
models.User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
}).then(function (user) {
|
||||
models.Note.findAll({
|
||||
where: {
|
||||
ownerId: user.id
|
||||
}
|
||||
}).then(function (notes) {
|
||||
const filenames = {}
|
||||
async.each(notes, function (note, callback) {
|
||||
const basename = note.title.replace(/\//g, '-') // Prevent subdirectories
|
||||
let filename
|
||||
let suffix = 0
|
||||
do {
|
||||
const separator = suffix === 0 ? '' : '-'
|
||||
filename = basename + separator + suffix + '.md'
|
||||
suffix++
|
||||
} while (filenames[filename])
|
||||
filenames[filename] = true
|
||||
|
||||
logger.debug('Write: ' + filename)
|
||||
archive.append(Buffer.from(note.content), { name: filename, date: note.lastchangeAt })
|
||||
callback(null, null)
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return response.errorInternalError(res)
|
||||
}
|
||||
|
||||
archive.finalize()
|
||||
})
|
||||
})
|
||||
}).catch(function (err) {
|
||||
logger.error('export user data failed: ' + err)
|
||||
return response.errorInternalError(res)
|
||||
})
|
||||
} else {
|
||||
return response.errorForbidden(res)
|
||||
}
|
||||
})
|
||||
|
||||
UserRouter.get('/user/:username/avatar.svg', function (req, res, next) {
|
||||
res.setHeader('Content-Type', 'image/svg+xml')
|
||||
res.setHeader('Cache-Control', 'public, max-age=86400')
|
||||
res.send(generateAvatar(req.params.username))
|
||||
})
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
const bodyParser = require('body-parser')
|
||||
|
||||
exports.wrap = innerHandler => (req, res, next) => innerHandler(req, res).catch(err => next(err))
|
||||
|
||||
// create application/x-www-form-urlencoded parser
|
||||
exports.urlencodedParser = bodyParser.urlencoded({
|
||||
extended: false,
|
||||
|
|
Loading…
Reference in New Issue