mirror of
https://github.com/smittix/intercept.git
synced 2026-04-26 23:59:59 -07:00
75 lines
2.1 KiB
Python
75 lines
2.1 KiB
Python
"""Authorization helpers for role-based and arming-gated operations."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from functools import wraps
|
|
from typing import Any, Callable
|
|
|
|
from flask import jsonify, session
|
|
|
|
ROLE_LEVELS: dict[str, int] = {
|
|
'viewer': 10,
|
|
'analyst': 20,
|
|
'operator': 30,
|
|
'supervisor': 40,
|
|
'admin': 50,
|
|
}
|
|
|
|
|
|
def current_username() -> str:
|
|
"""Get current username from session."""
|
|
return str(session.get('username') or 'anonymous')
|
|
|
|
|
|
def current_role() -> str:
|
|
"""Get current role from session with safe default."""
|
|
role = str(session.get('role') or 'viewer').strip().lower()
|
|
return role if role in ROLE_LEVELS else 'viewer'
|
|
|
|
|
|
def has_role(required_role: str) -> bool:
|
|
"""Return True if current session role satisfies required role."""
|
|
required = ROLE_LEVELS.get(required_role, ROLE_LEVELS['admin'])
|
|
actual = ROLE_LEVELS.get(current_role(), ROLE_LEVELS['viewer'])
|
|
return actual >= required
|
|
|
|
|
|
def require_role(required_role: str) -> Callable:
|
|
"""Decorator enforcing minimum role."""
|
|
|
|
def decorator(func: Callable) -> Callable:
|
|
@wraps(func)
|
|
def wrapper(*args: Any, **kwargs: Any):
|
|
if not has_role(required_role):
|
|
return jsonify({
|
|
'status': 'error',
|
|
'message': f'{required_role} role required',
|
|
'required_role': required_role,
|
|
'current_role': current_role(),
|
|
}), 403
|
|
return func(*args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
return decorator
|
|
|
|
|
|
def require_armed(func: Callable) -> Callable:
|
|
"""Decorator enforcing armed state for active actions."""
|
|
|
|
@wraps(func)
|
|
def wrapper(*args: Any, **kwargs: Any):
|
|
from utils.drone import get_drone_ops_service
|
|
|
|
service = get_drone_ops_service()
|
|
policy = service.get_policy_state()
|
|
if not policy.get('armed'):
|
|
return jsonify({
|
|
'status': 'error',
|
|
'message': 'Action plane is not armed',
|
|
'policy': policy,
|
|
}), 403
|
|
return func(*args, **kwargs)
|
|
|
|
return wrapper
|