2026-10-10 04:28:04 -04:00
|
|
|
|
"""日志查询编排。
|
|
|
|
|
|
|
|
|
|
|
|
操作日志与登录日志分别提供分页查询(两表字段与筛选项不同),操作日志另有
|
|
|
|
|
|
单条详情(列表为性能排除的 `request_data` 走详情按需加载)。
|
|
|
|
|
|
纯只读操作,不写审计 —— 读操作记日志只会淹没审计表。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
|
|
|
|
|
|
from app.core.exceptions import NotFoundError
|
|
|
|
|
|
from app.core.response import PageResult
|
|
|
|
|
|
from app.repositories import login_log_repository, operation_log_repository
|
|
|
|
|
|
from app.repositories.query_utils import LogFilters
|
|
|
|
|
|
from app.schemas.log import (
|
|
|
|
|
|
LoginLogOut,
|
|
|
|
|
|
LoginLogQuery,
|
|
|
|
|
|
OperationLogDetailOut,
|
|
|
|
|
|
OperationLogOut,
|
|
|
|
|
|
OperationLogQuery,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def list_operation_logs(session: Session, query: OperationLogQuery) -> PageResult[OperationLogOut]:
|
|
|
|
|
|
"""分页查询操作日志(列表不含 request_data,详情走 `get_operation_log`)。"""
|
2026-10-22 07:43:20 -04:00
|
|
|
|
repo_query = operation_log_repository.OperationLogListQuery(
|
|
|
|
|
|
filters=_filters_from(query),
|
2026-10-10 04:28:04 -04:00
|
|
|
|
offset=query.offset,
|
|
|
|
|
|
limit=query.page_size,
|
|
|
|
|
|
module=query.module,
|
|
|
|
|
|
action=query.action,
|
|
|
|
|
|
)
|
2026-10-22 07:43:20 -04:00
|
|
|
|
logs = operation_log_repository.list_logs(session, repo_query)
|
|
|
|
|
|
total = operation_log_repository.count_logs(session, repo_query)
|
2026-10-10 04:28:04 -04:00
|
|
|
|
return PageResult[OperationLogOut](
|
|
|
|
|
|
records=[OperationLogOut.model_validate(log) for log in logs],
|
|
|
|
|
|
total=total,
|
|
|
|
|
|
page_num=query.page_num,
|
|
|
|
|
|
page_size=query.page_size,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_operation_log(session: Session, log_id: int) -> OperationLogDetailOut:
|
|
|
|
|
|
"""查询单条操作日志详情(含已脱敏的 request_data)。
|
|
|
|
|
|
|
|
|
|
|
|
:raises NotFoundError: 日志不存在
|
|
|
|
|
|
"""
|
|
|
|
|
|
log = operation_log_repository.get_by_id(session, log_id)
|
|
|
|
|
|
if log is None:
|
|
|
|
|
|
raise NotFoundError("日志不存在")
|
|
|
|
|
|
return OperationLogDetailOut.model_validate(log)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def list_login_logs(session: Session, query: LoginLogQuery) -> PageResult[LoginLogOut]:
|
|
|
|
|
|
"""分页查询登录日志。"""
|
2026-10-22 07:43:20 -04:00
|
|
|
|
repo_query = login_log_repository.LoginLogListQuery(
|
|
|
|
|
|
filters=_filters_from(query),
|
2026-10-10 04:28:04 -04:00
|
|
|
|
offset=query.offset,
|
|
|
|
|
|
limit=query.page_size,
|
|
|
|
|
|
ip=query.ip,
|
|
|
|
|
|
)
|
2026-10-22 07:43:20 -04:00
|
|
|
|
logs = login_log_repository.list_logs(session, repo_query)
|
|
|
|
|
|
total = login_log_repository.count_logs(session, repo_query)
|
2026-10-10 04:28:04 -04:00
|
|
|
|
return PageResult[LoginLogOut](
|
|
|
|
|
|
records=[LoginLogOut.model_validate(log) for log in logs],
|
|
|
|
|
|
total=total,
|
|
|
|
|
|
page_num=query.page_num,
|
|
|
|
|
|
page_size=query.page_size,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _filters_from(query: OperationLogQuery | LoginLogQuery) -> LogFilters:
|
|
|
|
|
|
"""两类 Query 的公共筛选字段 → LogFilters(口径与 repository 共用一个实现)。"""
|
|
|
|
|
|
return LogFilters(
|
|
|
|
|
|
username=query.username,
|
|
|
|
|
|
success=query.success,
|
|
|
|
|
|
start_time=query.start_time,
|
|
|
|
|
|
end_time=query.end_time,
|
|
|
|
|
|
)
|