from functools import wraps from datetime import date from django.shortcuts import redirect, get_object_or_404 from django.http import HttpResponseNotFound, HttpResponseForbidden from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import AccessMixin from django.core.exceptions import PermissionDenied from django.contrib import messages from django.contrib.auth.decorators import user_passes_test def job_not_expired(view_func): @wraps(view_func) def _wrapped_view(request, job_id, *args, **kwargs): from .models import JobPosting job = get_object_or_404(JobPosting, pk=job_id) if job.expiration_date and job.application_deadline< date.today(): return redirect('expired_job_page') return view_func(request, job_id, *args, **kwargs) return _wrapped_view def user_type_required(allowed_types=None, login_url=None): """ Decorator to restrict view access based on user type. Args: allowed_types (list): List of allowed user types ['staff', 'agency', 'candidate'] login_url (str): URL to redirect to if user is not authenticated """ if allowed_types is None: allowed_types = ['staff'] def decorator(view_func): @wraps(view_func) @login_required(login_url=login_url) def _wrapped_view(request, *args, **kwargs): user = request.user # Check if user has user_type attribute if not hasattr(user, 'user_type') or not user.user_type: messages.error(request, "User type not specified. Please contact administrator.") return redirect('account_login') # Check if user type is allowed if user.user_type not in allowed_types: # Log unauthorized access attempt messages.error( request, f"Access denied. This page is restricted to {', '.join(allowed_types)} users." ) # Redirect based on user type if user.user_type == 'agency': return redirect('agency_portal_dashboard') elif user.user_type == 'candidate': return redirect('applicant_portal_dashboard') else: return redirect('dashboard') return view_func(request, *args, **kwargs) return _wrapped_view return decorator class UserTypeRequiredMixin(AccessMixin): """ Mixin for class-based views to restrict access based on user type. """ allowed_user_types = ['staff'] # Default to staff only login_url = '/accounts/login/' def dispatch(self, request, *args, **kwargs): if not request.user.is_authenticated: return self.handle_no_permission() # Check if user has user_type attribute if not hasattr(request.user, 'user_type') or not request.user.user_type: messages.error(request, "User type not specified. Please contact administrator.") return redirect('account_login') # Check if user type is allowed if request.user.user_type not in self.allowed_user_types: # Log unauthorized access attempt messages.error( request, f"Access denied. This page is restricted to {', '.join(self.allowed_user_types)} users." ) # Redirect based on user type if request.user.user_type == 'agency': return redirect('agency_portal_dashboard') elif request.user.user_type == 'candidate': return redirect('applicant_portal_dashboard') else: return redirect('dashboard') return super().dispatch(request, *args, **kwargs) def handle_no_permission(self): if self.request.user.is_authenticated: # User is authenticated but doesn't have permission messages.error( self.request, f"Access denied. This page is restricted to {', '.join(self.allowed_user_types)} users." ) return redirect('dashboard') else: # User is not authenticated return super().handle_no_permission() class StaffRequiredMixin(UserTypeRequiredMixin): """Mixin to restrict access to staff users only.""" allowed_user_types = ['staff'] class AgencyRequiredMixin(UserTypeRequiredMixin): """Mixin to restrict access to agency users only.""" allowed_user_types = ['agency'] login_url = '/accounts/login/' class CandidateRequiredMixin(UserTypeRequiredMixin): """Mixin to restrict access to candidate users only.""" allowed_user_types = ['candidate'] login_url = '/accounts/login/' class StaffOrAgencyRequiredMixin(UserTypeRequiredMixin): """Mixin to restrict access to staff and agency users.""" allowed_user_types = ['staff', 'agency'] class StaffOrCandidateRequiredMixin(UserTypeRequiredMixin): """Mixin to restrict access to staff and candidate users.""" allowed_user_types = ['staff', 'candidate'] def agency_user_required(view_func): """Decorator to restrict view to agency users only.""" return user_type_required(['agency'], login_url='/accounts/login/')(view_func) def candidate_user_required(view_func): """Decorator to restrict view to candidate users only.""" return user_type_required(['candidate'], login_url='/accounts/login/')(view_func) def staff_user_required(view_func): """Decorator to restrict view to staff users only.""" return user_type_required(['staff'])(view_func) def staff_or_agency_required(view_func): """Decorator to restrict view to staff and agency users.""" return user_type_required(['staff', 'agency'], login_url='/accounts/login/')(view_func) def staff_or_candidate_required(view_func): """Decorator to restrict view to staff and candidate users.""" return user_type_required(['staff', 'candidate'], login_url='/accounts/login/')(view_func) def is_superuser(user): return user.is_authenticated and user.is_superuser def superuser_required(view_func): return user_passes_test(is_superuser, login_url='/admin/login/?next=/', redirect_field_name=None)(view_func)