Source code for organisations.decorators

""" Club Menu Decorators to simplify code """
from django.http import HttpResponse
from django.shortcuts import redirect, get_object_or_404

from rbac.core import rbac_user_has_role
from rbac.views import rbac_forbidden
from .models import Organisation
from .views.general import get_rbac_model_for_state


def _check_extra_role(request, function, club, extra_role, *args, **kwargs):
    """sub function to check for extra access"""

    if rbac_user_has_role(request.user, extra_role):
        return function(request, club, *args, **kwargs)
    else:
        return rbac_forbidden(request, extra_role, htmx=True)


[docs] def check_club_menu_access( check_members=False, check_comms=False, check_sessions=False, check_payments=False, check_payments_view=False, check_session_or_payments=False, check_org_edit=False, ): """checks if user should have access to a club menu Call as: from .decorators import check_club_menu_access @check_club_menu_access() def my_func(request, club): You don't need @login_required as it does that for you as well Optional parameters: check_members: Will also check for the role orgs.members.{club.id}.edit check_comms: Will also check for the role notifications.orgcomms.{club.id}.edit check_sessions: Will also check for the role club_sessions.sessions.{club.id}.edit check_payments: Will also check for the role payments.manage.{club.id}.edit check_payments_view: Will also check for the role payments.manage.{club.id}.[edit|view] check_org_edit: Will also check for the role orgs.org.{club.id}.edit check_session_or_payments: Checks for either sessions or payments. This is needed as directors as well as payments people need to be able to make miscellaneous payments, but we want to keep both roles separate otherwise We add a parameter (club) to the actual call which is fine for calls from URLs but if we call this internally it will need to be called without the club parameter. The optional parameters are only applied for normal admin users, Global or State admins get in any way even if they don't have the extra permissions. """ # Need two layers of wrapper to handle the parameters being passed in def _method_wrapper(function): # second layer def _arguments_wrapper(request, *args, **kwargs): # Test if logged in if not request.user.is_authenticated: return redirect("/") # We only accept POSTs if request.method != "POST": return HttpResponse("Error - POST expected") # Get club club_id = request.POST.get("club_id") club = get_object_or_404(Organisation, pk=club_id) # TODO: add a multiple option to RBAC so we can combine these into a single query # Check for state level access rbac_model_for_state = get_rbac_model_for_state(club.state) state_role = f"orgs.state.{rbac_model_for_state}.edit" if rbac_user_has_role(request.user, state_role): return function(request, club, *args, **kwargs) # Check for global role if rbac_user_has_role(request.user, "orgs.admin.edit"): return function(request, club, *args, **kwargs) # Check for club level access club_role = f"orgs.org.{club.id}.view" if rbac_user_has_role(request.user, club_role): # Check for optional member parameter if check_members: extra_role = f"orgs.members.{club.id}.edit" return _check_extra_role( request, function, club, extra_role, *args, **kwargs ) # Check for optional comms parameter if check_comms: extra_role = f"notifications.orgcomms.{club.id}.edit" return _check_extra_role( request, function, club, extra_role, *args, **kwargs ) # Check for optional sessions parameter if check_sessions: extra_role = f"club_sessions.sessions.{club.id}.edit" return _check_extra_role( request, function, club, extra_role, *args, **kwargs ) # Check for optional sessions parameter if check_payments: extra_role = f"payments.manage.{club.id}.edit" return _check_extra_role( request, function, club, extra_role, *args, **kwargs ) # Check for optional sessions parameter if check_payments_view: view = f"payments.manage.{club.id}.view" edit = f"payments.manage.{club.id}.edit" if rbac_user_has_role(request.user, view) or rbac_user_has_role( request.user, edit ): return function(request, club, *args, **kwargs) else: return rbac_forbidden(request, view) # Check for optional sessions parameter if check_org_edit: extra_role = f"orgs.org.{club.id}.edit" return _check_extra_role( request, function, club, extra_role, *args, **kwargs ) # Check for optional sessions parameter if check_session_or_payments: if rbac_user_has_role( request.user, f"club_sessions.sessions.{club.id}.edit" ) or rbac_user_has_role( request.user, f"payments.manage.{club.id}.edit" ): return function(request, club, *args, **kwargs) else: # Can only return one role currently for rbac_forbidden return rbac_forbidden( request, f"payments.manage.{club.id}.edit" ) # Passed the access check and there are no additional checks so all good return function(request, club, *args, **kwargs) return rbac_forbidden(request, club_role, htmx=True) return _arguments_wrapper return _method_wrapper