Files
beige/backend/app/api/v1/users.py
yangqianqian df1856d793 上线版: 产品表单统一+form嵌套修复+用户管理+部署+三套叙事
- 产品编辑入口统一走 ProductFormFull(卖点/风格/人群/品牌词全字段);
  修复开任务页 <form> 套 <form> 致"编辑产品"报错、改不了、跳回首个产品
- dashboard 入口卡片对齐实际路由: 系统管理(/config) 与 工作配置(/settings) 分开;
  settings ?tab=products 直达改用挂载后读 URL, 消除 hydration mismatch
- 新增用户管理(users API/admin service/改密页) + alembic 022/023/024
- 上线部署: Dockerfile / docker-compose.prod+https / nginx https / .env.example
- A8 三套正交叙事(痛点/场景/成分背书) + beige 调色去AI化 + 飞轮 text_import 高权重信号

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:08:13 +08:00

84 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
app/api/v1/users.py — 管理员账号管理路由
全部挂 require_admin路由层只做参数校验→调 service→格式化响应。
禁用=软删除可恢复(倩倩姐2026-06-30);不物理删除。
"""
from typing import Annotated
from fastapi import APIRouter, Depends
from pydantic import BaseModel, field_validator
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.response import ok
from app.middleware.workspace_guard import CurrentUser, require_admin
from app.services import user_admin_service as svc
router = APIRouter(prefix="/users", tags=["users"])
class CreateUserRequest(BaseModel):
username: str
email: str
role: str
init_password: str
@field_validator("username", "email", "role", "init_password")
@classmethod
def not_empty(cls, v: str) -> str:
if not v or not v.strip():
raise ValueError("不能为空")
return v
class SetActiveRequest(BaseModel):
is_active: bool
@router.get("")
def list_users(
current_user: Annotated[CurrentUser, Depends(require_admin)],
db: Session = Depends(get_db),
):
"""列出本 workspace 成员(含已禁用)。"""
return ok(svc.list_workspace_users(db, current_user.workspace_id))
@router.post("")
def create_user(
body: CreateUserRequest,
current_user: Annotated[CurrentUser, Depends(require_admin)],
db: Session = Depends(get_db),
):
"""建号,强制首登改密。"""
return ok(svc.create_workspace_user(
db, current_user.workspace_id,
body.username, body.email, body.role, body.init_password,
))
@router.post("/{user_id}/active")
def set_active(
user_id: int,
body: SetActiveRequest,
current_user: Annotated[CurrentUser, Depends(require_admin)],
db: Session = Depends(get_db),
):
"""启用/禁用账号(软删除,可随时恢复)。"""
return ok(svc.set_user_active(
db, current_user.workspace_id, user_id, body.is_active, current_user.user_id,
))
@router.delete("/{user_id}")
def delete_user(
user_id: int,
current_user: Annotated[CurrentUser, Depends(require_admin)],
db: Session = Depends(get_db),
):
"""物理删除账号(不可恢复,与禁用区分)。"""
return ok(svc.delete_workspace_user(
db, current_user.workspace_id, user_id, current_user.user_id,
))