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.

265 lines
7.6 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. })
  94. })
  95. /**
  96. * Create / Authorize a new user
  97. */
  98. router.post('/users/create', (req, res) => {
  99. if (!res.locals.rights.manage) {
  100. return res.status(401).json({ msg: 'Unauthorized' })
  101. }
  102. let nUsr = {
  103. email: _.toLower(_.trim(req.body.email)),
  104. provider: _.trim(req.body.provider),
  105. password: req.body.password,
  106. name: _.trim(req.body.name)
  107. }
  108. if (!validator.isEmail(nUsr.email)) {
  109. return res.status(400).json({ msg: 'Invalid email address' })
  110. } else if (!validator.isIn(nUsr.provider, ['local', 'google', 'windowslive', 'facebook', 'github', 'slack'])) {
  111. return res.status(400).json({ msg: 'Invalid provider' })
  112. } else if (nUsr.provider === 'local' && !validator.isLength(nUsr.password, { min: 6 })) {
  113. return res.status(400).json({ msg: 'Password too short or missing' })
  114. } else if (nUsr.provider === 'local' && !validator.isLength(nUsr.name, { min: 2 })) {
  115. return res.status(400).json({ msg: 'Name is missing' })
  116. }
  117. db.User.findOne({ email: nUsr.email, provider: nUsr.provider }).then(exUsr => {
  118. if (exUsr) {
  119. return res.status(400).json({ msg: 'User already exists!' }) || true
  120. }
  121. let pwdGen = (nUsr.provider === 'local') ? db.User.hashPassword(nUsr.password) : Promise.resolve(true)
  122. return pwdGen.then(nPwd => {
  123. if (nUsr.provider !== 'local') {
  124. nUsr.password = ''
  125. nUsr.name = '-- pending --'
  126. } else {
  127. nUsr.password = nPwd
  128. }
  129. nUsr.rights = [{
  130. role: 'read',
  131. path: '/',
  132. exact: false,
  133. deny: false
  134. }]
  135. return db.User.create(nUsr).then(() => {
  136. return res.json({ ok: true })
  137. })
  138. }).catch(err => {
  139. winston.warn(err)
  140. return res.status(500).json({ msg: err })
  141. })
  142. }).catch(err => {
  143. winston.warn(err)
  144. return res.status(500).json({ msg: err })
  145. })
  146. })
  147. router.post('/users/:id', (req, res) => {
  148. if (!res.locals.rights.manage) {
  149. return res.status(401).json({ msg: lang.t('errors:unauthorized') })
  150. }
  151. if (!validator.isMongoId(req.params.id)) {
  152. return res.status(400).json({ msg: lang.t('errors:invaliduserid') })
  153. }
  154. return db.User.findById(req.params.id).then((usr) => {
  155. usr.name = _.trim(req.body.name)
  156. usr.rights = JSON.parse(req.body.rights)
  157. if (usr.provider === 'local' && req.body.password !== '********') {
  158. let nPwd = _.trim(req.body.password)
  159. if (nPwd.length < 6) {
  160. return Promise.reject(new Error(lang.t('errors:newpasswordtooshort')))
  161. } else {
  162. return db.User.hashPassword(nPwd).then((pwd) => {
  163. usr.password = pwd
  164. return usr.save()
  165. })
  166. }
  167. } else {
  168. return usr.save()
  169. }
  170. }).then((usr) => {
  171. // Update guest rights for future requests
  172. if (usr.provider === 'local' && usr.email === 'guest') {
  173. rights.guest = usr
  174. }
  175. return usr
  176. }).then(() => {
  177. return res.json({ msg: 'OK' })
  178. }).catch((err) => {
  179. res.status(400).json({ msg: err.message })
  180. })
  181. })
  182. /**
  183. * Delete / Deauthorize a user
  184. */
  185. router.delete('/users/:id', (req, res) => {
  186. if (!res.locals.rights.manage) {
  187. return res.status(401).json({ msg: lang.t('errors:unauthorized') })
  188. }
  189. if (!validator.isMongoId(req.params.id)) {
  190. return res.status(400).json({ msg: lang.t('errors:invaliduserid') })
  191. }
  192. return db.User.findByIdAndRemove(req.params.id).then(() => {
  193. return res.json({ msg: 'OK' })
  194. }).catch((err) => {
  195. res.status(500).json({ msg: err.message })
  196. })
  197. })
  198. router.get('/settings', (req, res) => {
  199. if (!res.locals.rights.manage) {
  200. return res.render('error-forbidden')
  201. }
  202. fs.readJsonAsync(path.join(ROOTPATH, 'package.json')).then(packageObj => {
  203. axios.get('https://api.github.com/repos/Requarks/wiki/releases/latest').then(resp => {
  204. let sysversion = {
  205. current: 'v' + packageObj.version,
  206. latest: resp.data.tag_name,
  207. latestPublishedAt: resp.data.published_at
  208. }
  209. res.render('pages/admin/settings', { adminTab: 'settings', sysversion })
  210. }).catch(err => {
  211. winston.warn(err)
  212. res.render('pages/admin/settings', { adminTab: 'settings', sysversion: { current: 'v' + packageObj.version } })
  213. })
  214. })
  215. })
  216. router.post('/settings/install', (req, res) => {
  217. if (!res.locals.rights.manage) {
  218. return res.render('error-forbidden')
  219. }
  220. // let sysLib = require(path.join(ROOTPATH, 'libs/system.js'))
  221. // sysLib.install('v1.0-beta.7')
  222. 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()
  223. })
  224. router.get('/theme', (req, res) => {
  225. if (!res.locals.rights.manage) {
  226. return res.render('error-forbidden')
  227. }
  228. res.render('pages/admin/theme', { adminTab: 'theme' })
  229. })
  230. module.exports = router