const randomstring = require('randomstring') const perms = require('./permissionController') const utils = require('./utilsController') const config = require('./../config') const logger = require('./../logger') const db = require('knex')(config.database) const self = { tokenLength: 64, tokenMaxTries: 3, onHold: new Set() } self.generateUniqueToken = async () => { for (let i = 0; i < self.tokenMaxTries; i++) { const token = randomstring.generate(self.tokenLength) if (self.onHold.has(token)) continue // Put token on-hold (wait for it to be inserted to DB) self.onHold.add(token) const user = await db.table('users') .where('token', token) .select('id') .first() if (user) { self.onHold.delete(token) continue } return token } return null } self.verify = async (req, res, next) => { const token = typeof req.body.token === 'string' ? req.body.token.trim() : '' if (!token) return res.json({ success: false, description: 'No token provided.' }) try { const user = await db.table('users') .where('token', token) .select('username', 'permission') .first() if (!user) return res.json({ success: false, description: 'Invalid token.' }) return res.json({ success: true, username: user.username, permissions: perms.mapPermissions(user) }) } catch (error) { logger.error(error) return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' }) } } self.list = async (req, res, next) => { const user = await utils.authorize(req, res) if (!user) return return res.json({ success: true, token: user.token }) } self.change = async (req, res, next) => { const user = await utils.authorize(req, res) if (!user) return const newToken = await self.generateUniqueToken() if (!newToken) return res.json({ success: false, description: 'Sorry, we could not allocate a unique token. Try again?' }) try { await db.table('users') .where('token', user.token) .update({ token: newToken, timestamp: Math.floor(Date.now() / 1000) }) self.onHold.delete(newToken) return res.json({ success: true, token: newToken }) } catch (error) { logger.error(error) return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' }) } } module.exports = self