Files
chinese-family-tree-2/PERMISSION_IMPLEMENTATION_STATUS.md
T
freedakgmail e44dd0bd95 0.0.8.0
2025-11-23 18:03:04 +08:00

6.7 KiB
Raw Blame History

🔐 权限控制实施状态

已完成

1. 核心权限系统

  • 权限工具函数 (lib/permissions.ts)
    • 创建 permissions 对象,包含所有权限检查函数
    • 添加辅助函数:getRoleDisplayNamegetRoleDescriptiongetRolePermissions
    • 修复类型冲突,使用 PrismaRole 和导出的 Role 类型
    • 添加完整的中文注释和文档

2. 页面权限控制

  • 首页 (app/page.tsx)

    • 导入 permissions
    • "添加成员"按钮使用 permissions.canCreate(role)
  • 成员列表页 (app/members/page.tsx)

    • 导入 permissionscurrentTree
    • "新增成员"按钮使用 permissions.canCreate(role)
    • 筛选和搜索功能对所有人可见

🚧 待实施

高优先级(今天完成)

1. 成员详情页 (app/members/[id]/page.tsx)

需要更新的按钮:

// 快速添加按钮
{permissions.canCreate(role) && (
  <>
    {!member.fatherId && <Button onClick={handleAddFather}>添加父亲</Button>}
    {!member.motherId && <Button onClick={handleAddMother}>添加母亲</Button>}
    <Button onClick={handleAddChild}>添加子女</Button>
    <Button onClick={handleAddSpouse}>添加配偶</Button>
  </>
)}

// 编辑删除按钮
{permissions.canUpdate(role) && (
  <Button onClick={() => setIsEditing(true)}>编辑</Button>
)}

{permissions.canDeleteMember(role) && (
  <Button variant="destructive" onClick={handleDelete}>删除</Button>
)}

2. 系统设置页 (app/settings/page.tsx)

需要更新的按钮:

// 导入导出
{permissions.canImport(role) && (
  <>
    <Button onClick={handleImportData}>导入数据</Button>
    <Button onClick={handleImportGEDCOM}>导入GEDCOM</Button>
  </>
)}

{permissions.canExport(role) && (
  <>
    <Button onClick={handleExportData}>导出数据</Button>
    <Button onClick={handleExportGEDCOM}>导出GEDCOM</Button>
  </>
)}

// 清空操作(仅 OWNER
{permissions.canClearData(role) && (
  <>
    <Button variant="destructive" onClick={handleClearData}>清空数据</Button>
    <Button variant="destructive" onClick={handleClearLogs}>清空日志</Button>
  </>
)}

3. 全局导航 (components/site-header.tsx)

需要更新的按钮:

// 删除家族树(仅 OWNER
{permissions.canDeleteTree(role) && (
  <DropdownMenuItem onClick={handleDeleteTree}>
    <Trash2 className="mr-2 h-4 w-4" />
    删除家族树
  </DropdownMenuItem>
)}

// 创建家族树
{permissions.canCreateTree(role) && (
  <DropdownMenuItem onClick={() => router.push('/trees/new')}>
    <Plus className="mr-2 h-4 w-4" />
    创建新家族树
  </DropdownMenuItem>
)}

中优先级(本周完成)

4. 新增成员页 (app/members/new/page.tsx)

需要添加页面级权限检查:

export default function NewMemberPage() {
  const { currentTree } = useFamily()
  const router = useRouter()
  
  // 权限检查
  useEffect(() => {
    if (!permissions.canCreate(currentTree?.currentUserRole)) {
      router.push('/members')
      toast.error('您没有权限添加成员')
    }
  }, [currentTree?.currentUserRole])
  
  // ... 其他代码
}

5. 族谱图页 (app/tree/page.tsx)

所有按钮都是查看功能,无需特殊权限控制。

6. 关系计算页 (app/relationship/page.tsx)

所有按钮都是查询功能,无需特殊权限控制。

7. 大事记页 (app/timeline/page.tsx)

所有按钮都是查看功能,无需特殊权限控制。

低优先级(下周完成)

8. API 层面权限验证

需要在以下 API 路由中添加权限检查:

// app/api/trees/[treeId]/members/route.ts
export async function POST(request: Request, { params }: { params: Promise<{ treeId: string }> }) {
  const session = await getServerSession(authOptions)
  const { treeId } = await params
  
  // 权限检查
  const { hasPermission } = await checkPermission(
    session.user.id,
    treeId,
    PrismaRole.EDITOR
  )
  
  if (!hasPermission) {
    return NextResponse.json({ error: "权限不足" }, { status: 403 })
  }
  
  // ... 执行操作
}

需要添加权限检查的 API

  • /api/trees/[treeId]/members POST - EDITOR
  • /api/trees/[treeId]/members/[memberId] PATCH - EDITOR
  • /api/trees/[treeId]/members/[memberId] DELETE - EDITOR
  • /api/trees/[treeId] DELETE - OWNER
  • /api/trees/[treeId]/invite POST - OWNER
  • /api/trees/[treeId]/collaborators/[collaboratorId] DELETE - OWNER
  • /api/trees/[treeId]/import POST - EDITOR

📊 进度统计

页面进度

  • 完成: 2/11 (18%)
  • 🚧 进行中: 0/11 (0%)
  • 待开始: 9/11 (82%)

按钮进度

  • 完成: 3/80+ (4%)
  • 待更新: 77/80+ (96%)

API 进度

  • 待开始: 0/7 (0%)

🎯 下一步行动

立即执行(接下来 30 分钟)

  1. 更新成员详情页的所有按钮
  2. 更新系统设置页的所有按钮
  3. 测试 OWNER 和 EDITOR 的按钮显示

今天完成

  1. 更新全局导航的按钮
  2. 添加新增成员页的权限检查
  3. 测试 VIEWER 的按钮显示

本周完成

  1. 添加所有 API 的权限验证
  2. 完整测试三种角色
  3. 添加错误提示和处理

💻 代码示例

标准实施模式

// 1. 导入权限函数
import { permissions } from "@/lib/permissions"

// 2. 获取当前角色
const { currentTree } = useFamily()
const role = currentTree?.currentUserRole

// 3. 条件渲染按钮
{permissions.canCreate(role) && (
  <Button onClick={handleAdd}>添加</Button>
)}

{permissions.canUpdate(role) && (
  <Button onClick={handleEdit}>编辑</Button>
)}

{permissions.canDeleteMember(role) && (
  <Button variant="destructive" onClick={handleDelete}>删除</Button>
)}

{permissions.canDeleteTree(role) && (
  <Button variant="destructive" onClick={handleDeleteTree}>删除家族树</Button>
)}

{permissions.canManageCollaborators(role) && (
  <Button onClick={handleInvite}>邀请协作者</Button>
)}

📝 注意事项

实施时注意

  1. 所有页面都要导入 permissions
  2. 所有页面都要获取 currentTreerole
  3. 使用条件渲染而不是禁用状态(更好的用户体验)
  4. ⚠️ 不要忘记 API 层面的权限验证
  5. ⚠️ 测试所有三种角色的显示效果

测试检查清单

  • OWNER 可以看到所有按钮
  • EDITOR 看不到管理类按钮
  • VIEWER 只能看到查看类按钮
  • 无权限操作时有友好提示
  • API 返回正确的错误码

🔗 相关文档


最后更新: 2025-11-23 17:35
当前状态: 🚧 进行中
预计完成: 今天晚上