Backend/middlewares/authenticate.js

71 lines
3.3 KiB
JavaScript

const Token = require('../models/Token');
const Link = require('../models/Link');
const User = require('../models/User');
const tokenTypes = ["Bearer", "API", "Server"];
const roleTrack = ["admin", "moderator", "user"];
// Checks the token
module.exports.checkToken = async (req, res) => {
// Get token header
const authHeader = req.headers["authorization"];
if (!authHeader) return res.status(400).json({message: "You need to provide the 'authorization' header"});
// Validate token header
const splitHeader = authHeader.split(" ");
if (splitHeader.length !== 2) return res.status(400).json({message: "You need to provide the token and the type of the token in the 'authorization' header"});
if (!tokenTypes.includes(splitHeader[0])) return res.status(400).json({message: "You need to provide a valid token type in the 'authorization' header"});
// Validate token in database [Session & API Tokens]
if (splitHeader[0] === "Bearer" || splitHeader[0] === "API") {
const token = await Token.findOne({token: splitHeader[1]}).exec();
if (token === null) return res.status(401).json({message: "The provided token is wrong"});
if (splitHeader[0] === "Bearer" && token.type === "api") return res.status(400).json({message: "You cannot provide session tokens for api requests"});
if (splitHeader[0] === "API" && token.type === "session") return res.status(400).json({message: "You cannot provide api tokens for session requests"});
return {type: splitHeader[0], user_id: token.user_id.toString(), token: token.token}
}
// Validate token in database [Server links]
if (splitHeader[0] === "Server") {
const link = await Link.findOne({token: splitHeader[1]}).exec();
if (link === null) return res.status(401).json({message: "The provided token is wrong or not a server link"});
if (!link.linked) return res.status(401).json({message: "The provided server is not linked yet"});
return {type: splitHeader[0], user_id: link.user_id.toString(), token: link.token}
}
}
// Checks if the server is authenticated
module.exports.isAuthenticatedServer = async (req, res, next) => {
const token = await this.checkToken(req, res);
if (!token.token) return;
if (token.type !== "Server") return res.status(403).json({message: "You are accessing a server route with an api/user token"});
req.user = await User.findById(token.user_id).exec();
if (req.user === null) return res.status(500).json({message: "An internal error occurred"});
next();
}
// Checks if the user is authenticated
module.exports.isAuthenticatedUser = async (req, res, next) => {
const token = await this.checkToken(req, res);
if (!token.token) return;
if (token.type === "Server") return res.status(403).json({message: "You are accessing a non-server route with a server token"});
req.user = await User.findById(token.user_id).exec();
if (req.user === null) return res.status(500).json({message: "An internal error occurred"});
next();
}
// Checks if the user has an exact role
module.exports.hasRoleExact = (role) => (req, res, next) => this.isAuthenticatedUser(req, res, () => {
if (req.user.rank !== role) return res.status(403).json({message: "You don't have access for this"});
next();
});
module.exports.roles = roleTrack;