2020-01-04 22:58:40 +00:00
|
|
|
'use strict'
|
|
|
|
|
|
|
|
const config = require('../config')
|
2020-01-04 23:38:19 +00:00
|
|
|
const logger = require('../logger')
|
|
|
|
|
2020-01-04 23:17:55 +00:00
|
|
|
const { Note, User } = require('../models')
|
2020-01-04 22:58:40 +00:00
|
|
|
|
|
|
|
const { newCheckViewPermission, errorForbidden, responseCodiMD, errorNotFound } = require('../response')
|
|
|
|
const { updateHistory } = require('../history')
|
2019-08-25 03:02:15 +00:00
|
|
|
const { actionPublish, actionSlide, actionInfo, actionDownload, actionPDF, actionGist, actionRevision, actionPandoc } = require('./noteActions')
|
2020-01-04 22:58:40 +00:00
|
|
|
|
2020-01-04 23:17:55 +00:00
|
|
|
async function getNoteById (noteId, { includeUser } = { includeUser: false }) {
|
2020-01-04 22:58:40 +00:00
|
|
|
const id = await Note.parseNoteIdAsync(noteId)
|
2020-01-04 23:17:55 +00:00
|
|
|
|
|
|
|
const includes = []
|
|
|
|
|
|
|
|
if (includeUser) {
|
|
|
|
includes.push({
|
|
|
|
model: User,
|
|
|
|
as: 'owner'
|
|
|
|
}, {
|
|
|
|
model: User,
|
|
|
|
as: 'lastchangeuser'
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-01-04 22:58:40 +00:00
|
|
|
const note = await Note.findOne({
|
|
|
|
where: {
|
|
|
|
id: id
|
2020-01-04 23:17:55 +00:00
|
|
|
},
|
|
|
|
include: includes
|
2020-01-04 22:58:40 +00:00
|
|
|
})
|
|
|
|
return note
|
|
|
|
}
|
|
|
|
|
|
|
|
async function createNote (userId, noteAlias) {
|
|
|
|
if (!config.allowAnonymous && !!userId) {
|
|
|
|
throw new Error('can not create note')
|
|
|
|
}
|
|
|
|
|
|
|
|
const note = await Note.create({
|
|
|
|
ownerId: userId,
|
2020-01-04 23:17:55 +00:00
|
|
|
alias: noteAlias
|
2020-01-04 22:58:40 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
if (userId) {
|
|
|
|
updateHistory(userId, note)
|
|
|
|
}
|
|
|
|
|
|
|
|
return note
|
|
|
|
}
|
|
|
|
|
|
|
|
// controller
|
|
|
|
async function showNote (req, res) {
|
|
|
|
const noteId = req.params.noteId
|
|
|
|
const userId = req.user ? req.user.id : null
|
|
|
|
|
|
|
|
let note = await getNoteById(noteId)
|
|
|
|
|
|
|
|
if (!note) {
|
|
|
|
// if allow free url enable, auto create note
|
|
|
|
if (!config.allowFreeURL || config.forbiddenNoteIDs.includes(noteId)) {
|
2020-02-26 03:20:42 +00:00
|
|
|
return errorNotFound(req, res)
|
2020-01-04 22:58:40 +00:00
|
|
|
}
|
|
|
|
note = await createNote(userId, noteId)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!newCheckViewPermission(note, req.isAuthenticated(), userId)) {
|
2020-02-26 03:13:45 +00:00
|
|
|
return errorForbidden(req, res)
|
2020-01-04 22:58:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// force to use note id
|
|
|
|
const id = Note.encodeNoteId(note.id)
|
|
|
|
if ((note.alias && noteId !== note.alias) || (!note.alias && noteId !== id)) {
|
|
|
|
return res.redirect(config.serverURL + '/' + (note.alias || id))
|
|
|
|
}
|
|
|
|
return responseCodiMD(res, note)
|
|
|
|
}
|
|
|
|
|
2020-02-07 02:55:50 +00:00
|
|
|
function canViewNote (note, isLogin, userId) {
|
|
|
|
if (note.permission === 'private') {
|
|
|
|
return note.ownerId === userId
|
|
|
|
}
|
|
|
|
if (note.permission === 'limited' || note.permission === 'protected') {
|
|
|
|
return isLogin
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2020-01-04 23:17:55 +00:00
|
|
|
async function showPublishNote (req, res) {
|
|
|
|
const shortid = req.params.shortid
|
|
|
|
|
|
|
|
const note = await getNoteById(shortid, {
|
|
|
|
includeUser: true
|
|
|
|
})
|
|
|
|
|
|
|
|
if (!note) {
|
2020-02-26 03:20:42 +00:00
|
|
|
return errorNotFound(req, res)
|
2020-01-04 23:17:55 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 02:23:46 +00:00
|
|
|
if (!canViewNote(note, req.isAuthenticated(), req.user ? req.user.id : null)) {
|
2020-02-26 03:13:45 +00:00
|
|
|
return errorForbidden(req, res)
|
2020-02-26 02:23:46 +00:00
|
|
|
}
|
|
|
|
|
2020-01-04 23:17:55 +00:00
|
|
|
if ((note.alias && shortid !== note.alias) || (!note.alias && shortid !== note.shortid)) {
|
|
|
|
return res.redirect(config.serverURL + '/s/' + (note.alias || note.shortid))
|
|
|
|
}
|
|
|
|
|
|
|
|
await note.increment('viewcount')
|
|
|
|
|
|
|
|
const body = note.content
|
|
|
|
const extracted = Note.extractMeta(body)
|
|
|
|
const markdown = extracted.markdown
|
|
|
|
const meta = Note.parseMeta(extracted.meta)
|
|
|
|
const createTime = note.createdAt
|
|
|
|
const updateTime = note.lastchangeAt
|
|
|
|
const title = Note.generateWebTitle(meta.title || Note.decodeTitle(note.title))
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
title: title,
|
|
|
|
description: meta.description || (markdown ? Note.generateDescription(markdown) : null),
|
|
|
|
viewcount: note.viewcount,
|
|
|
|
createtime: createTime,
|
|
|
|
updatetime: updateTime,
|
|
|
|
body: body,
|
|
|
|
owner: note.owner ? note.owner.id : null,
|
|
|
|
ownerprofile: note.owner ? User.getProfile(note.owner) : null,
|
|
|
|
lastchangeuser: note.lastchangeuser ? note.lastchangeuser.id : null,
|
|
|
|
lastchangeuserprofile: note.lastchangeuser ? User.getProfile(note.lastchangeuser) : null,
|
|
|
|
robots: meta.robots || false, // default allow robots
|
|
|
|
GA: meta.GA,
|
|
|
|
disqus: meta.disqus,
|
|
|
|
cspNonce: res.locals.nonce
|
|
|
|
}
|
|
|
|
|
|
|
|
res.set({
|
|
|
|
'Cache-Control': 'private' // only cache by client
|
|
|
|
})
|
|
|
|
|
|
|
|
res.render('pretty.ejs', data)
|
|
|
|
}
|
|
|
|
|
2020-01-04 23:38:19 +00:00
|
|
|
async function noteActions (req, res) {
|
|
|
|
const noteId = req.params.noteId
|
|
|
|
|
|
|
|
const note = await getNoteById(noteId)
|
2020-02-07 02:55:50 +00:00
|
|
|
|
2020-01-04 23:38:19 +00:00
|
|
|
if (!note) {
|
2020-02-26 03:20:42 +00:00
|
|
|
return errorNotFound(req, res)
|
2020-01-04 23:38:19 +00:00
|
|
|
}
|
|
|
|
|
2020-02-07 02:55:50 +00:00
|
|
|
if (!canViewNote(note, req.isAuthenticated(), req.user ? req.user.id : null)) {
|
2020-02-26 03:13:45 +00:00
|
|
|
return errorForbidden(req, res)
|
2020-02-07 02:55:50 +00:00
|
|
|
}
|
|
|
|
|
2020-01-04 23:38:19 +00:00
|
|
|
const action = req.params.action
|
|
|
|
switch (action) {
|
|
|
|
case 'publish':
|
|
|
|
case 'pretty': // pretty deprecated
|
|
|
|
return actionPublish(req, res, note)
|
|
|
|
case 'slide':
|
|
|
|
return actionSlide(req, res, note)
|
|
|
|
case 'download':
|
|
|
|
actionDownload(req, res, note)
|
|
|
|
break
|
|
|
|
case 'info':
|
|
|
|
actionInfo(req, res, note)
|
|
|
|
break
|
|
|
|
case 'pdf':
|
|
|
|
if (config.allowPDFExport) {
|
|
|
|
actionPDF(req, res, note)
|
|
|
|
} else {
|
|
|
|
logger.error('PDF export failed: Disabled by config. Set "allowPDFExport: true" to enable. Check the documentation for details')
|
2020-02-26 03:13:45 +00:00
|
|
|
errorForbidden(req, res)
|
2020-01-04 23:38:19 +00:00
|
|
|
}
|
|
|
|
break
|
|
|
|
case 'gist':
|
|
|
|
actionGist(req, res, note)
|
|
|
|
break
|
|
|
|
case 'revision':
|
|
|
|
actionRevision(req, res, note)
|
|
|
|
break
|
2019-08-25 03:02:15 +00:00
|
|
|
case 'pandoc':
|
|
|
|
actionPandoc(req, res, note)
|
|
|
|
break
|
2020-01-04 23:38:19 +00:00
|
|
|
default:
|
|
|
|
return res.redirect(config.serverURL + '/' + noteId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-04 22:58:40 +00:00
|
|
|
exports.showNote = showNote
|
2020-01-04 23:17:55 +00:00
|
|
|
exports.showPublishNote = showPublishNote
|
2020-01-04 23:38:19 +00:00
|
|
|
exports.noteActions = noteActions
|