This repository has been archived on 2022-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
IcyNet.eu/server/routes/admin.js

315 lines
7.0 KiB
JavaScript
Raw Normal View History

2017-08-27 18:39:30 +00:00
import express from 'express'
import { ensureLogin } from '../../scripts/ensureLogin'
2017-08-27 18:39:30 +00:00
import wrap from '../../scripts/asyncRoute'
import * as API from '../api/admin'
import { sendMail } from '../api/emailer'
import { User, Login } from '../api'
2017-08-27 18:39:30 +00:00
const router = express.Router()
const apiRouter = express.Router()
2017-08-28 15:42:16 +00:00
// Check for privilege required to access the admin panel
2017-10-09 14:38:27 +00:00
router.use(ensureLogin, wrap(async (req, res, next) => {
2017-08-27 18:39:30 +00:00
if (!req.session.privilege) {
2020-05-28 18:30:21 +00:00
const u = await User.get(req.session.user)
2017-08-27 18:39:30 +00:00
req.session.privilege = u.nw_privilege
}
if (req.session.user && req.session.privilege !== 5) {
return res.redirect('/login')
}
res.locals.server_time = process.uptime()
next()
}))
2017-08-28 15:42:16 +00:00
/* ================
* ASK PASSWORD
* ================
*/
router.get('/access', (req, res) => {
2017-08-28 15:42:16 +00:00
if (!req.session.accesstime || req.session.accesstime < Date.now()) {
2020-05-28 18:30:21 +00:00
return res.status(401).jsonp({ error: 'Access expired' })
2017-08-28 15:42:16 +00:00
}
2020-05-28 18:30:21 +00:00
res.jsonp({ access: req.session.accesstime - Date.now() })
2017-08-28 15:42:16 +00:00
})
// Post password to continue
router.post('/', wrap(async (req, res, next) => {
if (!req.body.password) return next()
if (req.body.csrf !== req.session.csrf) {
2020-05-28 18:30:21 +00:00
req.flash('message', { error: true, text: 'Invalid session token' })
2017-08-28 15:42:16 +00:00
return next()
}
const passReady = await Login.password(req.session.user, req.body.password)
2017-08-28 15:42:16 +00:00
if (passReady) {
2017-08-28 22:36:13 +00:00
req.session.accesstime = Date.now() + 600000 // 10 minutes
2017-08-28 15:42:16 +00:00
return res.redirect('/admin')
} else {
2020-05-28 18:30:21 +00:00
req.flash('message', { error: true, text: 'Invalid password' })
2017-08-28 15:42:16 +00:00
}
next()
}))
// Ensure that the admin panel is not kept open for prolonged time
router.use(wrap(async (req, res, next) => {
if (req.session.accesstime) {
if (req.session.accesstime > Date.now()) {
2017-08-28 22:36:13 +00:00
req.session.accesstime = Date.now() + 600000
return next()
}
2017-08-28 15:42:16 +00:00
delete req.session.accesstime
}
2020-05-28 18:30:21 +00:00
res.render('user/password', { post: '/admin' })
2017-08-28 15:42:16 +00:00
}))
2017-08-27 18:39:30 +00:00
/* =========
* VIEWS
* =========
*/
router.get('/', (req, res) => {
res.render('admin/index')
})
router.get('/oauth2', wrap(async (req, res) => {
res.render('admin/oauth2')
}))
/* =======
* API
* =======
*/
function csrfVerify (req, res, next) {
if (req.body.csrf !== req.session.csrf) {
return next(new Error('Invalid session'))
}
next()
}
/* =============
* User Data
* =============
*/
2017-08-28 15:42:16 +00:00
apiRouter.get('/users', wrap(async (req, res) => {
let page = parseInt(req.query.page)
if (isNaN(page) || page < 1) {
page = 1
}
2020-05-28 18:30:21 +00:00
const users = await API.getAllUsers(page, req.session.user.id)
2017-08-28 15:42:16 +00:00
res.jsonp(users)
}))
apiRouter.get('/user/:id', wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.params.id)
if (isNaN(id)) {
throw new Error('Invalid number')
}
res.jsonp(await API.getUser(id))
}))
apiRouter.post('/user', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.user_id)
if (isNaN(id)) {
throw new Error('Invalid or missing user ID')
}
res.jsonp(await API.editUser(id, req.body))
}))
apiRouter.post('/user/resend_activation', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.user_id)
if (isNaN(id)) {
throw new Error('Invalid or missing user ID')
}
res.jsonp(await API.resendActivationEmail(id))
}))
apiRouter.post('/user/revoke_totp', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.user_id)
if (isNaN(id)) {
throw new Error('Invalid or missing user ID')
}
res.jsonp(await API.revokeTotpToken(id))
}))
apiRouter.post('/user/reset_password', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.user_id)
if (isNaN(id)) {
throw new Error('Invalid or missing user ID')
}
res.jsonp(await API.sendPasswordEmail(id))
}))
2018-02-13 20:32:11 +00:00
apiRouter.post('/user/lock', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.user_id)
2018-02-13 20:32:11 +00:00
if (isNaN(id)) {
throw new Error('Invalid or missing user ID')
}
res.jsonp(await API.lockAccount(id))
}))
2017-12-07 19:57:42 +00:00
const availableScopes = ['uuid', 'email', 'username', 'display_name']
apiRouter.get('/search/users', wrap(async (req, res) => {
if (!req.query.terms) throw new Error('Please specify search terms!')
2020-05-28 18:30:21 +00:00
const scopes = []
2017-12-07 19:57:42 +00:00
if (req.query.scopes) {
2020-05-28 18:30:21 +00:00
const scq = req.query.scopes.split(',')
2017-12-07 19:57:42 +00:00
2020-05-28 18:30:21 +00:00
for (const i in scq) {
2017-12-07 19:57:42 +00:00
scq[i] = scq[i].trim()
if (availableScopes.indexOf(scq[i]) !== -1) {
scopes.push(scq[i])
}
}
}
if (!scopes.length) {
scopes.push('email')
}
2020-05-28 18:30:21 +00:00
const results = await API.searchUsers(req.query.terms, scopes)
2017-12-07 19:57:42 +00:00
res.jsonp(results)
}))
2017-08-28 22:36:13 +00:00
/* ===============
* OAuth2 Data
* ===============
*/
apiRouter.get('/clients', wrap(async (req, res) => {
let page = parseInt(req.query.page)
if (isNaN(page) || page < 1) {
page = 1
}
2020-05-28 18:30:21 +00:00
const clients = await API.getAllClients(page)
res.jsonp(clients)
}))
apiRouter.get('/client/:id', wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.params.id)
if (isNaN(id)) {
throw new Error('Invalid number')
}
2020-05-28 18:30:21 +00:00
const client = await API.getClient(id)
res.jsonp(client)
}))
apiRouter.post('/client/new', csrfVerify, wrap(async (req, res) => {
await API.createClient(req.body, req.session.user)
res.status(204).end()
}))
apiRouter.post('/client/update', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.id)
2017-08-30 12:23:45 +00:00
if (!id || isNaN(id)) throw new Error('ID missing')
await API.updateClient(id, req.body)
res.status(204).end()
}))
apiRouter.post('/client/new_secret', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.id)
if (isNaN(id)) {
throw new Error('Invalid client ID')
}
2020-05-28 18:30:21 +00:00
const client = await API.newSecret(id)
res.jsonp(client)
}))
apiRouter.post('/client/delete', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.id)
if (isNaN(id)) {
throw new Error('Invalid client ID')
}
2020-05-28 18:30:21 +00:00
const client = await API.removeClient(id)
res.jsonp(client)
}))
2017-08-28 22:36:13 +00:00
/* ========
* Bans
* ========
*/
apiRouter.get('/bans', wrap(async (req, res) => {
let page = parseInt(req.query.page)
if (isNaN(page) || page < 1) {
page = 1
}
2020-05-28 18:30:21 +00:00
const bans = await API.getAllBans(page)
2017-08-28 22:36:13 +00:00
res.jsonp(bans)
}))
apiRouter.post('/ban/pardon', csrfVerify, wrap(async (req, res) => {
2020-05-28 18:30:21 +00:00
const id = parseInt(req.body.id)
2017-08-28 22:36:13 +00:00
if (isNaN(id)) {
throw new Error('Invalid number')
2017-08-28 22:36:13 +00:00
}
2020-05-28 18:30:21 +00:00
const ban = await API.removeBan(id)
2017-08-28 22:36:13 +00:00
res.jsonp(ban)
}))
apiRouter.post('/ban', csrfVerify, wrap(async (req, res) => {
if (!req.body.user_id) throw new Error('ID missing')
2017-08-28 22:36:13 +00:00
2020-05-28 18:30:21 +00:00
const result = await API.addBan(req.body, req.session.user.id)
2017-08-28 22:36:13 +00:00
res.jsonp(result)
}))
2018-02-13 21:02:07 +00:00
apiRouter.post('/email', csrfVerify, wrap(async (req, res) => {
if (!req.body.email) throw new Error('Email missing')
if (!req.body.title) throw new Error('Title missing')
if (!req.body.content) throw new Error('Content missing')
var message = {
subject: req.body.title,
html: req.body.content
}
const result = await sendMail(req.body.email, message)
2018-02-13 21:02:07 +00:00
res.jsonp(result)
}))
apiRouter.use((err, req, res, next) => {
console.error(err)
2020-05-28 18:30:21 +00:00
return res.status(400).jsonp({ error: err.message })
})
2017-08-27 18:39:30 +00:00
router.use('/api', apiRouter)
export default router