""" Authentication and Authorization JWT-based auth with role-based access control """ from datetime import datetime, timedelta from typing import Optional, Dict, List from enum import Enum import jwt from fastapi import HTTPException, Security from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials class UserRole(str, Enum): """User roles""" ADMIN = "admin" MUNICIPALITY = "municipality" PROPERTY_OWNER = "property_owner" INFRASTRUCTURE_OWNER = "infrastructure_owner" INSURANCE = "insurance" BANK = "bank" RETAIL = "retail" ZOOMER = "zoomer" READONLY = "readonly" class Permission(str, Enum): """Permissions""" READ_OBSERVATIONS = "read:observations" WRITE_OBSERVATIONS = "write:observations" READ_ANALYTICS = "read:analytics" WRITE_ANALYTICS = "write:analytics" READ_DECISIONS = "read:decisions" WRITE_DECISIONS = "write:decisions" READ_ADMIN = "read:admin" WRITE_ADMIN = "write:admin" MANAGE_USERS = "manage:users" MANAGE_SYSTEM = "manage:system" # Role permissions mapping ROLE_PERMISSIONS = { UserRole.ADMIN: [p for p in Permission], UserRole.MUNICIPALITY: [ Permission.READ_OBSERVATIONS, Permission.WRITE_OBSERVATIONS, Permission.READ_ANALYTICS, Permission.READ_DECISIONS, Permission.WRITE_DECISIONS ], UserRole.PROPERTY_OWNER: [ Permission.READ_OBSERVATIONS, Permission.READ_ANALYTICS, Permission.READ_DECISIONS ], UserRole.INFRASTRUCTURE_OWNER: [ Permission.READ_OBSERVATIONS, Permission.WRITE_OBSERVATIONS, Permission.READ_ANALYTICS, Permission.READ_DECISIONS, Permission.WRITE_DECISIONS ], UserRole.INSURANCE: [ Permission.READ_OBSERVATIONS, Permission.READ_ANALYTICS, Permission.READ_DECISIONS ], UserRole.BANK: [ Permission.READ_OBSERVATIONS, Permission.READ_ANALYTICS, Permission.READ_DECISIONS ], UserRole.RETAIL: [ Permission.READ_OBSERVATIONS, Permission.READ_ANALYTICS, Permission.READ_DECISIONS ], UserRole.ZOOMER: [ Permission.READ_OBSERVATIONS, Permission.WRITE_OBSERVATIONS ], UserRole.READONLY: [ Permission.READ_OBSERVATIONS, Permission.READ_ANALYTICS ] } class AuthManager: """Authentication and authorization manager""" def __init__(self, secret_key: str, algorithm: str = "HS256"): self.secret_key = secret_key self.algorithm = algorithm self.security = HTTPBearer() def create_token(self, user_id: str, role: UserRole, expires_hours: int = 24) -> str: """Create JWT token""" payload = { "sub": user_id, "role": role.value, "permissions": [p.value for p in ROLE_PERMISSIONS[role]], "iat": datetime.utcnow(), "exp": datetime.utcnow() + timedelta(hours=expires_hours) } return jwt.encode(payload, self.secret_key, algorithm=self.algorithm) def verify_token(self, token: str) -> Dict: """Verify JWT token""" try: payload = jwt.decode(token, self.secret_key, algorithms=[self.algorithm]) return payload except jwt.ExpiredSignatureError: raise HTTPException(status_code=401, detail="Token expired") except jwt.InvalidTokenError: raise HTTPException(status_code=401, detail="Invalid token") def get_current_user(self, credentials: HTTPAuthorizationCredentials = Security(HTTPBearer())): """Get current user from token""" token = credentials.credentials return self.verify_token(token) def require_permission(self, permission: Permission): """Require specific permission""" def checker(credentials: HTTPAuthorizationCredentials = Security(HTTPBearer())): token = credentials.credentials payload = self.verify_token(token) user_permissions = payload.get("permissions", []) if permission.value not in user_permissions: raise HTTPException( status_code=403, detail=f"Permission denied: {permission.value}" ) return payload return checker def has_permission(self, user_payload: Dict, permission: Permission) -> bool: """Check if user has permission""" user_permissions = user_payload.get("permissions", []) return permission.value in user_permissions # Initialize auth manager import os auth_manager = AuthManager( secret_key=os.getenv("JWT_SECRET", "iom_jwt_secret") )