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.enableGitHubGist = config.isGitHubEnable
|
||||||
app.locals.enableGitlabSnippets = config.isGitlabSnippetsEnable
|
app.locals.enableGitlabSnippets = config.isGitlabSnippetsEnable
|
||||||
|
|
||||||
app.use(require('./lib/web/baseRouter'))
|
app.use(require('./lib/web/routes').router)
|
||||||
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'))
|
|
||||||
|
|
||||||
// response not found if no any route matxches
|
// response not found if no any route matxches
|
||||||
app.get('*', function (req, res) {
|
app.get('*', function (req, res) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ const get = require('lodash/get')
|
||||||
// core
|
// core
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
const history = require('./history')
|
const history = require('./web/history')
|
||||||
const models = require('./models')
|
const models = require('./models')
|
||||||
|
|
||||||
// ot
|
// ot
|
||||||
|
@ -247,8 +247,9 @@ async function _updateNoteAsync (note) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test it
|
// TODO: test it
|
||||||
function getStatus (callback) {
|
function getStatus () {
|
||||||
models.Note.count().then(function (notecount) {
|
return models.Note.count()
|
||||||
|
.then(function (notecount) {
|
||||||
var distinctaddresses = []
|
var distinctaddresses = []
|
||||||
var regaddresses = []
|
var regaddresses = []
|
||||||
var distinctregaddresses = []
|
var distinctregaddresses = []
|
||||||
|
@ -279,9 +280,10 @@ function getStatus (callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
models.User.count().then(function (regcount) {
|
|
||||||
// eslint-disable-next-line standard/no-callback-literal
|
return models.User.count()
|
||||||
return callback ? callback({
|
.then(function (regcount) {
|
||||||
|
return {
|
||||||
onlineNotes: Object.keys(notes).length,
|
onlineNotes: Object.keys(notes).length,
|
||||||
onlineUsers: Object.keys(users).length,
|
onlineUsers: Object.keys(users).length,
|
||||||
distinctOnlineUsers: distinctaddresses.length,
|
distinctOnlineUsers: distinctaddresses.length,
|
||||||
|
@ -293,8 +295,9 @@ function getStatus (callback) {
|
||||||
connectionSocketQueueLength: connectProcessQueue.queue.length,
|
connectionSocketQueueLength: connectProcessQueue.queue.length,
|
||||||
isDisconnectBusy: disconnectProcessQueue.lock,
|
isDisconnectBusy: disconnectProcessQueue.lock,
|
||||||
disconnectSocketQueueLength: disconnectProcessQueue.queue.length
|
disconnectSocketQueueLength: disconnectProcessQueue.queue.length
|
||||||
}) : null
|
}
|
||||||
}).catch(function (err) {
|
})
|
||||||
|
.catch(function (err) {
|
||||||
return logger.error('count user failed: ' + err)
|
return logger.error('count user failed: ' + err)
|
||||||
})
|
})
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
|
|
|
@ -14,9 +14,10 @@ const config = require('./config')
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
const models = require('./models')
|
const models = require('./models')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
const history = require('./history')
|
const history = require('./web/history')
|
||||||
|
|
||||||
// public
|
// public
|
||||||
|
exports.responseError = responseError
|
||||||
exports.errorForbidden = errorForbidden
|
exports.errorForbidden = errorForbidden
|
||||||
exports.errorNotFound = errorNotFound
|
exports.errorNotFound = errorNotFound
|
||||||
exports.errorBadRequest = errorBadRequest
|
exports.errorBadRequest = errorBadRequest
|
||||||
|
@ -33,6 +34,7 @@ exports.publishNoteActions = publishNoteActions
|
||||||
exports.publishSlideActions = publishSlideActions
|
exports.publishSlideActions = publishSlideActions
|
||||||
exports.githubActions = githubActions
|
exports.githubActions = githubActions
|
||||||
exports.gitlabActions = gitlabActions
|
exports.gitlabActions = gitlabActions
|
||||||
|
exports.checkViewPermission = checkViewPermission
|
||||||
|
|
||||||
function errorForbidden (res) {
|
function errorForbidden (res) {
|
||||||
const { req } = 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')
|
var LZString = require('@hackmd/lz-string')
|
||||||
|
|
||||||
// core
|
// core
|
||||||
var config = require('./config')
|
var config = require('../../config')
|
||||||
var logger = require('./logger')
|
var logger = require('../../logger')
|
||||||
var response = require('./response')
|
var response = require('../../response')
|
||||||
var models = require('./models')
|
var models = require('../../models')
|
||||||
|
|
||||||
function getHistory (userid, callback) {
|
function getHistory (userid, callback) {
|
||||||
models.User.findOne({
|
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')
|
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
|
// create application/x-www-form-urlencoded parser
|
||||||
exports.urlencodedParser = bodyParser.urlencoded({
|
exports.urlencodedParser = bodyParser.urlencoded({
|
||||||
extended: false,
|
extended: false,
|
||||||
|
|
Loading…
Reference in New Issue