You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
7.9 KiB

8 years ago
  1. 'use strict'
  2. /* global db, lang, rights, winston */
  3. var express = require('express')
  4. var router = express.Router()
  5. const Promise = require('bluebird')
  6. const validator = require('validator')
  7. const _ = require('lodash')
  8. const axios = require('axios')
  9. const path = require('path')
  10. const fs = Promise.promisifyAll(require('fs-extra'))
  11. /**
  12. * Admin
  13. */
  14. router.get('/', (req, res) => {
  15. res.redirect('/admin/profile')
  16. })
  17. router.get('/profile', (req, res) => {
  18. if (res.locals.isGuest) {
  19. return res.render('error-forbidden')
  20. }
  21. res.render('pages/admin/profile', { adminTab: 'profile' })
  22. })
  23. router.post('/profile', (req, res) => {
  24. if (res.locals.isGuest) {
  25. return res.render('error-forbidden')
  26. }
  27. return db.User.findById(req.user.id).then((usr) => {
  28. usr.name = _.trim(req.body.name)
  29. if (usr.provider === 'local' && req.body.password !== '********') {
  30. let nPwd = _.trim(req.body.password)
  31. if (nPwd.length < 6) {
  32. return Promise.reject(new Error('New Password too short!'))
  33. } else {
  34. return db.User.hashPassword(nPwd).then((pwd) => {
  35. usr.password = pwd
  36. return usr.save()
  37. })
  38. }
  39. } else {
  40. return usr.save()
  41. }
  42. }).then(() => {
  43. return res.json({ msg: 'OK' })
  44. }).catch((err) => {
  45. res.status(400).json({ msg: err.message })
  46. })
  47. })
  48. router.get('/stats', (req, res) => {
  49. if (res.locals.isGuest) {
  50. return res.render('error-forbidden')
  51. }
  52. Promise.all([
  53. db.Entry.count(),
  54. db.UplFile.count(),
  55. db.User.count()
  56. ]).spread((totalEntries, totalUploads, totalUsers) => {
  57. return res.render('pages/admin/stats', {
  58. totalEntries, totalUploads, totalUsers, adminTab: 'stats'
  59. }) || true
  60. }).catch((err) => {
  61. throw err
  62. })
  63. })
  64. router.get('/users', (req, res) => {
  65. if (!res.locals.rights.manage) {
  66. return res.render('error-forbidden')
  67. }
  68. db.User.find({})
  69. .select('-password -rights')
  70. .sort('name email')
  71. .exec().then((usrs) => {
  72. res.render('pages/admin/users', { adminTab: 'users', usrs })
  73. })
  74. })
  75. router.get('/users/:id', (req, res) => {
  76. if (!res.locals.rights.manage) {
  77. return res.render('error-forbidden')
  78. }
  79. if (!validator.isMongoId(req.params.id)) {
  80. return res.render('error-forbidden')
  81. }
  82. db.User.findById(req.params.id)
  83. .select('-password -providerId')
  84. .exec().then((usr) => {
  85. let usrOpts = {
  86. canChangeEmail: (usr.email !== 'guest' && usr.provider === 'local' && usr.email !== req.app.locals.appconfig.admin),
  87. canChangeName: (usr.email !== 'guest'),
  88. canChangePassword: (usr.email !== 'guest' && usr.provider === 'local'),
  89. canChangeRole: (usr.email !== 'guest' && !(usr.provider === 'local' && usr.email === req.app.locals.appconfig.admin)),
  90. canBeDeleted: (usr.email !== 'guest' && !(usr.provider === 'local' && usr.email === req.app.locals.appconfig.admin))
  91. }
  92. res.render('pages/admin/users-edit', { adminTab: 'users', usr, usrOpts })
  93. }).catch(err => { // eslint-disable-line handle-callback-err
  94. return res.status(404).end() || true
  95. })
  96. })
  97. /**
  98. * Create / Authorize a new user
  99. */
  100. router.post('/users/create', (req, res) => {
  101. if (!res.locals.rights.manage) {
  102. return res.status(401).json({ msg: 'Unauthorized' })
  103. }
  104. let nUsr = {
  105. email: _.toLower(_.trim(req.body.email)),
  106. provider: _.trim(req.body.provider),
  107. password: req.body.password,
  108. name: _.trim(req.body.name)
  109. }
  110. if (!validator.isEmail(nUsr.email)) {
  111. return res.status(400).json({ msg: 'Invalid email address' })
  112. } else if (!validator.isIn(nUsr.provider, ['local', 'google', 'windowslive', 'facebook', 'github', 'slack'])) {
  113. return res.status(400).json({ msg: 'Invalid provider' })
  114. } else if (nUsr.provider === 'local' && !validator.isLength(nUsr.password, { min: 6 })) {
  115. return res.status(400).json({ msg: 'Password too short or missing' })
  116. } else if (nUsr.provider === 'local' && !validator.isLength(nUsr.name, { min: 2 })) {
  117. return res.status(400).json({ msg: 'Name is missing' })
  118. }
  119. db.User.findOne({ email: nUsr.email, provider: nUsr.provider }).then(exUsr => {
  120. if (exUsr) {
  121. return res.status(400).json({ msg: 'User already exists!' }) || true
  122. }
  123. let pwdGen = (nUsr.provider === 'local') ? db.User.hashPassword(nUsr.password) : Promise.resolve(true)
  124. return pwdGen.then(nPwd => {
  125. if (nUsr.provider !== 'local') {
  126. nUsr.password = ''
  127. nUsr.name = '-- pending --'
  128. } else {
  129. nUsr.password = nPwd
  130. }
  131. nUsr.rights = [{
  132. role: 'read',
  133. path: '/',
  134. exact: false,
  135. deny: false
  136. }]
  137. return db.User.create(nUsr).then(() => {
  138. return res.json({ ok: true })
  139. })
  140. }).catch(err => {
  141. winston.warn(err)
  142. return res.status(500).json({ msg: err })
  143. })
  144. }).catch(err => {
  145. winston.warn(err)
  146. return res.status(500).json({ msg: err })
  147. })
  148. })
  149. router.post('/users/:id', (req, res) => {
  150. if (!res.locals.rights.manage) {
  151. return res.status(401).json({ msg: lang.t('errors:unauthorized') })
  152. }
  153. if (!validator.isMongoId(req.params.id)) {
  154. return res.status(400).json({ msg: lang.t('errors:invaliduserid') })
  155. }
  156. return db.User.findById(req.params.id).then((usr) => {
  157. usr.name = _.trim(req.body.name)
  158. usr.rights = JSON.parse(req.body.rights)
  159. if (usr.provider === 'local' && req.body.password !== '********') {
  160. let nPwd = _.trim(req.body.password)
  161. if (nPwd.length < 6) {
  162. return Promise.reject(new Error(lang.t('errors:newpasswordtooshort')))
  163. } else {
  164. return db.User.hashPassword(nPwd).then((pwd) => {
  165. usr.password = pwd
  166. return usr.save()
  167. })
  168. }
  169. } else {
  170. return usr.save()
  171. }
  172. }).then((usr) => {
  173. // Update guest rights for future requests
  174. if (usr.provider === 'local' && usr.email === 'guest') {
  175. rights.guest = usr
  176. }
  177. return usr
  178. }).then(() => {
  179. return res.json({ msg: 'OK' })
  180. }).catch((err) => {
  181. res.status(400).json({ msg: err.message })
  182. })
  183. })
  184. /**
  185. * Delete / Deauthorize a user
  186. */
  187. router.delete('/users/:id', (req, res) => {
  188. if (!res.locals.rights.manage) {
  189. return res.status(401).json({ msg: lang.t('errors:unauthorized') })
  190. }
  191. if (!validator.isMongoId(req.params.id)) {
  192. return res.status(400).json({ msg: lang.t('errors:invaliduserid') })
  193. }
  194. return db.User.findByIdAndRemove(req.params.id).then(() => {
  195. return res.json({ ok: true })
  196. }).catch((err) => {
  197. res.status(500).json({ ok: false, msg: err.message })
  198. })
  199. })
  200. router.get('/settings', (req, res) => {
  201. if (!res.locals.rights.manage) {
  202. return res.render('error-forbidden')
  203. }
  204. res.render('pages/admin/settings', { adminTab: 'settings' })
  205. })
  206. router.get('/system', (req, res) => {
  207. if (!res.locals.rights.manage) {
  208. return res.render('error-forbidden')
  209. }
  210. fs.readJsonAsync(path.join(ROOTPATH, 'package.json')).then(packageObj => {
  211. axios.get('https://api.github.com/repos/Requarks/wiki/releases/latest').then(resp => {
  212. let sysversion = {
  213. current: 'v' + packageObj.version,
  214. latest: resp.data.tag_name,
  215. latestPublishedAt: resp.data.published_at
  216. }
  217. res.render('pages/admin/system', { adminTab: 'system', sysversion })
  218. }).catch(err => {
  219. winston.warn(err)
  220. res.render('pages/admin/system', { adminTab: 'system', sysversion: { current: 'v' + packageObj.version } })
  221. })
  222. })
  223. })
  224. router.post('/system/install', (req, res) => {
  225. if (!res.locals.rights.manage) {
  226. return res.render('error-forbidden')
  227. }
  228. // let sysLib = require(path.join(ROOTPATH, 'libs/system.js'))
  229. // sysLib.install('v1.0-beta.7')
  230. res.status(400).send('Sorry, Upgrade/Re-Install via the web UI is not yet ready. You must use the npm upgrade method in the meantime.').end()
  231. })
  232. router.get('/theme', (req, res) => {
  233. if (!res.locals.rights.manage) {
  234. return res.render('error-forbidden')
  235. }
  236. res.render('pages/admin/theme', { adminTab: 'theme' })
  237. })
  238. module.exports = router