""" Custom RBAC Permission Classes Admin → full access to everything Caregiver → read own profile, manage own bookings User → manage own pets/bookings, read caregivers """ from rest_framework.permissions import BasePermission, SAFE_METHODS from api.models import Role class IsAdmin(BasePermission): """Only platform admins (role=admin OR is_staff).""" message = 'Admin access required.' def has_permission(self, request, view): return ( request.user and request.user.is_authenticated and (request.user.role == Role.ADMIN or request.user.is_staff) ) class IsCaregiver(BasePermission): """Only caregivers.""" message = 'Caregiver account required.' def has_permission(self, request, view): return ( request.user and request.user.is_authenticated and request.user.role == Role.CAREGIVER ) class IsAdminOrReadOnly(BasePermission): """ GET/HEAD/OPTIONS → any authenticated user. Mutations (POST/PUT/PATCH/DELETE) → admin only. Used on /caregivers/ endpoint. """ message = 'Write access requires admin privileges.' def has_permission(self, request, view): if not request.user or not request.user.is_authenticated: return False if request.method in SAFE_METHODS: return True return request.user.role == Role.ADMIN or request.user.is_staff class IsOwnerOrAdmin(BasePermission): """ Object-level: owner or admin can access. Works for Pet, Booking, Conversation objects. """ message = 'You do not have permission to access this resource.' def has_object_permission(self, request, view, obj): if request.user.role == Role.ADMIN or request.user.is_staff: return True # Support objects with either .user or .owner attribute owner = getattr(obj, 'user', None) or getattr(obj, 'owner', None) return owner == request.user class IsParticipantOrAdmin(BasePermission): """For Conversation / Message objects.""" message = 'You are not a participant in this conversation.' def has_object_permission(self, request, view, obj): if request.user.role == Role.ADMIN or request.user.is_staff: return True # obj is a Conversation conversation = getattr(obj, 'conversation', obj) return request.user in conversation.participants.all() class IsCaregiverOwnerOrAdmin(BasePermission): """Caregiver can update their own profile; admin can update any.""" message = 'You can only manage your own caregiver profile.' def has_object_permission(self, request, view, obj): if request.user.role == Role.ADMIN or request.user.is_staff: return True if request.method in SAFE_METHODS: return True return obj.user == request.user