const cache = require("../modules/cache") const bcrypt = require("bcryptjs") const usersRepo = require("../repositories/usersRepo") const adminService = require("./adminService") const tokensService = require("./tokensService") const identitiesRepo = require("../repositories/identitiesRepo") const credentialsRepo = require("../repositories/credentialsRepo") const { DefaultError } = require("../errors/errors") async function registerLocal({ identifier, password, profile = { displayName, avatarURL } }) { try { const user = await usersRepo.create(identifier, process.env.SERVER_UUID, null, profile.displayName, profile.avatarURL) const hashedPassword = await bcrypt.hash(password, Number(process.env.BCRYPT_SALT)) const credentials = await credentialsRepo.create(user.id, hashedPassword) if (credentials.length == 0) { throw new DefaultError(500, "Internal Server Error", "UserRegistration") } return user } catch (error) { throw error } } async function validatePassword({ password, passwordHash }) { try { await bcrypt.compare(password, passwordHash) } catch (error) { throw new DefaultError(401, "Bad credentials", "Wrong password") } } async function loginLocal({ identifier, password }) { try { const user = await usersRepo.findByIdentifier(identifier) const credentials = await credentialsRepo.findByUserId(user.id) await validatePassword({ password: password, passwordHash: credentials.passwordHash }) const accessToken = await tokensService.signToken(user) const refreshToken = await tokensService.signRefreshToken(user.id) return { user, tokens: { accessToken, refreshToken } } } catch (error) { console.log(error) throw new DefaultError(500, "Internal Server Error", error.toString()) } } async function refreshAccessToken({ refreshToken }) { try { const payload = await tokensService.verifyRefreshToken(refreshToken) await tokensService.revokeRefreshToken(refreshToken) const user = await usersRepo.findById(payload.userId) const newAccessToken = await tokensService.signToken(user) const newRefreshToken = await tokensService.signRefreshToken(user.id) return { accessToken: newAccessToken, refreshToken: newRefreshToken } } catch (error) { throw error } } async function changePassword({ userId, password, newPassword }) { try { const credentials = await credentialsRepo.findByUserId(userId) await validatePassword({ password, passwordHash: credentials.passwordHash }) await credentialsRepo.updatePassword(userId, newPassword) return true } catch (error) { throw error } } async function resetPassword({ userId, newPassword }) { try { await credentialsRepo.updatePassword(userId, newPassword) return true } catch (error) { throw error } } async function isNotLogged(req, res, next) { if (req.headers.authorization && req.headers.authorization.startsWith("Bearer")) { throw new DefaultError(401, "You must be logged out to do this action", "Auth header") } next() } async function isLogged(req, res, next) { if (!req.headers.authorization) { throw new DefaultError(401, "You must be logged in to do this action", "Auth header") } if (!req.headers.authorization.startsWith("Bearer ")) { throw new DefaultError(422, "Wrong auth header format", "WhereIsBearer") } const tokenVerified = await tokensService.verifyAccessToken(req.headers.authorization.replace("Bearer ", "")) const isBanned = await adminService.isUserBanned(tokenVerified.id) if (isBanned) { throw new DefaultError(403, "You're not allowed to do this action", "Banned") } let user = cache.users.get(tokenVerified.id) if (!user) { user = await usersRepo.findById(tokenVerified.id) if (!user) { throw new DefaultError(404, "User not found", "UserNotFound") } cache.users.put(tokenVerified.id, user) } req.user = user next() } function hasAdminRights(req, res, next) { if (req.user?.role == "admin") { return next() } throw new DefaultError(403, "Forbidden", "You must be administrator.") } module.exports = { isLogged, loginLocal, isNotLogged, resetPassword, registerLocal, changePassword, hasAdminRights, refreshAccessToken, }