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.

250 lines
7.1 KiB

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