Files
Server/services/authService.js
T
azures04 38882d7b87 Add bans, user cache, auth routes & token changes
Introduce user bans and caching, extend schemas, and add auth/user endpoints. Adds bans DDL and banRepo plus adminService to manage bans; introduces modules/cache for in-memory user caching used by authService and userService. Updates users and credentials DDLs (role, isDisabled, shouldReset). Changes tokensService to include role in access tokens and store refresh tokens as SHA-256 hashes. Updates repos (credentials create RETURNING, usersRepo.updateProfile positional params), enhances authService with isLogged/isNotLogged middleware, ban checks, and refreshed token flow. Adds auth routes (login, logout, refresh, register) and user routes (/me).
2026-09-16 01:45:44 +02:00

122 lines
4.2 KiB
JavaScript

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()
}
module.exports = {
isLogged,
loginLocal,
isNotLogged,
resetPassword,
registerLocal,
changePassword,
refreshAccessToken,
}