You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
orquestrador/admin_app/services/audit_service.py

206 lines
6.7 KiB
Python

from enum import Enum
from admin_app.db.models import AuditLog
from admin_app.repositories import AuditLogRepository
class AdminAuditEventType(str, Enum):
STAFF_LOGIN_SUCCEEDED = "staff.login.succeeded"
STAFF_LOGIN_FAILED = "staff.login.failed"
STAFF_LOGOUT_SUCCEEDED = "staff.logout.succeeded"
STAFF_ACCOUNT_CREATED = "staff.account.created"
STAFF_ACCOUNT_STATUS_UPDATED = "staff.account.status.updated"
TOOL_APPROVAL_RECORDED = "tool.approval.recorded"
TOOL_PUBLICATION_RECORDED = "tool.publication.recorded"
class AdminAuditOutcome(str, Enum):
SUCCESS = "success"
FAILED = "failed"
class AuditService:
def __init__(self, repository: AuditLogRepository):
self.repository = repository
def record_event(
self,
*,
actor_staff_account_id: int | None,
event_type: AdminAuditEventType,
resource_type: str,
resource_id: str | None,
outcome: AdminAuditOutcome,
message: str | None,
payload_json: dict | None,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.repository.create(
actor_staff_account_id=actor_staff_account_id,
event_type=event_type.value,
resource_type=resource_type,
resource_id=resource_id,
outcome=outcome.value,
message=message,
payload_json=payload_json,
ip_address=ip_address,
user_agent=user_agent,
)
def record_login_succeeded(
self,
*,
actor_staff_account_id: int,
session_id: int,
email: str,
role: str,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.record_event(
actor_staff_account_id=actor_staff_account_id,
event_type=AdminAuditEventType.STAFF_LOGIN_SUCCEEDED,
resource_type="staff_account",
resource_id=str(actor_staff_account_id),
outcome=AdminAuditOutcome.SUCCESS,
message="Login administrativo concluido.",
payload_json={"session_id": session_id, "email": email, "role": role},
ip_address=ip_address,
user_agent=user_agent,
)
def record_login_failed(
self,
*,
email: str,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.record_event(
actor_staff_account_id=None,
event_type=AdminAuditEventType.STAFF_LOGIN_FAILED,
resource_type="staff_account",
resource_id=email,
outcome=AdminAuditOutcome.FAILED,
message="Tentativa de login administrativo falhou.",
payload_json={"email": email},
ip_address=ip_address,
user_agent=user_agent,
)
def record_logout_succeeded(
self,
*,
actor_staff_account_id: int,
session_id: int,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.record_event(
actor_staff_account_id=actor_staff_account_id,
event_type=AdminAuditEventType.STAFF_LOGOUT_SUCCEEDED,
resource_type="staff_session",
resource_id=str(session_id),
outcome=AdminAuditOutcome.SUCCESS,
message="Sessao administrativa encerrada.",
payload_json={"session_id": session_id},
ip_address=ip_address,
user_agent=user_agent,
)
def record_staff_account_created(
self,
*,
actor_staff_account_id: int,
created_staff_account_id: int,
email: str,
role: str,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.record_event(
actor_staff_account_id=actor_staff_account_id,
event_type=AdminAuditEventType.STAFF_ACCOUNT_CREATED,
resource_type="staff_account",
resource_id=str(created_staff_account_id),
outcome=AdminAuditOutcome.SUCCESS,
message="Conta administrativa de colaborador criada.",
payload_json={
"created_staff_account_id": created_staff_account_id,
"email": email,
"role": role,
},
ip_address=ip_address,
user_agent=user_agent,
)
def record_staff_account_status_updated(
self,
*,
actor_staff_account_id: int,
target_staff_account_id: int,
is_active: bool,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.record_event(
actor_staff_account_id=actor_staff_account_id,
event_type=AdminAuditEventType.STAFF_ACCOUNT_STATUS_UPDATED,
resource_type="staff_account",
resource_id=str(target_staff_account_id),
outcome=AdminAuditOutcome.SUCCESS,
message="Status de colaborador administrativo atualizado.",
payload_json={
"target_staff_account_id": target_staff_account_id,
"is_active": is_active,
},
ip_address=ip_address,
user_agent=user_agent,
)
def record_tool_approval(
self,
*,
actor_staff_account_id: int,
tool_name: str,
tool_version: int,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.record_event(
actor_staff_account_id=actor_staff_account_id,
event_type=AdminAuditEventType.TOOL_APPROVAL_RECORDED,
resource_type="tool_publication",
resource_id=tool_name,
outcome=AdminAuditOutcome.SUCCESS,
message="Aprovacao de tool registrada.",
payload_json={"tool_name": tool_name, "tool_version": tool_version},
ip_address=ip_address,
user_agent=user_agent,
)
def record_tool_publication(
self,
*,
actor_staff_account_id: int,
tool_name: str,
tool_version: int,
ip_address: str | None,
user_agent: str | None,
) -> AuditLog:
return self.record_event(
actor_staff_account_id=actor_staff_account_id,
event_type=AdminAuditEventType.TOOL_PUBLICATION_RECORDED,
resource_type="tool_publication",
resource_id=tool_name,
outcome=AdminAuditOutcome.SUCCESS,
message="Publicacao de tool registrada.",
payload_json={"tool_name": tool_name, "tool_version": tool_version},
ip_address=ip_address,
user_agent=user_agent,
)
def list_recent(self, limit: int = 50) -> list[AuditLog]:
return self.repository.list_recent(limit=limit)