Source code for maeser.controllers.common.decorators
"""
This module contains decorators for rate limiting and admin access control
in a Flask application.
© 2024 Carson Bush, Blaine Freestone
This file is part of Maeser.
Maeser is free software: you can redistribute it and/or modify it under the terms of
the GNU Lesser General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
Maeser is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
Maeser. If not, see <https://www.gnu.org/licenses/>.
"""
from functools import wraps
from flask import abort
[docs]
def rate_limited(auth_manager, current_user):
"""
Decorator to rate limit an endpoint based on user's remaining requests.
Args:
auth_manager: The authentication manager to handle request limits.
current_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):
"""
Decorator to ensure that an endpoint can only be accessed by an admin.
Args:
current_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