283 lines
5.9 KiB
TypeScript
283 lines
5.9 KiB
TypeScript
import { prisma } from "./prisma"
|
|
import { Role as PrismaRole } from "@prisma/client"
|
|
|
|
// 导出 Role 类型供前端使用
|
|
export type Role = "OWNER" | "EDITOR" | "VIEWER"
|
|
|
|
export async function checkPermission(
|
|
userId: string,
|
|
treeId: string,
|
|
requiredRole: PrismaRole = PrismaRole.VIEWER
|
|
) {
|
|
// 检查是否是所有者
|
|
const tree = await prisma.familyTree.findFirst({
|
|
where: {
|
|
id: treeId,
|
|
ownerId: userId
|
|
}
|
|
})
|
|
|
|
if (tree) {
|
|
return { hasPermission: true, role: PrismaRole.OWNER as Role }
|
|
}
|
|
|
|
// 检查协作者权限
|
|
const collaborator = await prisma.treeCollaborator.findFirst({
|
|
where: {
|
|
treeId,
|
|
userId
|
|
}
|
|
})
|
|
|
|
if (!collaborator) {
|
|
return { hasPermission: false, role: null }
|
|
}
|
|
|
|
const roleHierarchy = {
|
|
[PrismaRole.OWNER]: 3,
|
|
[PrismaRole.EDITOR]: 2,
|
|
[PrismaRole.VIEWER]: 1
|
|
}
|
|
|
|
const hasPermission = roleHierarchy[collaborator.role] >= roleHierarchy[requiredRole]
|
|
|
|
return { hasPermission, role: collaborator.role as Role }
|
|
}
|
|
|
|
export async function requireAuth(userId: string | undefined) {
|
|
if (!userId) {
|
|
throw new Error("未授权")
|
|
}
|
|
return userId
|
|
}
|
|
|
|
/**
|
|
* 权限控制工具函数
|
|
* 用于基于角色的访问控制 (RBAC)
|
|
*/
|
|
|
|
/**
|
|
* 权限检查函数集合
|
|
*/
|
|
export const permissions = {
|
|
// ==================== 增加权限 ====================
|
|
|
|
/**
|
|
* 是否可以创建/添加成员
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canCreate: (role?: Role): boolean => {
|
|
return role === "OWNER" || role === "EDITOR"
|
|
},
|
|
|
|
/**
|
|
* 是否可以创建家族树
|
|
* 所有登录用户都可以创建自己的家族树
|
|
*/
|
|
canCreateTree: (role?: Role): boolean => {
|
|
return true // 所有人都可以创建新家族树
|
|
},
|
|
|
|
// ==================== 修改权限 ====================
|
|
|
|
/**
|
|
* 是否可以编辑/更新成员信息
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canUpdate: (role?: Role): boolean => {
|
|
return role === "OWNER" || role === "EDITOR"
|
|
},
|
|
|
|
/**
|
|
* 是否可以导入数据
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canImport: (role?: Role): boolean => {
|
|
return role === "OWNER" || role === "EDITOR"
|
|
},
|
|
|
|
// ==================== 删除权限 ====================
|
|
|
|
/**
|
|
* 是否可以删除成员
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canDeleteMember: (role?: Role): boolean => {
|
|
return role === "OWNER" || role === "EDITOR"
|
|
},
|
|
|
|
/**
|
|
* 是否可以删除家族树
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canDeleteTree: (role?: Role): boolean => {
|
|
return role === "OWNER"
|
|
},
|
|
|
|
/**
|
|
* 是否可以清空数据
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canClearData: (role?: Role): boolean => {
|
|
return role === "OWNER"
|
|
},
|
|
|
|
// ==================== 协作者管理权限 ====================
|
|
|
|
/**
|
|
* 是否可以邀请协作者
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canInviteCollaborators: (role?: Role): boolean => {
|
|
return role === "OWNER"
|
|
},
|
|
|
|
/**
|
|
* 是否可以移除协作者
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canRemoveCollaborators: (role?: Role): boolean => {
|
|
return role === "OWNER"
|
|
},
|
|
|
|
/**
|
|
* 是否可以管理协作者(邀请和移除)
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canManageCollaborators: (role?: Role): boolean => {
|
|
return role === "OWNER"
|
|
},
|
|
|
|
// ==================== 查看权限 ====================
|
|
|
|
/**
|
|
* 是否可以查看信息
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canView: (role?: Role): boolean => {
|
|
return true //
|
|
},
|
|
|
|
/**
|
|
* 是否可以搜索和查询
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canSearch: (role?: Role): boolean => {
|
|
return true //
|
|
},
|
|
|
|
/**
|
|
* 是否可以导出数据
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canExport: (role?: Role): boolean => {
|
|
return true //
|
|
},
|
|
|
|
/**
|
|
* 是否可以打印
|
|
* OWNER | EDITOR | VIEWER
|
|
*/
|
|
canPrint: (role?: Role): boolean => {
|
|
return true //
|
|
},
|
|
}
|
|
|
|
// ==================== 兼容旧代码的函数 ====================
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
export function canEditTree(role?: Role): boolean {
|
|
return permissions.canUpdate(role)
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
export function canDeleteTree(role?: Role): boolean {
|
|
return permissions.canDeleteTree(role)
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
export function canInviteCollaborators(role?: Role): boolean {
|
|
return permissions.canInviteCollaborators(role)
|
|
}
|
|
|
|
// ==================== 权限验证辅助函数 ====================
|
|
|
|
/**
|
|
*
|
|
*/
|
|
export function requirePermission(
|
|
role: Role | undefined,
|
|
permissionCheck: (role?: Role) => boolean,
|
|
errorMessage: string = "您没有权限执行此操作"
|
|
): void {
|
|
if (!permissionCheck(role)) {
|
|
throw new Error(errorMessage)
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
export function getRoleDisplayName(role: Role): string {
|
|
const roleNames: Record<Role, string> = {
|
|
OWNER: "所有者",
|
|
EDITOR: "编辑者",
|
|
VIEWER: "查看者",
|
|
}
|
|
return roleNames[role] || role
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
export function getRoleDescription(role: Role): string {
|
|
const descriptions: Record<Role, string> = {
|
|
OWNER: "拥有全部权限,可以管理家族树和协作者",
|
|
EDITOR: "可以添加、编辑和删除成员,但不能删除家族树或管理协作者",
|
|
VIEWER: "只能查看、搜索和导出数据,不能进行任何修改操作",
|
|
}
|
|
return descriptions[role] || ""
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
export function getRolePermissions(role: Role): string[] {
|
|
const allPermissions = {
|
|
OWNER: [
|
|
"查看所有信息",
|
|
"搜索和筛选",
|
|
"导出和打印",
|
|
"添加成员",
|
|
"编辑成员",
|
|
"删除成员",
|
|
"导入数据",
|
|
"邀请协作者",
|
|
"移除协作者",
|
|
"删除家族树",
|
|
"清空数据",
|
|
],
|
|
EDITOR: [
|
|
"查看所有信息",
|
|
"搜索和筛选",
|
|
"导出和打印",
|
|
"添加成员",
|
|
"编辑成员",
|
|
"删除成员",
|
|
"导入数据",
|
|
],
|
|
VIEWER: [
|
|
"查看所有信息",
|
|
"搜索和筛选",
|
|
"导出和打印",
|
|
],
|
|
}
|
|
return allPermissions[role] || []
|
|
}
|