feat: implement PATCH /user/settings/{option} and fix timezone range to UTC-12~+14
- Add SettingOption StrEnum (nickname/language/timezone) for path param validation - Add UserSettingUpdateRequest DTO with Pydantic constraints - Implement endpoint: extract value by option name, validate non-null for required fields - Fix timezone upper bound from 12 to 14 (UTC+14 exists, e.g. Line Islands) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ from middleware.auth import auth_required
|
|||||||
from middleware.dependencies import SessionDep
|
from middleware.dependencies import SessionDep
|
||||||
from sqlmodels import (
|
from sqlmodels import (
|
||||||
BUILTIN_DEFAULT_COLORS, ThemePreset, UserThemeUpdateRequest,
|
BUILTIN_DEFAULT_COLORS, ThemePreset, UserThemeUpdateRequest,
|
||||||
|
SettingOption, UserSettingUpdateRequest,
|
||||||
)
|
)
|
||||||
from sqlmodels.color import ThemeColorsBase
|
from sqlmodels.color import ThemeColorsBase
|
||||||
from utils import JWT, Password, http_exceptions
|
from utils import JWT, Password, http_exceptions
|
||||||
@@ -209,21 +210,35 @@ async def router_user_settings_theme(
|
|||||||
@user_settings_router.patch(
|
@user_settings_router.patch(
|
||||||
path='/{option}',
|
path='/{option}',
|
||||||
summary='更新用户设定',
|
summary='更新用户设定',
|
||||||
description='Update user settings.',
|
status_code=status.HTTP_204_NO_CONTENT,
|
||||||
dependencies=[Depends(auth_required)],
|
|
||||||
status_code=204,
|
|
||||||
)
|
)
|
||||||
def router_user_settings_patch(option: str) -> None:
|
async def router_user_settings_patch(
|
||||||
|
session: SessionDep,
|
||||||
|
user: Annotated[sqlmodels.user.User, Depends(auth_required)],
|
||||||
|
option: SettingOption,
|
||||||
|
request: UserSettingUpdateRequest,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Update user settings.
|
更新单个用户设置项
|
||||||
|
|
||||||
Args:
|
路径参数:
|
||||||
option (str): The setting option to update.
|
- option: 设置项名称(nickname / language / timezone)
|
||||||
|
|
||||||
Returns:
|
请求体:
|
||||||
dict: A dictionary containing the result of the settings update.
|
- 包含与 option 同名的字段及其新值
|
||||||
|
|
||||||
|
错误处理:
|
||||||
|
- 422: 无效的 option 或字段值不符合约束
|
||||||
|
- 400: 必填字段值缺失
|
||||||
"""
|
"""
|
||||||
http_exceptions.raise_not_implemented()
|
value = getattr(request, option.value)
|
||||||
|
|
||||||
|
# language / timezone 不允许设为 null
|
||||||
|
if value is None and option != SettingOption.NICKNAME:
|
||||||
|
http_exceptions.raise_bad_request(f"设置项 {option.value} 不允许为空")
|
||||||
|
|
||||||
|
setattr(user, option.value, value)
|
||||||
|
await user.save(session)
|
||||||
|
|
||||||
|
|
||||||
@user_settings_router.get(
|
@user_settings_router.get(
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ from .user import (
|
|||||||
UserResponse,
|
UserResponse,
|
||||||
UserSettingResponse,
|
UserSettingResponse,
|
||||||
UserThemeUpdateRequest,
|
UserThemeUpdateRequest,
|
||||||
|
SettingOption,
|
||||||
|
UserSettingUpdateRequest,
|
||||||
WebAuthnInfo,
|
WebAuthnInfo,
|
||||||
UserTwoFactorResponse,
|
UserTwoFactorResponse,
|
||||||
# 管理员DTO
|
# 管理员DTO
|
||||||
|
|||||||
@@ -308,6 +308,32 @@ class UserThemeUpdateRequest(SQLModelBase):
|
|||||||
"""颜色配置"""
|
"""颜色配置"""
|
||||||
|
|
||||||
|
|
||||||
|
class SettingOption(StrEnum):
|
||||||
|
"""用户可自助修改的设置选项"""
|
||||||
|
|
||||||
|
NICKNAME = "nickname"
|
||||||
|
"""昵称"""
|
||||||
|
|
||||||
|
LANGUAGE = "language"
|
||||||
|
"""语言偏好"""
|
||||||
|
|
||||||
|
TIMEZONE = "timezone"
|
||||||
|
"""时区"""
|
||||||
|
|
||||||
|
|
||||||
|
class UserSettingUpdateRequest(SQLModelBase):
|
||||||
|
"""用户设置更新请求 DTO,根据 option 路径参数仅使用对应字段"""
|
||||||
|
|
||||||
|
nickname: str | None = Field(default=None, max_length=50)
|
||||||
|
"""昵称(传 null 可清除)"""
|
||||||
|
|
||||||
|
language: str | None = Field(default=None, max_length=5)
|
||||||
|
"""语言偏好"""
|
||||||
|
|
||||||
|
timezone: int | None = Field(default=None, ge=-12, le=14)
|
||||||
|
"""时区,UTC 偏移小时数"""
|
||||||
|
|
||||||
|
|
||||||
class UserTwoFactorResponse(SQLModelBase):
|
class UserTwoFactorResponse(SQLModelBase):
|
||||||
"""用户两步验证信息 DTO"""
|
"""用户两步验证信息 DTO"""
|
||||||
|
|
||||||
@@ -474,7 +500,7 @@ class User(UserBase, UUIDTableBaseMixin):
|
|||||||
language: str = Field(default="zh-CN", max_length=5)
|
language: str = Field(default="zh-CN", max_length=5)
|
||||||
"""语言偏好"""
|
"""语言偏好"""
|
||||||
|
|
||||||
timezone: int = Field(default=8, ge=-12, le=12)
|
timezone: int = Field(default=8, ge=-12, le=14)
|
||||||
"""时区,UTC 偏移小时数"""
|
"""时区,UTC 偏移小时数"""
|
||||||
|
|
||||||
# 外键
|
# 外键
|
||||||
|
|||||||
Reference in New Issue
Block a user