Source code for maeser.controllers.common.decorators
# SPDX-License-Identifier: LGPL-3.0-or-later
"""
This module contains decorators for rate limiting and admin access control
in a Flask application.
"""
from maeser.user_manager import UserManager, User
from functools import wraps
from flask import abort
[docs]
def rate_limited(auth_manager: UserManager, current_user: User):
"""
Decorator to rate limit an endpoint based on user's remaining requests.
Aborts endpoint with code 429 if the user is out of requests.
Args:
auth_manager (UserManager): The authentication manager to handle request limits.
current_user (User): The user object containing request information.
Returns:
A wrapped endpoint function that checks for rate limits.
"""
def decorator(endpoint):
@wraps(endpoint)
def rate_limited_wrapper(*args, **kwargs):
# Check if user has any requests remaining before proceeding
if current_user.requests_remaining <= 0:
print(f"User ({current_user.full_id_name}) has no requests remaining")
abort(429, "Rate limit reached, please try again later")
result = endpoint(*args, **kwargs)
# Decrease the number of requests remaining for the user once response is sent and update the result
auth_manager.decrease_requests(current_user.auth_method, current_user.ident)
result["requests_remaining"] = auth_manager.get_requests_remaining(
current_user.auth_method, current_user.ident
)
return result
rate_limited_wrapper.__name__ = f"{endpoint.__name__}"
return rate_limited_wrapper
return decorator
[docs]
def admin_required(current_user: User):
"""
Decorator to ensure that an endpoint can only be accessed by an admin.
Aborts endpoint with code 403 if user does not have admin access.
Args:
current_user (User): The user object to check for admin privileges.
Returns:
A wrapped endpoint function that checks for admin access.
"""
def decorator(endpoint):
@wraps(endpoint)
def admin_wrapper(*args, **kwargs):
if current_user.admin:
print(f"User ({current_user.full_id_name}) is admin")
return endpoint(*args, **kwargs)
print(f"User ({current_user.full_id_name}) is not authorized")
abort(403, "Admin access is required to access this page.")
admin_wrapper.__name__ = f"{endpoint.__name__}"
return admin_wrapper
return decorator