from functools import wraps from django.core.exceptions import PermissionDenied from django.shortcuts import redirect from django.contrib import messages from .models import TenantUserRole # Allowed roles for staff/admin actions STAFF_ROLES = [ 'admin', 'campaign_manager', 'campaign_staff', 'system_admin', 'campaign_admin' ] def get_user_role(user, tenant): if user.is_superuser: return 'admin' role_obj = TenantUserRole.objects.filter(user=user, tenant=tenant).first() if role_obj: return role_obj.role return None def has_role(user, tenant, roles): if user.is_superuser: return True if not tenant: return False user_role = get_user_role(user, tenant) return user_role in roles def is_block_walker(user): return user.groups.filter(name='Block Walker').exists() def can_view_voters(user, tenant): if user.has_perm("core.view_voter"): return True if user.is_superuser: return True # If they can edit, they can view if can_edit_voter(user, tenant): return True # All authenticated users with a tenant role can usually view voters in our app # but we should restrict it if they have NO role and NO permission. role = get_user_role(user, tenant) if role: # Any role (even if not in STAFF_ROLES) allows viewing voters? # Block Walkers don't have a TenantUserRole usually, they have a Group. return True return False def can_view_donations(user, tenant): if user.has_perm("core.view_donation"): return True if user.is_superuser: return True role = get_user_role(user, tenant) if role in STAFF_ROLES: return True return False def can_edit_voter(user, tenant): if user.has_perm("core.change_voter"): return True if user.is_superuser: return True role = get_user_role(user, tenant) if role in STAFF_ROLES: return True return False def can_view_volunteers(user, tenant): if user.has_perm("core.view_volunteer"): return True if user.is_superuser: return True role = get_user_role(user, tenant) if role in STAFF_ROLES: return True return False def can_edit_volunteer(user, tenant): if user.has_perm("core.change_volunteer"): return True if user.is_superuser: return True role = get_user_role(user, tenant) if role in STAFF_ROLES: return True return False def role_required(roles, permission=None): def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): from .models import Tenant tenant_id = request.session.get('tenant_id') if not tenant_id: if request.user.is_superuser: return view_func(request, *args, **kwargs) messages.warning(request, "Please select a campaign first.") return redirect('index') tenant = Tenant.objects.filter(id=tenant_id).first() if not tenant: messages.warning(request, "Campaign not found.") return redirect('index') # Check roles first if has_role(request.user, tenant, roles): return view_func(request, *args, **kwargs) # Check for specific permission if provided if permission and request.user.has_perm(permission): return view_func(request, *args, **kwargs) messages.error(request, "You do not have permission to perform this action.") return redirect('index') return _wrapped_view return decorator