feat: 添加 LDAP 认证支持

- 新增 LDAP 服务和 API 接口
- 添加 LDAP 配置管理页面
- 登录页面支持 LDAP/本地认证切换
- 数据库迁移支持 LDAP 相关字段
This commit is contained in:
fawney19
2026-01-06 14:38:42 +08:00
21 changed files with 3947 additions and 2037 deletions

View File

@@ -4,9 +4,9 @@ API端点请求/响应模型定义
import re
from datetime import datetime
from typing import Any, Dict, List, Optional
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, ConfigDict, Field, field_validator
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
from ..core.enums import UserRole
@@ -15,17 +15,9 @@ from ..core.enums import UserRole
class LoginRequest(BaseModel):
"""登录请求"""
email: str = Field(..., min_length=3, max_length=255, description="邮箱地址")
email: str = Field(..., min_length=1, max_length=255, description="邮箱/用户名")
password: str = Field(..., min_length=1, max_length=128, description="密码")
@classmethod
@field_validator("email")
def validate_email(cls, v):
"""验证邮箱格式"""
email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
if not re.match(email_pattern, v):
raise ValueError("邮箱格式无效")
return v.lower()
auth_type: Literal["local", "ldap"] = Field(default="local", description="认证类型")
@classmethod
@field_validator("password")
@@ -36,6 +28,24 @@ class LoginRequest(BaseModel):
raise ValueError("密码不能为空")
return v
@model_validator(mode="after")
def validate_login(self):
"""根据认证类型校验并规范化登录标识"""
identifier = self.email.strip()
if not identifier:
raise ValueError("用户名/邮箱不能为空")
# 本地和 LDAP 登录都支持用户名或邮箱
# 如果是邮箱格式,转换为小写
email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
if re.match(email_pattern, identifier):
self.email = identifier.lower()
else:
self.email = identifier
return self
class LoginResponse(BaseModel):
"""登录响应"""