const { randomBytes } = require('crypto') const { promisify } = require('util') const passport = require('passport') const User = require('../models/user') const email = require('../models/email') const { origin } = require('../config/keys') const { rememberMeCookieSettings } = require('../config/settings') const RandomBytesAsync = promisify(randomBytes) const { DEFAULT_HITS_PER_PAGE } = require('../config/settings') const user = {} user.register = async (req, res) => { // TODO Add validation. const userId = await User.create({ ...req.body, language: req.session.language }) const activationToken = (await RandomBytesAsync(32)).toString('hex') await User.saveActivationToken(userId, activationToken) const { email: userEmail, username } = req.body let activationLink = new URL('/users/activate', origin) activationLink.searchParams.set('token', activationToken) activationLink = activationLink.href const renderAsync = promisify(req.app.render.bind(req.app)) const emailHtml = await renderAsync(`email/user-activation_${req.language}`, { username, activationLink }) await email.send({ to: userEmail, subject: req.t('Aktivacija računa'), html: emailHtml }) res.send(req.t('Registracija uspešna')) } user.activateAccount = async (req, res) => { // TODO Add validation. What if user is already logged in? What if account is already active? ... const { token } = req.query const user = await User.fetchByActivationToken(token) await User.activateAccount(user) const loginAsync = promisify(req.login.bind(req)) await loginAsync(user) if (req.session.language) { await User.updateLanguage(user.id, req.session.language) delete req.session.language } res.redirect('/') } user.login = async (req, res, next) => { passport.authenticate( 'local', { badRequestMessage: req.t( 'Nepravilno uporabniško ime, elektronski naslov ali geslo.' ) }, async (err, user, info) => { if (err) return next(err) if (!user) { const err = Error(info.message) err.status = 403 err.displayInProd = true return next(err) } const loginAsync = promisify(req.login.bind(req)) await loginAsync(user) if (req.body.rememberMe) { // TODO Consider what happens if the user already has a remember me token. const rememberMeToken = await User.generateRememberMeToken() await User.saveRememberMeToken(user, rememberMeToken) res.cookie('remember_me', rememberMeToken, rememberMeCookieSettings) } if (req.session.language) { await User.updateLanguage(user.id, req.session.language) delete req.session.language } res.send(req.t('Prijava uspešna')) } )(req, res, next) } user.logout = async (req, res) => { const rememberMeToken = req.signedCookies.remember_me if (rememberMeToken) { res.clearCookie('remember_me') await User.clearRememberMeToken(rememberMeToken) } req.session.language = req.user.language req.logout() // Manually clear session.passport due to bug in current passport version. delete req.session.passport.user res.redirect('/') } user.list = async (req, res) => { const resultsPerPage = req.user?.hitsPerPage || DEFAULT_HITS_PER_PAGE const { pages_total: numberOfAllPages, results } = await User.fetchAll( resultsPerPage, 1 ) res.render('pages/admin/user-list', { title: req.t('Seznam uporabnikov'), numberOfAllPages, results }) } user.listAllWithPortalRoles = async (req, res) => { const users = await User.fetchAllWithPortalRoles() res.render('pages/admin/user-portals', { title: req.t('Skrbniki portala'), users }) } user.findByUsernameOrEmail = async (req, res) => { const userNameEmail = req.query.userNameEmail const searchedUser = await User.findByUsernameOrEmail(userNameEmail) res.send(searchedUser) } user.updateRoles = async (req, res) => { await User.updatePortalRoles(req.body.rolesPerUser) res.redirect('back') } user.adminEdit = async (req, res) => { const userId = req.params.userId const [userData, userRoles] = await Promise.all([ User.fetchUser(userId), User.fetchUserRoles(userId) ]) res.render('pages/admin/user-edit', { title: req.t('Uporabnik'), userData, userRoles }) } // TODO Aljaž: Luka, please adjust update function for updating user's password and email // TODO Handle username unique constraint failure. user.adminUpdate = async (req, res) => { const { userId } = req.params await User.updateUser(userId, req.body) res.redirect('back') } module.exports = user