2020-11-08 13:54:08 -08:00
|
|
|
const verifyAuth = require('../../middlewares/verifyAuth')
|
|
|
|
const express = require('express')
|
2020-10-29 20:50:36 -07:00
|
|
|
const { nanoid } = require('nanoid')
|
|
|
|
|
2020-10-30 08:15:00 -07:00
|
|
|
const SECRET_TOKEN_LENGTH = 32
|
|
|
|
const SECRET_TOKEN_LIFETIME =
|
2020-10-29 20:50:36 -07:00
|
|
|
// One week, approximately. Doesn't need to be perfect.
|
2020-11-08 13:54:08 -08:00
|
|
|
1000 * // milliseconds
|
|
|
|
60 * // seconds
|
|
|
|
60 * // minutes
|
|
|
|
24 * // hours
|
|
|
|
7 // days
|
2018-11-20 11:19:58 -08:00
|
|
|
|
2021-09-14 23:41:44 -07:00
|
|
|
module.exports = ({ db, ensurePfp }) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
const router = express.Router()
|
2018-11-20 11:19:58 -08:00
|
|
|
|
|
|
|
router.get('/', verifyAuth(), (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
2018-11-20 11:19:58 -08:00
|
|
|
db.allDocs({ include_docs: true })
|
|
|
|
.then(docs => {
|
2021-12-03 08:13:43 -08:00
|
|
|
res.render('adminSettings', { title: _CC.lang('ADMIN_SETTINGS_HEADER'), users: docs.rows })
|
2018-11-20 11:19:58 -08:00
|
|
|
})
|
2020-11-08 13:54:08 -08:00
|
|
|
.catch(err => { throw err })
|
|
|
|
})
|
2018-11-20 11:19:58 -08:00
|
|
|
|
|
|
|
router.post('/add', verifyAuth(), async (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
2021-09-14 23:41:44 -07:00
|
|
|
const username = req.body.newUserUsername.trim()
|
2020-10-29 20:50:36 -07:00
|
|
|
await db.put({
|
2021-09-14 23:41:44 -07:00
|
|
|
_id: username,
|
2020-10-29 20:50:36 -07:00
|
|
|
admin: false,
|
|
|
|
wishlist: [],
|
|
|
|
|
2020-10-30 08:15:00 -07:00
|
|
|
signupToken: nanoid(SECRET_TOKEN_LENGTH),
|
|
|
|
expiry: new Date().getTime() + SECRET_TOKEN_LIFETIME
|
2020-11-08 13:54:08 -08:00
|
|
|
})
|
2021-09-14 23:41:44 -07:00
|
|
|
await ensurePfp(username)
|
2020-10-29 20:50:36 -07:00
|
|
|
res.redirect(`/admin-settings/edit/${req.body.newUserUsername.trim()}`)
|
2020-11-08 13:54:08 -08:00
|
|
|
})
|
2018-11-20 11:19:58 -08:00
|
|
|
|
2020-10-29 20:50:36 -07:00
|
|
|
router.get('/edit/:userToEdit', verifyAuth(), async (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
2020-10-29 20:50:36 -07:00
|
|
|
const doc = await db.get(req.params.userToEdit)
|
|
|
|
delete doc.password
|
2020-11-08 13:54:08 -08:00
|
|
|
res.render('admin-user-edit', { user: doc })
|
|
|
|
})
|
2018-11-20 11:19:58 -08:00
|
|
|
|
2020-10-29 20:50:36 -07:00
|
|
|
router.post('/edit/refresh-signup-token/:userToEdit', verifyAuth(), async (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
2020-10-29 20:50:36 -07:00
|
|
|
const doc = await db.get(req.params.userToEdit)
|
2020-10-30 08:15:00 -07:00
|
|
|
doc.signupToken = nanoid(SECRET_TOKEN_LENGTH)
|
|
|
|
doc.expiry = new Date().getTime() + SECRET_TOKEN_LIFETIME
|
|
|
|
await db.put(doc)
|
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToEdit}`)
|
2020-11-08 13:54:08 -08:00
|
|
|
})
|
2020-10-30 08:15:00 -07:00
|
|
|
|
|
|
|
router.post('/edit/resetpw/:userToEdit', verifyAuth(), async (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
2020-10-30 08:15:00 -07:00
|
|
|
const doc = await db.get(req.params.userToEdit)
|
|
|
|
doc.pwToken = nanoid(SECRET_TOKEN_LENGTH)
|
|
|
|
doc.pwExpiry = new Date().getTime() + SECRET_TOKEN_LIFETIME
|
|
|
|
await db.put(doc)
|
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToEdit}`)
|
2020-11-08 13:54:08 -08:00
|
|
|
})
|
2020-10-30 08:15:00 -07:00
|
|
|
|
|
|
|
router.post('/edit/cancelresetpw/:userToEdit', verifyAuth(), async (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
2020-10-30 08:15:00 -07:00
|
|
|
const doc = await db.get(req.params.userToEdit)
|
|
|
|
delete doc.pwToken
|
|
|
|
delete doc.pwExpiry
|
2020-10-29 20:50:36 -07:00
|
|
|
await db.put(doc)
|
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToEdit}`)
|
2020-11-08 13:54:08 -08:00
|
|
|
})
|
2020-10-29 20:50:36 -07:00
|
|
|
|
|
|
|
router.post('/edit/rename/:userToRename', verifyAuth(), async (req, res) => {
|
|
|
|
if (!req.user.admin && req.user._id !== req.params.userToRename) return res.redirect('/')
|
|
|
|
if (!req.body.newUsername) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_NO_USERNAME_PROVIDED'))
|
2020-10-29 20:50:36 -07:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToRename}`)
|
|
|
|
}
|
|
|
|
if (req.body.newUsername === req.params.userToRename) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_SAME_NAME'))
|
2020-10-29 20:50:36 -07:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToRename}`)
|
|
|
|
}
|
|
|
|
|
|
|
|
const oldName = req.params.userToRename
|
|
|
|
const newName = req.body.newUsername
|
|
|
|
|
|
|
|
const userDoc = await db.get(oldName)
|
|
|
|
userDoc._id = newName
|
|
|
|
delete userDoc._rev
|
|
|
|
try {
|
|
|
|
await db.put(userDoc)
|
|
|
|
try {
|
|
|
|
const usersBulk = []
|
|
|
|
const users = (await db.allDocs({ include_docs: true })).rows
|
|
|
|
for (const { doc: user } of users) {
|
|
|
|
for (const item of user.wishlist) {
|
|
|
|
if (item.pledgedBy === oldName) item.pledgedBy = newName
|
|
|
|
if (item.addedBy === oldName) item.addedBy = newName
|
|
|
|
}
|
|
|
|
usersBulk.push(user)
|
|
|
|
}
|
|
|
|
|
|
|
|
await db.bulkDocs(usersBulk)
|
|
|
|
await db.remove(await db.get(oldName))
|
2020-11-08 13:54:08 -08:00
|
|
|
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('success', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_RENAMED_USER'))
|
2020-10-29 20:50:36 -07:00
|
|
|
return res.redirect(`/wishlist/${newName}`)
|
|
|
|
} catch (error) {
|
|
|
|
console.log(error, error.stack)
|
|
|
|
await db.remove(await db.get(newName))
|
|
|
|
throw error
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
req.flash('error', error.message)
|
|
|
|
return res.redirect(`/admin-settings/edit/${oldName}`)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2020-11-03 17:25:20 -08:00
|
|
|
router.post('/edit/impersonate/:userToEdit', verifyAuth(), async (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
2020-11-03 17:25:20 -08:00
|
|
|
req.login({ _id: req.params.userToEdit }, err => {
|
|
|
|
if (err) {
|
|
|
|
req.flash('error', err.message)
|
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToEdit}`)
|
|
|
|
}
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('success', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_IMPERSONATE_SUCCESS', req.params.userToEdit))
|
2020-11-03 17:25:20 -08:00
|
|
|
res.redirect('/')
|
|
|
|
})
|
2020-11-08 13:54:08 -08:00
|
|
|
})
|
2020-11-03 17:25:20 -08:00
|
|
|
|
2021-01-02 14:07:07 -08:00
|
|
|
router.post('/edit/promote/:userToPromote', verifyAuth(), async (req, res) => {
|
|
|
|
if (!req.user.admin) return res.redirect('/')
|
|
|
|
const user = await db.get(req.params.userToPromote)
|
|
|
|
if (!user) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_PROMOTE_DEMOTE_NOT_FOUND'))
|
2021-01-02 14:07:07 -08:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToPromote}`)
|
|
|
|
}
|
|
|
|
if (user.admin) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_PROMOTE_ALREADY_ADMIN'))
|
2021-01-02 14:07:07 -08:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToPromote}`)
|
|
|
|
}
|
|
|
|
|
|
|
|
user.admin = true
|
|
|
|
await db.put(user)
|
|
|
|
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('success', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_PROMOTE_SUCCESS', user._id))
|
2021-01-02 14:07:07 -08:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToPromote}`)
|
|
|
|
})
|
|
|
|
|
|
|
|
router.post('/edit/demote/:userToDemote', verifyAuth(), async (req, res) => {
|
|
|
|
if (!req.user.admin) return res.redirect('/')
|
|
|
|
if (req.user._id === req.params.userToDemote) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_DEMOTE_SELF'))
|
2021-01-02 14:07:07 -08:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToDemote}`)
|
|
|
|
}
|
|
|
|
|
|
|
|
const user = await db.get(req.params.userToDemote)
|
|
|
|
|
|
|
|
if (!user) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_PROMOTE_DEMOTE_NOT_FOUND'))
|
2021-01-02 14:07:07 -08:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToDemote}`)
|
|
|
|
}
|
|
|
|
if (!user.admin) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_DEMOTE_NOT_ADMIN'))
|
2021-01-02 14:07:07 -08:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToDemote}`)
|
|
|
|
}
|
|
|
|
|
|
|
|
user.admin = false
|
|
|
|
await db.put(user)
|
|
|
|
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('success', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_DEMOTE_SUCCESS', user._id))
|
2021-01-02 14:07:07 -08:00
|
|
|
return res.redirect(`/admin-settings/edit/${req.params.userToDemote}`)
|
|
|
|
})
|
|
|
|
|
2020-10-29 20:50:36 -07:00
|
|
|
router.post('/edit/remove/:userToRemove', verifyAuth(), async (req, res) => {
|
2020-11-08 13:54:08 -08:00
|
|
|
if (!req.user.admin) return res.redirect('/')
|
|
|
|
const doc = await db.get(req.params.userToRemove)
|
2018-11-20 11:19:58 -08:00
|
|
|
if (doc.admin) {
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('error', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_DELETE_FAIL_ADMIN'))
|
2020-11-08 13:54:08 -08:00
|
|
|
return res.redirect('/admin-settings')
|
2018-11-20 11:19:58 -08:00
|
|
|
}
|
2020-11-08 13:54:08 -08:00
|
|
|
await db.remove(doc)
|
|
|
|
const { rows } = await db.allDocs({ include_docs: true })
|
|
|
|
for (let i = 0; i < rows.length; i++) {
|
|
|
|
for (let j = 0; j < rows[i].doc.wishlist.length; j++) {
|
|
|
|
if (rows[i].doc.wishlist[j].pledgedBy === req.params.userToRemove) {
|
|
|
|
rows[i].doc.wishlist[j].pledgedBy = undefined
|
|
|
|
if (rows[i].doc.wishlist[j].addedBy === req.params.userToRemove) rows[i].doc.wishlist.splice(j, 1)
|
|
|
|
await db.put(rows[i].doc)
|
2018-11-20 11:19:58 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('success', _CC.lang('ADMIN_SETTINGS_USERS_EDIT_DELETE_SUCCESS', req.params.userToRemove))
|
2018-11-20 11:19:58 -08:00
|
|
|
res.redirect('/admin-settings')
|
2020-11-08 13:54:08 -08:00
|
|
|
})
|
2018-11-20 11:19:58 -08:00
|
|
|
|
2021-09-13 13:47:56 -07:00
|
|
|
router.get('/clear-wishlists', verifyAuth(), async (req, res) => {
|
|
|
|
if (!req.user.admin) return res.redirect('/')
|
|
|
|
res.render('admin-clear-wishlists')
|
|
|
|
})
|
|
|
|
|
|
|
|
router.post('/clear-wishlists', verifyAuth(), async (req, res) => {
|
|
|
|
if (!req.user.admin) return res.redirect('/')
|
|
|
|
const { rows } = await db.allDocs({ include_docs: true })
|
|
|
|
for (const row of rows) {
|
|
|
|
row.doc.wishlist = []
|
|
|
|
await db.put(row.doc)
|
|
|
|
}
|
2021-12-03 08:13:43 -08:00
|
|
|
req.flash('success', _CC.lang('ADMIN_SETTINGS_CLEARDB_SUCCESS'))
|
2021-09-13 13:47:56 -07:00
|
|
|
res.redirect('/admin-settings')
|
|
|
|
})
|
|
|
|
|
2020-11-08 13:54:08 -08:00
|
|
|
return router
|
|
|
|
}
|