Skip to content

Commit

Permalink
Better documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
kyrea committed Dec 29, 2023
1 parent 1b2f14e commit 48435c1
Showing 1 changed file with 61 additions and 24 deletions.
85 changes: 61 additions & 24 deletions src/middlewares/authorize.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,48 @@ import Stats from '../models/schemas/Stat.js';

/**
* Middleware for handling user authentication and request validation.
*
* @function
* @param {string} requiredRole - The required role to access the endpoint.
* @returns {function} - Express middleware function.
* @throws {Error} Throws an error if there is an issue with authentication or validation.
*
* @error {400} Bad Request - User has not provided a valid token.
* @error {401} Unauthorized - User has provided an invalid API key.
* @error {403} Forbidden - User is banned, request limit is exhausted, or insufficient privileges.
*/
const authorize = (requiredRole) => async (req, res, next) => {
const authorize = requiredRole => async (req, res, next) => {
try {
// Extract API key from request headers
/**
* Extract API key from request headers.
*
* @type {string}
*/
const key = req.headers.authorization;

// Verify if the API key exists in the database
/**
* Handle case where the user has not provided a valid token.
*/
if (!key) {
await incrementSystemStats({
endpoints_requests: 1,
daily_requests: 1,
});
return next(createError(400, 'Bad Request. Go to https://docs.waifu.it for more info.'));
}

/**
* Verify if the API key exists in the database.
*
* @type {Object|null}
*/
const userData = await Users.findOne({ token: key });

// Update request quotas and count
/**
* Update request quotas and count.
*
* @type {Object}
*/
const updateData = {
$inc: {
req_quoto: userData && userData.req_quoto > 0 ? -1 : 0,
Expand All @@ -24,22 +54,21 @@ const authorize = (requiredRole) => async (req, res, next) => {
};
await Users.updateOne({ token: key }, updateData);

// Handle case where the user has not provided a valid token
/**
* Handle case where the user has not provided a valid token.
*/
if (!userData) {
await incrementSystemStats({
failed_requests: 1,
endpoints_requests: 1,
daily_requests: 1,
});
return next(
createError(
401,
'Invalid API key. Go to https://docs.waifu.it for more info.'
)
);
return next(createError(401, 'Invalid API key. Go to https://docs.waifu.it for more info.'));
}

// Handle case where the user is banned
/**
* Handle case where the user is banned.
*/
if (userData.banned) {
await incrementSystemStats({
banned_requests: 1,
Expand All @@ -49,42 +78,50 @@ const authorize = (requiredRole) => async (req, res, next) => {
return next(createError(403, "You've been banned from using the API."));
}

// Handle case where the request limit is exhausted [Currently Disabled]
/**
* Handle case where the request limit is exhausted.
*/
if (userData.req_quoto <= 0) {
return next(
createError(
403,
"You've exhausted your request limits. Buy Premium to increase it more."
)
);
return next(createError(403, "You've exhausted your request limits. Buy Premium to increase it more."));
}

// Check if the user has the required role
/**
* Check if the user has the required role.
*/
if (!userData.roles.includes(requiredRole)) {
return next(createError(403, 'Insufficient privileges to access this endpoint.'));
}

// Increment system stats for successful requests
/**
* Increment system stats for successful requests.
*/
await incrementSystemStats({
endpoints_requests: 1,
success_requests: 1,
daily_requests: 1,
});

// Call the next middleware
/**
* Call the next middleware.
*/
return next();
} catch (error) {
// Pass any caught errors to the error handler
/**
* Pass any caught errors to the error handler.
*/
return next(error);
}
};

/**
* Increment the specified statistics in the system stats collection.
*
* @function
* @param {Object} stats - Statistics to be incremented.
* @returns {Promise<void>} - Resolves when the stats are updated.
* @throws {Error} Throws an error if there is an issue with updating statistics.
*/
const incrementSystemStats = async (stats) => {
const incrementSystemStats = async stats => {
await Stats.findByIdAndUpdate({ _id: 'systemstats' }, { $inc: stats });
};

Expand Down

0 comments on commit 48435c1

Please sign in to comment.