Spaces:
Runtime error
Runtime error
| import "server-only"; | |
| import { getSession } from "./auth-instance"; | |
| import { getIsUserAdmin } from "lib/user/utils"; | |
| import { admin, editor, user as userRole } from "./roles"; | |
| import type { BetterAuthRole } from "./types"; | |
| import { parseRoleString, isBetterAuthRole } from "./types"; | |
| /** | |
| * Simple permission helpers that wrap Better Auth's role system | |
| * | |
| * Philosophy: | |
| * - Keep it simple and clear | |
| * - Users can always manage themselves | |
| * - Only admins can manage other users | |
| * - Easy to show/hide UI elements | |
| * - Easy to extend for workflows, etc. later | |
| */ | |
| /** | |
| * Check if user has admin permissions (for showing/hiding admin areas) | |
| */ | |
| export async function hasAdminPermission(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| const isAdmin = getIsUserAdmin(session.user); | |
| return isAdmin; | |
| } catch (error) { | |
| console.error("Error checking admin permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can list other users | |
| * Currently: only admins can list users | |
| */ | |
| export async function canListUsers(): Promise<boolean> { | |
| return await hasAdminPermission(); | |
| } | |
| /** | |
| * Check if user can manage other users (create, edit, delete, etc.) | |
| * Currently: only admins can manage other users | |
| */ | |
| export async function canManageUsers(): Promise<boolean> { | |
| return await hasAdminPermission(); | |
| } | |
| /** | |
| * Check if user can manage a specific user (themselves OR has manage permission) | |
| */ | |
| export async function canManageUser(targetUserId: string): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| // Can always manage own profile | |
| if (session.user.id === targetUserId) return true; | |
| // Or has admin permissions to manage other users | |
| return await canManageUsers(); | |
| } catch (error) { | |
| console.error("Error checking user management permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Require admin permissions or throw error | |
| */ | |
| export async function requireAdminPermission( | |
| action: string = "perform this action", | |
| ): Promise<void> { | |
| const hasPermission = await hasAdminPermission(); | |
| if (!hasPermission) { | |
| throw new Error(`Unauthorized: Admin access required to ${action}`); | |
| } | |
| } | |
| /** | |
| * Require user list permissions or throw error | |
| */ | |
| export async function requireUserListPermission( | |
| action: string = "list users", | |
| ): Promise<void> { | |
| const hasPermission = await canListUsers(); | |
| if (!hasPermission) { | |
| throw new Error(`Unauthorized: Permission required to ${action}`); | |
| } | |
| } | |
| /** | |
| * Require user management permissions or throw error | |
| */ | |
| export async function requireUserManagePermission( | |
| action: string = "manage users", | |
| ): Promise<void> { | |
| const hasPermission = await canManageUsers(); | |
| if (!hasPermission) { | |
| throw new Error(`Unauthorized: Permission required to ${action}`); | |
| } | |
| } | |
| /** | |
| * Require permission to manage specific user or throw error | |
| */ | |
| export async function requireUserManagePermissionFor( | |
| targetUserId: string, | |
| action: string = "manage this user", | |
| ): Promise<void> { | |
| const hasPermission = await canManageUser(targetUserId); | |
| if (!hasPermission) { | |
| throw new Error(`Unauthorized: Permission required to ${action}`); | |
| } | |
| } | |
| /** | |
| * Get current user session or null | |
| */ | |
| export async function getCurrentUser() { | |
| try { | |
| const session = await getSession(); | |
| return session?.user || null; | |
| } catch { | |
| return null; | |
| } | |
| } | |
| /** | |
| * Check if user is editor or admin (can create/edit resources) | |
| */ | |
| export async function hasEditorPermission(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| // Check if user is admin or editor | |
| return session.user.role === "admin" || session.user.role === "editor"; | |
| } catch (error) { | |
| console.error("Error checking editor permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Get the role permissions based on user's role string | |
| */ | |
| function getRolePermissions(role: string | undefined | null): BetterAuthRole { | |
| const cleanRole = parseRoleString(role); | |
| switch (cleanRole) { | |
| case "admin": | |
| return admin as BetterAuthRole; | |
| case "editor": | |
| return editor as BetterAuthRole; | |
| case "user": | |
| default: | |
| return userRole as BetterAuthRole; | |
| } | |
| } | |
| /** | |
| * Check if role has specific permission for a resource | |
| */ | |
| function hasPermission( | |
| userRoleString: string | undefined | null, | |
| permission: | |
| | "use" | |
| | "create" | |
| | "list" | |
| | "delete" | |
| | "update" | |
| | "view" | |
| | "share", | |
| resource: "agent" | "workflow" | "mcp", | |
| ): boolean { | |
| const roleObject = getRolePermissions(userRoleString); | |
| // Validate role object structure | |
| if (!isBetterAuthRole(roleObject)) { | |
| console.error("Invalid role object structure"); | |
| return false; | |
| } | |
| const statements = roleObject.statements; | |
| const resourcePermissions = statements[resource] || []; | |
| return ( | |
| Array.isArray(resourcePermissions) && | |
| resourcePermissions.includes(permission) | |
| ); | |
| } | |
| /** | |
| * Check if user can create agents | |
| */ | |
| export async function canCreateAgent(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "create", "agent"); | |
| } catch (error) { | |
| console.error("Error checking agent create permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can edit agents | |
| */ | |
| export async function canEditAgent(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "update", "agent"); | |
| } catch (error) { | |
| console.error("Error checking agent edit permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can delete agents | |
| */ | |
| export async function canDeleteAgent(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "delete", "agent"); | |
| } catch (error) { | |
| console.error("Error checking agent delete permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can create workflows | |
| */ | |
| export async function canCreateWorkflow(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "create", "workflow"); | |
| } catch (error) { | |
| console.error("Error checking workflow create permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can edit workflows | |
| */ | |
| export async function canEditWorkflow(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "update", "workflow"); | |
| } catch (error) { | |
| console.error("Error checking workflow edit permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can delete workflows | |
| */ | |
| export async function canDeleteWorkflow(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "delete", "workflow"); | |
| } catch (error) { | |
| console.error("Error checking workflow delete permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can create MCP connections | |
| */ | |
| export async function canCreateMCP(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "create", "mcp"); | |
| } catch (error) { | |
| console.error("Error checking MCP create permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can edit MCP connections | |
| */ | |
| export async function canEditMCP(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "update", "mcp"); | |
| } catch (error) { | |
| console.error("Error checking MCP edit permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can change visibility of MCP connections | |
| */ | |
| export async function canChangeVisibilityMCP(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "share", "mcp"); | |
| } catch (error) { | |
| console.error("Error checking MCP visibility change permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can delete MCP connections | |
| */ | |
| export async function canDeleteMCP(): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| return hasPermission(session.user.role, "delete", "mcp"); | |
| } catch (error) { | |
| console.error("Error checking MCP delete permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Require editor permissions or throw error | |
| */ | |
| export async function requireEditorPermission( | |
| action: string = "perform this action", | |
| ): Promise<void> { | |
| const hasPermission = await hasEditorPermission(); | |
| if (!hasPermission) { | |
| throw new Error( | |
| `Unauthorized: Editor or Admin access required to ${action}`, | |
| ); | |
| } | |
| } | |
| /** | |
| * Check if user can manage a specific MCP server | |
| * Users can manage their own servers, admins can manage all | |
| */ | |
| export async function canManageMCPServer( | |
| mcpOwnerId: string, | |
| visibility: string = "private", | |
| ): Promise<boolean> { | |
| try { | |
| const session = await getSession(); | |
| if (!session?.user) return false; | |
| // Admins can manage all MCP servers | |
| if (session.user.role === "admin") return true; | |
| // Users can only manage their own private MCP servers | |
| if (session.user.id === mcpOwnerId && visibility === "private") return true; | |
| return false; | |
| } catch (error) { | |
| console.error("Error checking MCP management permission:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if user can share MCP servers (admin only) | |
| */ | |
| export async function canShareMCPServer(): Promise<boolean> { | |
| return await hasAdminPermission(); | |
| } | |