feat(权限): 实现权限树形结构管理
- 在权限模型中添加 parentid 字段支持树形结构 - 新增权限树形结构 API 接口 - 更新初始化脚本以支持权限树形结构 - 调整权限字段长度限制
This commit is contained in:
parent
a3206bb0f6
commit
5632b0d69c
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,12 +2,14 @@ from fastapi import APIRouter, Depends, HTTPException
|
|||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from fastcrud import FastCRUD
|
from fastcrud import FastCRUD
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
from database import get_db
|
from database import get_db
|
||||||
from models import Permission, Role
|
from models import Permission, Role
|
||||||
from schemas import (
|
from schemas import (
|
||||||
PermissionCreate,
|
PermissionCreate,
|
||||||
PermissionResponse,
|
PermissionResponse,
|
||||||
|
PermissionTreeResponse,
|
||||||
RolePermissionAssign,
|
RolePermissionAssign,
|
||||||
RolePermissionResponse,
|
RolePermissionResponse,
|
||||||
)
|
)
|
||||||
@ -37,6 +39,7 @@ async def create_permission(
|
|||||||
db_permission = Permission(
|
db_permission = Permission(
|
||||||
name=permission_data.name,
|
name=permission_data.name,
|
||||||
code=permission_data.code,
|
code=permission_data.code,
|
||||||
|
parentid=permission_data.parentid,
|
||||||
description=permission_data.description,
|
description=permission_data.description,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -58,6 +61,40 @@ async def get_permissions(
|
|||||||
return permissions
|
return permissions
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/tree", response_model=list[PermissionTreeResponse])
|
||||||
|
async def get_permission_tree(
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
"""获取权限树形结构(基于 parentid)"""
|
||||||
|
# 获取所有权限
|
||||||
|
result = await db.execute(select(Permission))
|
||||||
|
permissions = result.scalars().all()
|
||||||
|
|
||||||
|
# 转换为字典,便于查找
|
||||||
|
perm_dict = {perm.id: {
|
||||||
|
"id": perm.id,
|
||||||
|
"name": perm.name,
|
||||||
|
"code": perm.code,
|
||||||
|
"parentid": perm.parentid,
|
||||||
|
"description": perm.description,
|
||||||
|
"children": []
|
||||||
|
} for perm in permissions}
|
||||||
|
|
||||||
|
# 构建树形结构
|
||||||
|
tree = []
|
||||||
|
for perm_id, perm_data in perm_dict.items():
|
||||||
|
parentid = perm_data["parentid"]
|
||||||
|
if parentid == 0:
|
||||||
|
# 顶级节点
|
||||||
|
tree.append(perm_data)
|
||||||
|
elif parentid in perm_dict:
|
||||||
|
# 子节点,添加到父节点的 children
|
||||||
|
perm_dict[parentid]["children"].append(perm_data)
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{permission_id}", response_model=PermissionResponse)
|
@router.get("/{permission_id}", response_model=PermissionResponse)
|
||||||
async def get_permission(
|
async def get_permission(
|
||||||
permission_id: int,
|
permission_id: int,
|
||||||
|
|||||||
Binary file not shown.
@ -1,66 +1,129 @@
|
|||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select, text
|
||||||
from models import Role, User, Permission
|
from models import Role, User, Permission
|
||||||
from utils.password import get_password_hash
|
from utils.password import get_password_hash
|
||||||
|
|
||||||
|
|
||||||
|
async def ensure_permission_table_structure(db: AsyncSession):
|
||||||
|
"""确保 permission 表结构符合最新要求"""
|
||||||
|
print("检查并更新 permission 表结构...")
|
||||||
|
|
||||||
|
# 检查表是否存在
|
||||||
|
result = await db.execute(
|
||||||
|
text("SELECT table_name FROM information_schema.tables WHERE table_name = 'permission'")
|
||||||
|
)
|
||||||
|
table_exists = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not table_exists:
|
||||||
|
print("permission 表不存在,将由 SQLAlchemy 创建")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 检查是否缺少 parentid 字段
|
||||||
|
result = await db.execute(
|
||||||
|
text("SELECT column_name FROM information_schema.columns WHERE table_name = 'permission'")
|
||||||
|
)
|
||||||
|
existing_columns = {row[0] for row in result.fetchall()}
|
||||||
|
|
||||||
|
# 添加 parentid 字段
|
||||||
|
if 'parentid' not in existing_columns:
|
||||||
|
try:
|
||||||
|
await db.execute(text("ALTER TABLE permission ADD COLUMN IF NOT EXISTS parentid INTEGER DEFAULT 0"))
|
||||||
|
print("添加 parentid 字段成功")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"添加 parentid 字段失败: {e}")
|
||||||
|
|
||||||
|
# 删除旧字段(如果存在)
|
||||||
|
for old_column in ['module', 'submodule', 'action']:
|
||||||
|
if old_column in existing_columns:
|
||||||
|
try:
|
||||||
|
await db.execute(text(f"ALTER TABLE permission DROP COLUMN IF EXISTS {old_column}"))
|
||||||
|
print(f"删除旧字段 {old_column} 成功")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"删除旧字段 {old_column} 失败: {e}")
|
||||||
|
|
||||||
|
await db.commit()
|
||||||
|
print("permission 表结构更新完成")
|
||||||
|
|
||||||
|
|
||||||
async def init_permissions(db: AsyncSession):
|
async def init_permissions(db: AsyncSession):
|
||||||
"""初始化权限数据"""
|
"""初始化权限数据(树形结构)"""
|
||||||
# 定义需要初始化的权限
|
# 定义需要初始化的权限(树形结构)
|
||||||
required_permissions = [
|
# parentid: 0 = 顶级模块, >0 = 子权限
|
||||||
{"name": "用户管理", "code": "user:manage", "description": "用户管理权限"},
|
permission_tree = [
|
||||||
{"name": "用户查询", "code": "user:read", "description": "用户查询权限"},
|
# 顶级模块
|
||||||
{"name": "用户创建", "code": "user:create", "description": "用户创建权限"},
|
{"name": "权限管理", "code": "perm", "parentid": 0, "description": "权限管理模块"},
|
||||||
{"name": "用户更新", "code": "user:update", "description": "用户更新权限"},
|
|
||||||
{"name": "用户删除", "code": "user:delete", "description": "用户删除权限"},
|
# 二级子模块
|
||||||
{"name": "角色管理", "code": "role:manage", "description": "角色管理权限"},
|
{"name": "用户管理", "code": "perm:user", "parentid": 1, "description": "用户管理子模块"},
|
||||||
{"name": "角色查询", "code": "role:read", "description": "角色查询权限"},
|
{"name": "角色管理", "code": "perm:role", "parentid": 1, "description": "角色管理子模块"},
|
||||||
{"name": "角色创建", "code": "role:create", "description": "角色创建权限"},
|
{"name": "权限配置", "code": "perm:config", "parentid": 1, "description": "权限配置子模块"},
|
||||||
{"name": "角色更新", "code": "role:update", "description": "角色更新权限"},
|
|
||||||
{"name": "角色删除", "code": "role:delete", "description": "角色删除权限"},
|
# 用户管理操作
|
||||||
{"name": "权限管理", "code": "permission:manage", "description": "权限管理权限"},
|
{"name": "查看列表", "code": "perm:user:list", "parentid": 2, "description": "查看用户列表"},
|
||||||
{"name": "权限查询", "code": "permission:read", "description": "权限查询权限"},
|
{"name": "查看详情", "code": "perm:user:detail", "parentid": 2, "description": "查看用户详情"},
|
||||||
{"name": "权限创建", "code": "permission:create", "description": "权限创建权限"},
|
{"name": "搜索", "code": "perm:user:search", "parentid": 2, "description": "搜索用户"},
|
||||||
{"name": "权限更新", "code": "permission:update", "description": "权限更新权限"},
|
{"name": "创建", "code": "perm:user:create", "parentid": 2, "description": "创建新用户"},
|
||||||
{"name": "权限删除", "code": "permission:delete", "description": "权限删除权限"},
|
{"name": "编辑", "code": "perm:user:edit", "parentid": 2, "description": "编辑用户信息"},
|
||||||
|
{"name": "删除", "code": "perm:user:delete", "parentid": 2, "description": "删除用户"},
|
||||||
|
{"name": "导出", "code": "perm:user:export", "parentid": 2, "description": "导出用户数据"},
|
||||||
|
|
||||||
|
# 角色管理操作
|
||||||
|
{"name": "查看列表", "code": "perm:role:list", "parentid": 3, "description": "查看角色列表"},
|
||||||
|
{"name": "查看详情", "code": "perm:role:detail", "parentid": 3, "description": "查看角色详情"},
|
||||||
|
{"name": "搜索", "code": "perm:role:search", "parentid": 3, "description": "搜索角色"},
|
||||||
|
{"name": "创建", "code": "perm:role:create", "parentid": 3, "description": "创建新角色"},
|
||||||
|
{"name": "编辑", "code": "perm:role:edit", "parentid": 3, "description": "编辑角色信息"},
|
||||||
|
{"name": "删除", "code": "perm:role:delete", "parentid": 3, "description": "删除角色"},
|
||||||
|
{"name": "导出", "code": "perm:role:export", "parentid": 3, "description": "导出角色数据"},
|
||||||
|
{"name": "分配权限", "code": "perm:role:assign", "parentid": 3, "description": "为角色分配权限"},
|
||||||
|
|
||||||
|
# 权限配置操作
|
||||||
|
{"name": "查看列表", "code": "perm:config:list", "parentid": 4, "description": "查看权限列表"},
|
||||||
|
{"name": "查看详情", "code": "perm:config:detail", "parentid": 4, "description": "查看权限详情"},
|
||||||
|
{"name": "搜索", "code": "perm:config:search", "parentid": 4, "description": "搜索权限"},
|
||||||
|
{"name": "创建", "code": "perm:config:create", "parentid": 4, "description": "创建新权限"},
|
||||||
|
{"name": "编辑", "code": "perm:config:edit", "parentid": 4, "description": "编辑权限信息"},
|
||||||
|
{"name": "删除", "code": "perm:config:delete", "parentid": 4, "description": "删除权限"},
|
||||||
|
{"name": "导出", "code": "perm:config:export", "parentid": 4, "description": "导岀权限数据"},
|
||||||
]
|
]
|
||||||
|
|
||||||
# 检查现有权限
|
# 检查现有权限
|
||||||
result = await db.execute(select(Permission))
|
result = await db.execute(select(Permission))
|
||||||
existing_permissions = result.scalars().all()
|
existing_permissions = result.scalars().all()
|
||||||
existing_permission_codes = {perm.code for perm in existing_permissions}
|
existing_permission_codes = {perm.code: perm for perm in existing_permissions}
|
||||||
|
|
||||||
# 检查需要创建或更新的权限
|
# 创建或更新权限
|
||||||
permissions_to_add = []
|
created_count = 0
|
||||||
permissions_to_update = []
|
updated_count = 0
|
||||||
|
|
||||||
for perm_data in required_permissions:
|
for perm_data in permission_tree:
|
||||||
perm_code = perm_data["code"]
|
perm_code = perm_data["code"]
|
||||||
if perm_code not in existing_permission_codes:
|
if perm_code not in existing_permission_codes:
|
||||||
# 权限不存在,需要创建
|
# 权限不存在,需要创建
|
||||||
permissions_to_add.append(Permission(**perm_data))
|
db.add(Permission(**perm_data))
|
||||||
|
created_count += 1
|
||||||
else:
|
else:
|
||||||
# 权限存在,检查是否需要更新
|
# 权限存在,检查是否需要更新
|
||||||
existing_perm = next(
|
existing_perm = existing_permission_codes[perm_code]
|
||||||
perm for perm in existing_permissions if perm.code == perm_code
|
update_needed = False
|
||||||
)
|
|
||||||
if existing_perm.name != perm_data["name"] or existing_perm.description != perm_data["description"]:
|
if existing_perm.name != perm_data["name"]:
|
||||||
existing_perm.name = perm_data["name"]
|
existing_perm.name = perm_data["name"]
|
||||||
|
update_needed = True
|
||||||
|
if existing_perm.parentid != perm_data["parentid"]:
|
||||||
|
existing_perm.parentid = perm_data["parentid"]
|
||||||
|
update_needed = True
|
||||||
|
if existing_perm.description != perm_data["description"]:
|
||||||
existing_perm.description = perm_data["description"]
|
existing_perm.description = perm_data["description"]
|
||||||
permissions_to_update.append(existing_perm)
|
update_needed = True
|
||||||
|
|
||||||
|
if update_needed:
|
||||||
|
updated_count += 1
|
||||||
|
|
||||||
# 执行创建和更新操作
|
if created_count > 0 or updated_count > 0:
|
||||||
if permissions_to_add:
|
|
||||||
for perm in permissions_to_add:
|
|
||||||
db.add(perm)
|
|
||||||
await db.commit()
|
await db.commit()
|
||||||
print(f"创建了 {len(permissions_to_add)} 个权限")
|
print(f"创建了 {created_count} 个权限,更新了 {updated_count} 个权限")
|
||||||
|
else:
|
||||||
if permissions_to_update:
|
|
||||||
await db.commit()
|
|
||||||
print(f"更新了 {len(permissions_to_update)} 个权限")
|
|
||||||
|
|
||||||
if not permissions_to_add and not permissions_to_update:
|
|
||||||
print("权限数据已存在且无需更新,跳过初始化")
|
print("权限数据已存在且无需更新,跳过初始化")
|
||||||
|
|
||||||
print("权限数据初始化/更新完成")
|
print("权限数据初始化/更新完成")
|
||||||
@ -293,6 +356,7 @@ async def init_test_user(db: AsyncSession):
|
|||||||
async def init_all_data(db: AsyncSession):
|
async def init_all_data(db: AsyncSession):
|
||||||
"""初始化所有数据"""
|
"""初始化所有数据"""
|
||||||
print("开始初始化数据库数据...")
|
print("开始初始化数据库数据...")
|
||||||
|
await ensure_permission_table_structure(db)
|
||||||
await init_roles(db)
|
await init_roles(db)
|
||||||
await init_permissions(db)
|
await init_permissions(db)
|
||||||
await init_role_permissions(db)
|
await init_role_permissions(db)
|
||||||
|
|||||||
@ -56,8 +56,9 @@ class Permission(Base):
|
|||||||
|
|
||||||
__tablename__ = "permission"
|
__tablename__ = "permission"
|
||||||
id = Column(Integer, primary_key=True, index=True, comment="权限ID")
|
id = Column(Integer, primary_key=True, index=True, comment="权限ID")
|
||||||
name = Column(String(50), nullable=False, comment="权限名称")
|
name = Column(String(100), nullable=False, comment="权限名称")
|
||||||
code = Column(String(50), nullable=False, unique=True, comment="权限编码")
|
code = Column(String(100), nullable=False, unique=True, comment="权限编码")
|
||||||
|
parentid = Column(Integer, default=0, comment="父权限ID(0表示顶级模块)")
|
||||||
description = Column(String(255), nullable=True, comment="权限描述")
|
description = Column(String(255), nullable=True, comment="权限描述")
|
||||||
createtime = Column(DateTime, default=datetime.utcnow, comment="创建时间")
|
createtime = Column(DateTime, default=datetime.utcnow, comment="创建时间")
|
||||||
updatetime = Column(
|
updatetime = Column(
|
||||||
|
|||||||
@ -112,8 +112,9 @@ class RoleResponse(RoleBase):
|
|||||||
class PermissionBase(BaseModel):
|
class PermissionBase(BaseModel):
|
||||||
"""权限基础模型"""
|
"""权限基础模型"""
|
||||||
|
|
||||||
name: str = Field(..., max_length=50, description="权限名称")
|
name: str = Field(..., max_length=100, description="权限名称")
|
||||||
code: str = Field(..., max_length=50, description="权限编码")
|
code: str = Field(..., max_length=100, description="权限编码")
|
||||||
|
parentid: int = Field(0, description="父权限ID(0表示顶级模块)")
|
||||||
description: Optional[str] = Field(None, max_length=255, description="权限描述")
|
description: Optional[str] = Field(None, max_length=255, description="权限描述")
|
||||||
|
|
||||||
|
|
||||||
@ -133,6 +134,17 @@ class PermissionResponse(PermissionBase):
|
|||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionTreeResponse(BaseModel):
|
||||||
|
"""权限树响应模型"""
|
||||||
|
|
||||||
|
id: int = Field(..., description="权限ID")
|
||||||
|
name: str = Field(..., description="权限名称")
|
||||||
|
code: str = Field(..., description="权限编码")
|
||||||
|
parentid: int = Field(..., description="父权限ID")
|
||||||
|
description: Optional[str] = Field(None, description="权限描述")
|
||||||
|
children: list = Field([], description="子权限列表")
|
||||||
|
|
||||||
|
|
||||||
# 角色权限关联相关模型
|
# 角色权限关联相关模型
|
||||||
class RolePermissionAssign(BaseModel):
|
class RolePermissionAssign(BaseModel):
|
||||||
"""角色权限分配模型"""
|
"""角色权限分配模型"""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user