6.7 KiB
6.7 KiB
🔐 权限控制实施状态
✅ 已完成
1. 核心权限系统
- ✅ 权限工具函数 (
lib/permissions.ts)- 创建
permissions对象,包含所有权限检查函数 - 添加辅助函数:
getRoleDisplayName、getRoleDescription、getRolePermissions - 修复类型冲突,使用
PrismaRole和导出的Role类型 - 添加完整的中文注释和文档
- 创建
2. 页面权限控制
-
✅ 首页 (
app/page.tsx)- 导入
permissions - "添加成员"按钮使用
permissions.canCreate(role)
- 导入
-
✅ 成员列表页 (
app/members/page.tsx)- 导入
permissions和currentTree - "新增成员"按钮使用
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]/membersPOST - EDITOR - ✅
/api/trees/[treeId]/members/[memberId]PATCH - EDITOR - ✅
/api/trees/[treeId]/members/[memberId]DELETE - EDITOR - ✅
/api/trees/[treeId]DELETE - OWNER - ✅
/api/trees/[treeId]/invitePOST - OWNER - ✅
/api/trees/[treeId]/collaborators/[collaboratorId]DELETE - OWNER - ✅
/api/trees/[treeId]/importPOST - EDITOR
📊 进度统计
页面进度
- ✅ 完成: 2/11 (18%)
- 🚧 进行中: 0/11 (0%)
- ⏳ 待开始: 9/11 (82%)
按钮进度
- ✅ 完成: 3/80+ (4%)
- ⏳ 待更新: 77/80+ (96%)
API 进度
- ⏳ 待开始: 0/7 (0%)
🎯 下一步行动
立即执行(接下来 30 分钟)
- 更新成员详情页的所有按钮
- 更新系统设置页的所有按钮
- 测试 OWNER 和 EDITOR 的按钮显示
今天完成
- 更新全局导航的按钮
- 添加新增成员页的权限检查
- 测试 VIEWER 的按钮显示
本周完成
- 添加所有 API 的权限验证
- 完整测试三种角色
- 添加错误提示和处理
💻 代码示例
标准实施模式
// 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>
)}
📝 注意事项
实施时注意
- ✅ 所有页面都要导入
permissions - ✅ 所有页面都要获取
currentTree和role - ✅ 使用条件渲染而不是禁用状态(更好的用户体验)
- ⚠️ 不要忘记 API 层面的权限验证
- ⚠️ 测试所有三种角色的显示效果
测试检查清单
- OWNER 可以看到所有按钮
- EDITOR 看不到管理类按钮
- VIEWER 只能看到查看类按钮
- 无权限操作时有友好提示
- API 返回正确的错误码
🔗 相关文档
最后更新: 2025-11-23 17:35
当前状态: 🚧 进行中
预计完成: 今天晚上