'use strict' // response // external modules const fs = require('fs') const path = require('path') const fetch = require('node-fetch') // core const config = require('./config') const logger = require('./logger') const models = require('./models') const noteUtil = require('./web/note/util') const errors = require('./errors') // public const response = { showIndex: showIndex, githubActions: githubActions, gitlabActions: gitlabActions } function showIndex (req, res, next) { const authStatus = req.isAuthenticated() const deleteToken = '' const data = { signin: authStatus, infoMessage: req.flash('info'), errorMessage: req.flash('error'), imprint: fs.existsSync(path.join(config.docsPath, 'imprint.md')), privacyStatement: fs.existsSync(path.join(config.docsPath, 'privacy.md')), termsOfUse: fs.existsSync(path.join(config.docsPath, 'terms-of-use.md')), deleteToken: deleteToken } if (authStatus) { models.User.findOne({ where: { id: req.user.id } }).then(function (user) { if (user) { data.deleteToken = user.deleteToken res.render('index.ejs', data) } }) } else { res.render('index.ejs', data) } } function githubActions (req, res, next) { const noteId = req.params.noteId noteUtil.findNote(req, res, function (note) { const action = req.params.action switch (action) { case 'gist': githubActionGist(req, res, note) break default: res.redirect(config.serverURL + '/' + noteId) break } }) } function githubActionGist (req, res, note) { const code = req.query.code const state = req.query.state if (!code || !state) { return errors.errorForbidden(res) } else { const data = { client_id: config.github.clientID, client_secret: config.github.clientSecret, code: code, state: state } const authUrl = 'https://github.com/login/oauth/access_token' fetch(authUrl, { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json', Accept: 'application/json' } }).then(resp => { if (!resp.ok) { throw new Error('forbidden') } return resp.json() }).then(body => { const accessToken = body.access_token if (!accessToken) { throw new Error('forbidden') } const content = note.content const title = models.Note.decodeTitle(note.title) const filename = title.replace('/', ' ') + '.md' const gist = { files: {} } gist.files[filename] = { content: content } const gistUrl = 'https://api.github.com/gists' return fetch(gistUrl, { method: 'POST', body: JSON.stringify(gist), headers: { 'User-Agent': 'HedgeDoc', Authorization: 'token ' + accessToken, 'Content-Type': 'application/json', Accept: 'application/json' } }) }).then(resp => { if (resp.status !== 201) { throw new Error('forbidden') } return resp.json() }).then(body => { res.setHeader('referer', '') res.redirect(body.html_url) }).catch(error => { if (error.message === 'forbidden') { return errors.errorForbidden(res) } logger.error('GitHub Gist auth failed: ' + error) return errors.errorInternalError(res) }) } } function gitlabActions (req, res, next) { const noteId = req.params.noteId noteUtil.findNote(req, res, function (note) { const action = req.params.action switch (action) { case 'projects': gitlabActionProjects(req, res, note) break default: res.redirect(config.serverURL + '/' + noteId) break } }) } function gitlabActionProjects (req, res, note) { if (req.isAuthenticated()) { models.User.findOne({ where: { id: req.user.id } }).then(function (user) { if (!user) { return errors.errorNotFound(res) } const ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version } ret.accesstoken = user.accessToken ret.profileid = user.profileid const apiUrl = `${config.gitlab.baseURL}/api/${config.gitlab.version}/projects?membership=yes&per_page=100&access_token=${user.accessToken}` fetch(apiUrl).then(resp => { if (!resp.ok) { res.send(ret) throw new Error('HTTP request returned not okay-ish status') } return resp.json() }).then(body => { ret.projects = body return res.send(ret) }) }).catch(function (err) { logger.error('gitlab action projects failed: ' + err) return errors.errorInternalError(res) }) } else { return errors.errorForbidden(res) } } module.exports = response