| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- """认证审计日志构造与独立失败事务。"""
- from __future__ import annotations
- from typing import Any
- from flask import request
- from dms.common.enums import AuditAction, AuditResult, AuditTarget
- from dms.common.request_context import get_request_id
- from dms.extensions import db
- from dms.models import AuditLog, User
- from dms.security.auth_context import get_auth_context
- def client_ip() -> str | None:
- forwarded = request.headers.get("X-Forwarded-For", "")
- value = forwarded.split(",", 1)[0].strip() if forwarded else request.remote_addr
- return value[:64] if value else None
- def auth_audit(
- *,
- action: AuditAction,
- result: AuditResult,
- user: User | None = None,
- attempted_username: str | None = None,
- failure_reason: str | None = None,
- detail: dict[str, Any] | None = None,
- ) -> AuditLog:
- username = user.username if user is not None else attempted_username
- return AuditLog(
- user_id=user.id if user is not None else None,
- username=username,
- real_name=user.real_name if user is not None else None,
- organization_id=user.organization_id if user is not None else None,
- organization_name=user.organization_name if user is not None else None,
- action_type=action.value,
- target_type=AuditTarget.AUTH.value,
- target_id=user.id if user is not None else None,
- target_name=username,
- operation_result=result.value,
- failure_reason=failure_reason,
- client_ip=client_ip(),
- user_agent=(request.user_agent.string or "")[:500] or None,
- request_id=get_request_id(),
- operation_detail=detail,
- )
- def business_audit(
- *,
- action: AuditAction,
- target: AuditTarget,
- target_id: int,
- target_name: str,
- detail: dict[str, Any] | None = None,
- ) -> AuditLog:
- """使用请求级认证快照构造修改类业务成功审计。"""
- context = get_auth_context()
- return AuditLog(
- user_id=context.user_id,
- username=context.username,
- real_name=context.real_name,
- organization_id=context.organization_id,
- organization_name=context.organization_name,
- action_type=action.value,
- target_type=target.value,
- target_id=target_id,
- target_name=target_name,
- operation_result=AuditResult.SUCCESS.value,
- failure_reason=None,
- client_ip=client_ip(),
- user_agent=(request.user_agent.string or "")[:500] or None,
- request_id=get_request_id(),
- operation_detail=detail,
- )
- def record_login_failure(
- *,
- user: User | None,
- attempted_username: str,
- failure_reason: str,
- ) -> None:
- """在登录主流程之外用短事务持久化失败审计。"""
- db.session.rollback()
- try:
- db.session.add(
- auth_audit(
- action=AuditAction.LOGIN,
- result=AuditResult.FAILURE,
- user=user,
- attempted_username=attempted_username,
- failure_reason=failure_reason,
- detail={"username": attempted_username},
- )
- )
- db.session.commit()
- except Exception:
- db.session.rollback()
- raise
|