""" Authorization helpers for multi-event system Ensures users can only access events they are members of """ from fastapi import Depends, HTTPException, status from sqlalchemy.orm import Session from uuid import UUID import crud from database import get_db class AuthzError(HTTPException): """Authorization error""" def __init__(self, detail: str = "Not authorized"): super().__init__(status_code=status.HTTP_403_FORBIDDEN, detail=detail) async def verify_event_access( event_id: UUID, db: Session = Depends(get_db), current_user_id: UUID = Depends(lambda: None) ) -> dict: """ Verify that current user is a member of the event Returns: dict with event and member info Raises: HTTPException 403 if user is not a member """ # This is a helper - actual implementation depends on how you handle auth # You'll need to implement get_current_user_id() based on your auth system # (JWT, session cookies, etc.) event = crud.get_event(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") if not current_user_id: raise HTTPException(status_code=401, detail="Not authenticated") member = crud.get_event_member(db, event_id, current_user_id) if not member: raise AuthzError("You are not a member of this event") return { "event": event, "member": member, "role": member.role, "user_id": current_user_id } async def verify_event_admin( event_id: UUID, db: Session = Depends(get_db), current_user_id: UUID = Depends(lambda: None) ) -> dict: """ Verify that current user is an admin of the event Raises: HTTPException 403 if user is not admin """ authz = await verify_event_access(event_id, db, current_user_id) if authz["role"] not in ("admin",): raise AuthzError("Only event admins can perform this action") return authz async def verify_event_editor( event_id: UUID, db: Session = Depends(get_db), current_user_id: UUID = Depends(lambda: None) ) -> dict: """ Verify that current user is at least an editor of the event Raises: HTTPException 403 if user is not editor or admin """ authz = await verify_event_access(event_id, db, current_user_id) if authz["role"] not in ("admin", "editor"): raise AuthzError("Only event editors and admins can perform this action") return authz async def verify_guest_belongs_to_event( guest_id: UUID, event_id: UUID, db: Session = Depends(get_db) ) -> None: """ Verify that guest belongs to the specified event Raises: HTTPException 404 if guest doesn't belong to event """ guest = crud.get_guest(db, guest_id, event_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found in this event") # Role-based access control enum class Role: ADMIN = "admin" EDITOR = "editor" VIEWER = "viewer" @classmethod def is_admin(cls, role: str) -> bool: return role == cls.ADMIN @classmethod def is_editor(cls, role: str) -> bool: return role in (cls.ADMIN, cls.EDITOR) @classmethod def is_viewer(cls, role: str) -> bool: return role in (cls.ADMIN, cls.EDITOR, cls.VIEWER) # Permission definitions class Permission: """Define permissions for each role""" @staticmethod def can_edit_event(role: str) -> bool: """Can modify event details""" return Role.is_admin(role) @staticmethod def can_delete_event(role: str) -> bool: """Can delete event""" return Role.is_admin(role) @staticmethod def can_manage_members(role: str) -> bool: """Can add/remove members""" return Role.is_admin(role) @staticmethod def can_add_guests(role: str) -> bool: """Can add guests to event""" return Role.is_editor(role) @staticmethod def can_edit_guests(role: str) -> bool: """Can edit guest details""" return Role.is_editor(role) @staticmethod def can_delete_guests(role: str) -> bool: """Can delete guests""" return Role.is_admin(role) @staticmethod def can_import_guests(role: str) -> bool: """Can bulk import guests""" return Role.is_editor(role) @staticmethod def can_send_messages(role: str) -> bool: """Can send WhatsApp messages""" return Role.is_viewer(role) # All members can send @staticmethod def can_view_guests(role: str) -> bool: """Can view guests list""" return Role.is_viewer(role)