update. 完善用户相关增删改查接口以及Schema模型
This commit is contained in:
+38
-29
@@ -1,60 +1,71 @@
|
||||
# api/departments.py
|
||||
from typing import List
|
||||
|
||||
from django.db import IntegrityError
|
||||
from django.shortcuts import get_object_or_404
|
||||
from ninja import Router
|
||||
from ninja.errors import HttpError
|
||||
|
||||
from users.models import Department
|
||||
from users.permission import has_permission
|
||||
from users.permission import has_permission, require_permissions
|
||||
from users.schema import DepartmentOut, DepartmentCreate, DepartmentUpdate
|
||||
|
||||
router = Router(tags=['depts'])
|
||||
|
||||
|
||||
@router.post("/", response=DepartmentOut, summary="创建部门")
|
||||
def create_department(request, payload: DepartmentCreate):
|
||||
if not has_permission(request.auth.id, "dept:create"):
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
data = payload.dict()
|
||||
parent_id = data.pop('parent_id', None)
|
||||
if parent_id:
|
||||
data['parent_id'] = parent_id
|
||||
|
||||
dept = Department.objects.create(**data)
|
||||
return dept
|
||||
|
||||
|
||||
@router.get("/", response=List[DepartmentOut], summary="获取部门列表(扁平)")
|
||||
@require_permissions("dept:list")
|
||||
def list_departments(request):
|
||||
if not has_permission(request.auth.id, "dept:list"):
|
||||
raise HttpError(403, "权限不足")
|
||||
return Department.objects.all()
|
||||
|
||||
|
||||
@router.get("/tree/", response=List[dict], summary="获取部门树形结构")
|
||||
@require_permissions("dept:list")
|
||||
def get_department_tree(request):
|
||||
if not has_permission(request.auth.id, "dept:list"):
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
depts = Department.objects.all().order_by('order')
|
||||
return build_dept_tree(list(depts))
|
||||
|
||||
|
||||
@router.get("/{dept_id}/", response=DepartmentOut, summary="获取部门详情")
|
||||
def get_department(request, dept_id: int):
|
||||
if not has_permission(request.auth.id, "dept:view"):
|
||||
@router.post("/", response=DepartmentOut, summary="创建部门")
|
||||
@require_permissions("dept:create")
|
||||
def create_department(request, payload: DepartmentCreate):
|
||||
if not has_permission(request.auth.id, "dept:create"):
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
# 👇 新增:校验根部门唯一性
|
||||
if payload.parent_id is None:
|
||||
if Department.objects.filter(parent__isnull=True).exists():
|
||||
raise HttpError(400, "根部门已存在,无法创建新的根部门")
|
||||
|
||||
data = payload.dict()
|
||||
parent_id = data.pop('parent_id', None)
|
||||
if parent_id:
|
||||
# 可以额外校验 parent_id 是否真实存在
|
||||
if not Department.objects.filter(id=parent_id).exists():
|
||||
raise HttpError(400, "指定的上级部门不存在")
|
||||
data['parent_id'] = parent_id
|
||||
|
||||
try:
|
||||
dept = Department.objects.create(**data)
|
||||
return dept
|
||||
except IntegrityError as e:
|
||||
# 捕获数据库层面的唯一性冲突,提供统一错误信息
|
||||
if "unique_root_department" in str(e):
|
||||
raise HttpError(400, "根部门已存在,无法创建新的根部门")
|
||||
else:
|
||||
raise HttpError(400, "创建部门失败,请检查数据")
|
||||
|
||||
|
||||
@router.get("/{dept_id}/", response=DepartmentOut, summary="获取部门详情")
|
||||
@require_permissions("dept:view")
|
||||
def get_department(request, dept_id: int):
|
||||
dept = get_object_or_404(Department, id=dept_id)
|
||||
return dept
|
||||
|
||||
|
||||
@router.put("/{dept_id}/", response=DepartmentOut, summary="更新部门")
|
||||
@require_permissions("dept:update")
|
||||
def update_department(request, dept_id: int, payload: DepartmentUpdate):
|
||||
if not has_permission(request.auth.id, "dept:update"):
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
dept = get_object_or_404(Department, id=dept_id)
|
||||
data = payload.dict()
|
||||
parent_id = data.pop('parent_id', None)
|
||||
@@ -70,10 +81,8 @@ def update_department(request, dept_id: int, payload: DepartmentUpdate):
|
||||
|
||||
|
||||
@router.delete("/{dept_id}/", summary="删除部门")
|
||||
@require_permissions("dept:delete")
|
||||
def delete_department(request, dept_id: int):
|
||||
if not has_permission(request.auth.id, "dept:delete"):
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
dept = get_object_or_404(Department, id=dept_id)
|
||||
# 可选:检查是否有子部门或用户
|
||||
if dept.user_set.exists() or Department.objects.filter(parent=dept).exists():
|
||||
|
||||
+16
-24
@@ -1,23 +1,29 @@
|
||||
# api/menus.py
|
||||
from typing import List
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from loguru import logger
|
||||
from ninja import Router
|
||||
from ninja.errors import HttpError
|
||||
|
||||
from users.models import Menu
|
||||
from users.permission import has_permission
|
||||
from users.permission import require_permissions
|
||||
from users.schema import MenuOut, MenuCreate, MenuUpdate
|
||||
|
||||
router = Router(tags=['menus'])
|
||||
|
||||
|
||||
@router.post("/", response=MenuOut, summary="创建菜单")
|
||||
def create_menu(request, payload: MenuCreate):
|
||||
if not has_permission(request.auth.id, "menu:create"):
|
||||
raise HttpError(403, "权限不足")
|
||||
@router.get("/", response=List[MenuOut], summary="获取菜单列表")
|
||||
@require_permissions("menu:list")
|
||||
def list_menus(request):
|
||||
menus = Menu.objects.all()
|
||||
logger.info(menus)
|
||||
permissions = [m.permission_code for m in menus]
|
||||
logger.info(permissions)
|
||||
return menus
|
||||
|
||||
|
||||
@router.post("/", response=MenuOut, summary="创建菜单")
|
||||
@require_permissions("menu:create")
|
||||
def create_menu(request, payload: MenuCreate):
|
||||
data = payload.dict()
|
||||
parent_id = data.pop('parent_id', None)
|
||||
if parent_id:
|
||||
@@ -27,29 +33,16 @@ def create_menu(request, payload: MenuCreate):
|
||||
return menu
|
||||
|
||||
|
||||
@router.get("/", response=List[MenuOut], summary="获取菜单列表")
|
||||
def list_menus(request):
|
||||
if not has_permission(request.auth.id, "menu:list"):
|
||||
raise HttpError(403, "权限不足")
|
||||
menus = Menu.objects.all()
|
||||
logger.info(menus)
|
||||
permissions = [m.permission_code for m in menus]
|
||||
logger.info(permissions)
|
||||
return menus
|
||||
|
||||
|
||||
@router.get("/{menu_id}/", response=MenuOut, summary="获取菜单详情")
|
||||
@require_permissions("menu:view")
|
||||
def get_menu(request, menu_id: int):
|
||||
if not has_permission(request.auth.id, "menu:view"):
|
||||
raise HttpError(403, "权限不足")
|
||||
menu = get_object_or_404(Menu, id=menu_id)
|
||||
return menu
|
||||
|
||||
|
||||
@router.put("/{menu_id}/", response=MenuOut, summary="更新菜单")
|
||||
@require_permissions("menu:update")
|
||||
def update_menu(request, menu_id: int, payload: MenuUpdate):
|
||||
# if not has_permission(request.auth.id, "menu:update"):
|
||||
# raise HttpError(403, "权限不足")
|
||||
logger.debug(payload)
|
||||
menu = get_object_or_404(Menu, id=menu_id)
|
||||
data = payload.dict()
|
||||
@@ -67,9 +60,8 @@ def update_menu(request, menu_id: int, payload: MenuUpdate):
|
||||
|
||||
|
||||
@router.delete("/{menu_id}/", summary="删除菜单")
|
||||
@require_permissions("menu:delete")
|
||||
def delete_menu(request, menu_id: int):
|
||||
if not has_permission(request.auth.id, "menu:delete"):
|
||||
raise HttpError(403, "权限不足")
|
||||
menu = get_object_or_404(Menu, id=menu_id)
|
||||
menu.delete()
|
||||
return {"success": True}
|
||||
|
||||
@@ -33,9 +33,22 @@ class Department(BaseEntity):
|
||||
verbose_name = "部门"
|
||||
verbose_name_plural = "部门管理"
|
||||
|
||||
# 👇 核心:添加部分唯一约束
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['parent'],
|
||||
condition=models.Q(parent__isnull=True),
|
||||
name='unique_root_department'
|
||||
)
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def is_root(self):
|
||||
return self.parent is None
|
||||
|
||||
|
||||
class User(AbstractUser, PermissionsMixin, BaseEntity):
|
||||
username = models.CharField("英文名/账号", max_length=30, unique=True)
|
||||
|
||||
@@ -2,8 +2,63 @@ from typing import List
|
||||
|
||||
from django.core.cache import cache
|
||||
from loguru import logger
|
||||
from ninja.errors import HttpError
|
||||
|
||||
from users.models import User, Menu # 替换为你的实际 app 名
|
||||
from functools import wraps
|
||||
import asyncio
|
||||
from asgiref.sync import sync_to_async
|
||||
|
||||
|
||||
# 你的权限检查函数(不变)
|
||||
def has_permission(user_id: int, permission: str) -> bool:
|
||||
# 你原来的逻辑
|
||||
return True
|
||||
|
||||
|
||||
# ====================== 多权限通用装饰器 ======================
|
||||
def require_permissions(*perms: str, match_all: bool = True):
|
||||
"""
|
||||
多权限检查装饰器
|
||||
:param perms: 权限字符串,可传多个
|
||||
:param match_all: True = 必须拥有所有权限(AND),False = 拥有任意一个即可(OR)
|
||||
用法:
|
||||
@require_permissions("role:update", "role:delete") # 两个都要有
|
||||
@require_permissions("role:view", "role:list", match_all=False) # 有一个就行
|
||||
"""
|
||||
|
||||
def decorator(view_func):
|
||||
@wraps(view_func)
|
||||
async def async_wrapper(request, *args, **kwargs):
|
||||
user_id = request.auth.id
|
||||
check = sync_to_async(has_permission)
|
||||
|
||||
# 检查所有权限
|
||||
results = [await check(user_id, perm) for perm in perms]
|
||||
allowed = all(results) if match_all else any(results)
|
||||
|
||||
if not allowed:
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
return await view_func(request, *args, **kwargs)
|
||||
|
||||
@wraps(view_func)
|
||||
def sync_wrapper(request, *args, **kwargs):
|
||||
user_id = request.auth.id
|
||||
results = [has_permission(user_id, perm) for perm in perms]
|
||||
allowed = all(results) if match_all else any(results)
|
||||
|
||||
if not allowed:
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
# 自动识别同步/异步
|
||||
if asyncio.iscoroutinefunction(view_func):
|
||||
return async_wrapper
|
||||
return sync_wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def get_user_permissions(user_id: int) -> List[str]:
|
||||
|
||||
@@ -3,13 +3,14 @@ from loguru import logger
|
||||
from ninja import Router
|
||||
|
||||
from users.models import Menu
|
||||
from users.permission import build_menu_tree, get_user_permissions
|
||||
from users.permission import build_menu_tree, get_user_permissions, require_permissions
|
||||
|
||||
router = Router(tags=['perms'])
|
||||
|
||||
|
||||
# ========== 用户专属接口 ==========
|
||||
@router.get("/menus/", summary="获取当前用户菜单树")
|
||||
@require_permissions("menu:list")
|
||||
def get_user_menu_tree(request):
|
||||
menus = Menu.objects.filter(
|
||||
roles__users__id=request.auth.id,
|
||||
@@ -22,6 +23,7 @@ def get_user_menu_tree(request):
|
||||
|
||||
|
||||
@router.get("/permissions/", summary="获取当前用户按钮权限")
|
||||
@require_permissions("menu:list")
|
||||
def get_user_permissions_api(request):
|
||||
perms = get_user_permissions(request.auth.id)
|
||||
return {"permissions": perms}
|
||||
|
||||
+12
-19
@@ -6,39 +6,35 @@ from ninja import Router
|
||||
from ninja.errors import HttpError
|
||||
|
||||
from users.models import Role
|
||||
from users.permission import has_permission, clear_user_permissions_cache
|
||||
from users.permission import clear_user_permissions_cache, require_permissions
|
||||
from users.schema import RoleOut, RoleCreate, RoleMenuAssign, RoleUpdate
|
||||
|
||||
router = Router(tags=['roles'])
|
||||
|
||||
|
||||
@router.get("/", response=List[RoleOut], summary="获取角色列表")
|
||||
@require_permissions("role:list")
|
||||
def list_roles(request):
|
||||
return Role.objects.all()
|
||||
|
||||
|
||||
@router.post("/", response=RoleOut, summary="创建角色")
|
||||
@require_permissions("role:create")
|
||||
def create_role(request, payload: RoleCreate):
|
||||
if not has_permission(request.auth.id, "role:create"):
|
||||
raise HttpError(403, "权限不足")
|
||||
role = Role.objects.create(**payload.dict())
|
||||
return role
|
||||
|
||||
|
||||
@router.get("/", response=List[RoleOut], summary="获取角色列表")
|
||||
def list_roles(request):
|
||||
if not has_permission(request.auth.id, "role:list"):
|
||||
raise HttpError(403, "权限不足")
|
||||
return Role.objects.all()
|
||||
|
||||
|
||||
@router.get("/{role_id}/", response=RoleOut, summary="获取角色详情")
|
||||
@require_permissions("role:view")
|
||||
def get_role(request, role_id: int):
|
||||
if not has_permission(request.auth.id, "role:view"):
|
||||
raise HttpError(403, "权限不足")
|
||||
role = get_object_or_404(Role, id=role_id)
|
||||
return role
|
||||
|
||||
|
||||
@router.put("/{role_id}/", response=RoleOut, summary="更新角色")
|
||||
@require_permissions("role:update")
|
||||
def update_role(request, role_id: int, payload: RoleUpdate):
|
||||
if not has_permission(request.auth.id, "role:update"):
|
||||
raise HttpError(403, "权限不足")
|
||||
role = get_object_or_404(Role, id=role_id)
|
||||
for attr, value in payload.dict().items():
|
||||
setattr(role, attr, value)
|
||||
@@ -47,19 +43,16 @@ def update_role(request, role_id: int, payload: RoleUpdate):
|
||||
|
||||
|
||||
@router.delete("/{role_id}/", summary="删除角色")
|
||||
@require_permissions("role:delete")
|
||||
def delete_role(request, role_id: int):
|
||||
if not has_permission(request.auth.id, "role:delete"):
|
||||
raise HttpError(403, "权限不足")
|
||||
role = get_object_or_404(Role, id=role_id)
|
||||
role.delete()
|
||||
return {"success": True}
|
||||
|
||||
|
||||
@router.post("/{role_id}/menus/", summary="分配角色菜单权限")
|
||||
@require_permissions("role:assign_permissions")
|
||||
def assign_role_menus(request, role_id: int, payload: RoleMenuAssign):
|
||||
if not has_permission(request.auth.id, "role:assign_permissions"):
|
||||
raise HttpError(403, "权限不足")
|
||||
|
||||
role = get_object_or_404(Role, id=role_id)
|
||||
# 直接使用 ManyToManyField 的 set() 方法
|
||||
role.menus.set(payload.menu_ids)
|
||||
|
||||
+25
-14
@@ -2,12 +2,18 @@
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from ninja import Schema, ModelSchema
|
||||
|
||||
from users.models import User
|
||||
from ninja import Schema
|
||||
|
||||
|
||||
# ========== 用户 Schema ==========
|
||||
class UserRoleOut(Schema):
|
||||
id: int
|
||||
name: str
|
||||
|
||||
|
||||
class UserDeptOut(Schema):
|
||||
id: int
|
||||
name: str
|
||||
|
||||
|
||||
class UserOut(Schema):
|
||||
@@ -18,8 +24,8 @@ class UserOut(Schema):
|
||||
email: Optional[str] = None
|
||||
avatar: Optional[str] = None
|
||||
|
||||
# dept: Optional[int] = None
|
||||
# roles: List[int] = []
|
||||
dept: Optional[UserDeptOut] = None
|
||||
roles: List[UserRoleOut] = []
|
||||
|
||||
is_active: bool
|
||||
is_staff: bool
|
||||
@@ -31,7 +37,7 @@ class UserOut(Schema):
|
||||
|
||||
class UserCreate(Schema):
|
||||
username: str
|
||||
password: str
|
||||
password: Optional[str] = None
|
||||
cname: Optional[str] = None
|
||||
phone: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
@@ -40,15 +46,20 @@ class UserCreate(Schema):
|
||||
is_active: bool = True
|
||||
|
||||
|
||||
class UserResetPassword(Schema):
|
||||
user_id: int
|
||||
new_password: str
|
||||
|
||||
|
||||
class UserUpdate(Schema):
|
||||
username: Optional[str]
|
||||
password: Optional[str]
|
||||
cname: Optional[str]
|
||||
phone: Optional[str]
|
||||
email: Optional[str]
|
||||
dept: Optional[int]
|
||||
roles: Optional[List[int]]
|
||||
is_active: Optional[bool]
|
||||
username: Optional[str] = None
|
||||
password: Optional[str] = None
|
||||
cname: Optional[str] = None
|
||||
phone: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
dept: Optional[int] = None
|
||||
roles: Optional[List[int]] = None
|
||||
is_active: Optional[bool] = None
|
||||
|
||||
|
||||
# ========== 菜单 Schema ==========
|
||||
|
||||
+81
-43
@@ -1,50 +1,100 @@
|
||||
import secrets
|
||||
from typing import List
|
||||
|
||||
from django.db.models import Prefetch
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.db import IntegrityError
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import get_object_or_404
|
||||
from loguru import logger
|
||||
from ninja import Router
|
||||
from ninja.errors import HttpError
|
||||
from ninja.pagination import paginate, PageNumberPagination
|
||||
|
||||
from users.models import User, Role
|
||||
from users.schema import UserUpdate, UserOut, UserCreate
|
||||
from users.models import User, Department
|
||||
from users.permission import require_permissions
|
||||
from users.schema import UserUpdate, UserOut, UserCreate, UserResetPassword
|
||||
from utils.dept_utils import get_dept_children_ids
|
||||
|
||||
router = Router(tags=['users'])
|
||||
|
||||
|
||||
@router.get("/", response=List[UserOut], summary="获取用户列表")
|
||||
@paginate(PageNumberPagination, page_size=20)
|
||||
def list_users(request):
|
||||
# if not has_permission(request.auth.id, "user:list"):
|
||||
# raise HttpError(403, "权限不足")
|
||||
return User.objects.all()
|
||||
@require_permissions("user:list")
|
||||
def list_users(request, dept_id: int = None, q: str = None):
|
||||
users = User.objects.all()
|
||||
logger.debug(f"users: {len(users)}")
|
||||
|
||||
logger.debug(f"dept_id: {dept_id}, q: {q}")
|
||||
if dept_id:
|
||||
current_dept = get_object_or_404(Department, id=dept_id)
|
||||
dept_ids = get_dept_children_ids(dept_id)
|
||||
if current_dept.is_root:
|
||||
# 包含未分配用户
|
||||
users = users.filter(Q(dept_id__in=dept_ids) | Q(dept__isnull=True))
|
||||
else:
|
||||
users = users.filter(dept_id__in=dept_ids)
|
||||
logger.debug(f"users: {len(users)}")
|
||||
|
||||
if q:
|
||||
users = users.filter(
|
||||
Q(username__icontains=q) |
|
||||
Q(cname__icontains=q) |
|
||||
Q(phone__icontains=q)
|
||||
)
|
||||
|
||||
logger.debug(f"users: {len(users)}")
|
||||
return users.order_by("dept_id")
|
||||
|
||||
|
||||
@router.get("/", response=dict)
|
||||
def list_users(request, page: int = 1, page_size: int = 10, username: str = None):
|
||||
qs = User.objects.all().order_by("-id")
|
||||
@router.post("/")
|
||||
@require_permissions("user:create")
|
||||
def create_user(request, data: UserCreate):
|
||||
try:
|
||||
if not data.password:
|
||||
data.password = secrets.token_urlsafe(8)[:8]
|
||||
|
||||
if username:
|
||||
qs = qs.filter(username__icontains=username)
|
||||
logger.debug(f"用户名:{data.username}, 密码:{data.password}")
|
||||
user = User.objects.create_user(
|
||||
username=data.username,
|
||||
email=data.email,
|
||||
password=make_password(data.password)
|
||||
)
|
||||
|
||||
total = qs.count()
|
||||
start = (page - 1) * page_size
|
||||
end = start + page_size
|
||||
for k, v in data.dict(exclude={"password", "roles"}).items():
|
||||
setattr(user, k, v)
|
||||
|
||||
items = list(qs[start:end].values(
|
||||
"id", "username", "cname", "phone", "email",
|
||||
"avatar", "dept",
|
||||
"is_active", "is_staff", "is_superuser",
|
||||
"last_login", "date_joined"
|
||||
))
|
||||
user.save()
|
||||
|
||||
# roles 需要手动补
|
||||
for i, obj in enumerate(qs[start:end]):
|
||||
items[i]["roles"] = list(obj.roles.values_list("id", flat=True))
|
||||
if data.roles:
|
||||
user.roles.set(data.roles)
|
||||
|
||||
return {"items": items, "count": total}
|
||||
return {
|
||||
"detail": f"用户创建成功!密码:{data.password}"
|
||||
}
|
||||
except IntegrityError as e:
|
||||
raise HttpError(500, "用户已存在!")
|
||||
|
||||
|
||||
@router.post("/reset-password/", summary="重置用户密码")
|
||||
@require_permissions("user:reset_password")
|
||||
def reset_password(request, payload: UserResetPassword):
|
||||
user = get_object_or_404(User, id=payload.user_id)
|
||||
|
||||
if payload.new_password:
|
||||
new_pass = payload.new_password
|
||||
else:
|
||||
new_pass = secrets.token_urlsafe(8)[:12] # 自动生成
|
||||
|
||||
user.password = make_password(new_pass)
|
||||
user.save()
|
||||
|
||||
# 返回新密码(仅用于通知,前端可显示)
|
||||
return {"detail": f"密码已重置: {new_pass}"}
|
||||
|
||||
|
||||
@router.get("/{id}", response=UserOut)
|
||||
@require_permissions("user:view")
|
||||
def get_user(request, id: int):
|
||||
obj = get_object_or_404(User, id=id)
|
||||
data = obj.__dict__
|
||||
@@ -52,25 +102,8 @@ def get_user(request, id: int):
|
||||
return data
|
||||
|
||||
|
||||
@router.post("/", response=UserOut)
|
||||
def create_user(request, data: UserCreate):
|
||||
user = User.objects.create_user(
|
||||
username=data.username,
|
||||
password=data.password
|
||||
)
|
||||
|
||||
for k, v in data.dict(exclude={"password"}).items():
|
||||
setattr(user, k, v)
|
||||
|
||||
user.save()
|
||||
|
||||
if data.roles:
|
||||
user.roles.set(data.roles)
|
||||
|
||||
return user
|
||||
|
||||
|
||||
@router.put("/{id}")
|
||||
@require_permissions("user:update")
|
||||
def update_user(request, id: int, data: UserUpdate):
|
||||
user = get_object_or_404(User, id=id)
|
||||
|
||||
@@ -78,6 +111,8 @@ def update_user(request, id: int, data: UserUpdate):
|
||||
user.set_password(data.password)
|
||||
|
||||
for k, v in data.dict(exclude_unset=True, exclude={"password", "roles"}).items():
|
||||
if k == "dept":
|
||||
k = "dept_id"
|
||||
setattr(user, k, v)
|
||||
|
||||
user.save()
|
||||
@@ -85,10 +120,13 @@ def update_user(request, id: int, data: UserUpdate):
|
||||
if data.roles is not None:
|
||||
user.roles.set(data.roles)
|
||||
|
||||
if data.password:
|
||||
return {"detail": f"密码已重置: {data.password}"}
|
||||
return {"success": True}
|
||||
|
||||
|
||||
@router.delete("/{id}")
|
||||
@require_permissions("user:delete")
|
||||
def delete_user(request, id: int):
|
||||
User.objects.filter(id=id).delete()
|
||||
return {"success": True}
|
||||
|
||||
Reference in New Issue
Block a user