后端 FastAPI 六层结构(api/services/repositories/models/schemas/core), 统一响应信封、全局异常、日志脱敏;6 张表经 Alembic 迁移建库,SQL 留存 db/migration;登录鉴权含图形验证码(Redis GETDEL 防重放)、JWT、登录限流、 登出黑名单(TTL=令牌剩余有效期)、登录日志。 前端 Vue3 + TS + Element Plus 骨架,含登录页、路由守卫、请求封装与 Vite 代理。 工程配置:uv 锁定 Python 3.12、ruff 检查与格式化、editorconfig、gitattributes。 测试 184 项(单元 155 / 集成 29)全绿,浏览器端到端 8 项通过。 Co-Authored-By: Claude Code <noreply@anthropic.com>
39 lines
1015 B
Python
39 lines
1015 B
Python
"""登录日志数据访问。"""
|
||
|
||
from sqlalchemy.orm import Session
|
||
|
||
from app.models import LoginLog
|
||
|
||
# user_agent 列宽,超长需截断否则插入报错
|
||
_USER_AGENT_MAX_LEN = 255
|
||
|
||
|
||
def add(
|
||
session: Session,
|
||
*,
|
||
user_id: int | None,
|
||
username: str,
|
||
ip: str | None,
|
||
user_agent: str | None,
|
||
success: bool,
|
||
fail_reason: str | None = None,
|
||
) -> None:
|
||
"""写入一条登录日志。只 flush 不 commit。
|
||
|
||
**绝不记录密码** —— 明文与哈希都不写。日志是最容易泄漏凭据的地方。
|
||
|
||
:param user_id: 账号不存在时传 None(列本身可空)
|
||
:param username: 用户名原样记录,便于账号不存在时也能追溯
|
||
"""
|
||
session.add(
|
||
LoginLog(
|
||
user_id=user_id,
|
||
username=username,
|
||
ip=ip,
|
||
user_agent=user_agent[:_USER_AGENT_MAX_LEN] if user_agent else None,
|
||
success=1 if success else 0,
|
||
fail_reason=fail_reason,
|
||
)
|
||
)
|
||
session.flush()
|