UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 32.1 kB
{"version":3,"file":"use-permissions.cjs","sources":["../../../src/hooks/use-permissions.tsx"],"sourcesContent":["/**\n * @frank-auth/react - usePermissions Hook\n *\n * Comprehensive permissions hook that provides role-based access control (RBAC),\n * permission checking, and authorization utilities for multi-tenant applications.\n */\n\n'use client'\n\nimport {useCallback, useEffect, useMemo, useState} from 'react';\n\nimport type {UserPermissionAssignment, UserRoleAssignment,} from '@frank-auth/client';\n\nimport {useAuth} from './use-auth';\nimport {useConfig} from '@/provider';\n\nimport type {AuthError, PermissionContext,} from '../provider/types';\n\n// ============================================================================\n// Permission Hook Interface\n// ============================================================================\n\nexport interface UsePermissionsReturn {\n // Permission state\n permissions: string[];\n roles: string[];\n roleAssignments: UserRoleAssignment[];\n permissionAssignments: UserPermissionAssignment[];\n isLoaded: boolean;\n isLoading: boolean;\n error: AuthError | null;\n\n // Permission checking\n hasPermission: (permission: string, context?: PermissionContext) => boolean;\n hasRole: (role: string, context?: PermissionContext) => boolean;\n hasAnyPermission: (permissions: string[], context?: PermissionContext) => boolean;\n hasAllPermissions: (permissions: string[], context?: PermissionContext) => boolean;\n can: (action: string, resource: string, context?: PermissionContext) => boolean;\n\n // Context-aware checking\n canInOrganization: (permission: string, organizationId?: string) => boolean;\n canInApplication: (permission: string, applicationId: string) => boolean;\n hasSystemPermission: (permission: string) => boolean;\n\n // Role checking\n isSystemAdmin: boolean;\n isOrganizationOwner: (organizationId?: string) => boolean;\n isOrganizationAdmin: (organizationId?: string) => boolean;\n isOrganizationMember: (organizationId?: string) => boolean;\n\n // Permission management\n refreshPermissions: () => Promise<void>;\n\n // Convenience methods\n requirePermission: (permission: string, context?: PermissionContext) => void;\n requireRole: (role: string, context?: PermissionContext) => void;\n requireAnyPermission: (permissions: string[], context?: PermissionContext) => void;\n requireAllPermissions: (permissions: string[], context?: PermissionContext) => void;\n\n // Current context\n currentContext: PermissionContext;\n setContext: (context: PermissionContext) => void;\n}\n\n// ============================================================================\n// Permission Actions and Resources\n// ============================================================================\n\nexport const PERMISSION_ACTIONS = {\n // Generic CRUD actions\n CREATE: 'create',\n READ: 'read',\n UPDATE: 'update',\n DELETE: 'delete',\n\n // User management actions\n INVITE: 'invite',\n REMOVE: 'remove',\n SUSPEND: 'suspend',\n ACTIVATE: 'activate',\n\n // Admin actions\n MANAGE: 'manage',\n CONFIGURE: 'configure',\n AUDIT: 'audit',\n\n // Special actions\n TRANSFER: 'transfer',\n EXPORT: 'export',\n IMPORT: 'import',\n} as const;\n\nexport const PERMISSION_RESOURCES = {\n // User resources\n USER: 'user',\n USER_PROFILE: 'user:profile',\n USER_SESSION: 'user:session',\n USER_MFA: 'user:mfa',\n\n // Organization resources\n ORGANIZATION: 'organization',\n ORGANIZATION_SETTINGS: 'organization:settings',\n ORGANIZATION_MEMBERS: 'organization:members',\n ORGANIZATION_INVITATIONS: 'organization:invitations',\n ORGANIZATION_BILLING: 'organization:billing',\n ORGANIZATION_AUDIT: 'organization:audit',\n\n // Application resources\n APPLICATION: 'application',\n APPLICATION_SETTINGS: 'application:settings',\n APPLICATION_USERS: 'application:users',\n APPLICATION_SESSIONS: 'application:sessions',\n\n // System resources\n SYSTEM: 'system',\n SYSTEM_USERS: 'system:users',\n SYSTEM_ORGANIZATIONS: 'system:organizations',\n SYSTEM_SETTINGS: 'system:settings',\n SYSTEM_BILLING: 'system:billing',\n SYSTEM_AUDIT: 'system:audit',\n} as const;\n\nexport const SYSTEM_ROLES = {\n SUPER_ADMIN: 'system:super_admin',\n ADMIN: 'system:admin',\n SUPPORT: 'system:support',\n} as const;\n\nexport const ORGANIZATION_ROLES = {\n OWNER: 'organization:owner',\n ADMIN: 'organization:admin',\n MEMBER: 'organization:member',\n BILLING: 'organization:billing',\n SUPPORT: 'organization:support',\n} as const;\n\n// ============================================================================\n// Main usePermissions Hook\n// ============================================================================\n\n/**\n * Comprehensive permissions hook for role-based access control\n *\n * @example Basic permission checking\n * ```tsx\n * import { usePermissions } from '@frank-auth/react';\n *\n * function UserManagement() {\n * const {\n * hasPermission,\n * canInOrganization,\n * isOrganizationAdmin,\n * requirePermission\n * } = usePermissions();\n *\n * // Simple permission check\n * if (!hasPermission('organization:members:manage')) {\n * return <div>Access denied</div>;\n * }\n *\n * // Organization-specific check\n * const canManageMembers = canInOrganization('members:manage');\n *\n * // Role-based check\n * const isAdmin = isOrganizationAdmin();\n *\n * const handleDeleteUser = () => {\n * // Throws if permission not granted\n * requirePermission('organization:members:delete');\n * // Delete user logic...\n * };\n *\n * return (\n * <div>\n * {canManageMembers && (\n * <button onClick={handleDeleteUser}>Delete User</button>\n * )}\n * {isAdmin && (\n * <button>Admin Actions</button>\n * )}\n * </div>\n * );\n * }\n * ```\n *\n * @example Context-aware permissions\n * ```tsx\n * function MultiContextComponent() {\n * const {\n * can,\n * hasSystemPermission,\n * canInApplication,\n * setContext\n * } = usePermissions();\n *\n * // Action-resource based checking\n * const canCreateUsers = can('create', 'user');\n * const canDeleteOrg = can('delete', 'organization');\n *\n * // System-level permissions\n * const canManageSystem = hasSystemPermission('system:manage');\n *\n * // Application-specific permissions\n * const canConfigureApp = canInApplication('configure', 'app_123');\n *\n * // Switch context\n * const switchToOrgContext = () => {\n * setContext({\n * type: 'organization',\n * organizationId: 'org_456'\n * });\n * };\n *\n * return (\n * <div>\n * {canCreateUsers && <button>Create User</button>}\n * {canDeleteOrg && <button>Delete Organization</button>}\n * {canManageSystem && <button>System Settings</button>}\n * {canConfigureApp && <button>App Configuration</button>}\n * <button onClick={switchToOrgContext}>Switch Context</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example Permission guards\n * ```tsx\n * function PermissionGuardExample() {\n * const { hasAnyPermission, hasAllPermissions } = usePermissions();\n *\n * // User needs at least one of these permissions\n * const canAccess = hasAnyPermission([\n * 'organization:read',\n * 'organization:members:read'\n * ]);\n *\n * // User needs all of these permissions\n * const canFullyManage = hasAllPermissions([\n * 'organization:manage',\n * 'organization:members:manage',\n * 'organization:billing:manage'\n * ]);\n *\n * if (!canAccess) {\n * return <div>You don't have access to this section</div>;\n * }\n *\n * return (\n * <div>\n * <h1>Organization Dashboard</h1>\n * {canFullyManage && (\n * <div>Full management controls available</div>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions(): UsePermissionsReturn {\n const {user, activeOrganization, sdk} = useAuth();\n \n const [permissions, setPermissions] = useState<string[]>([]);\n const [roles, setRoles] = useState<string[]>([]);\n const [roleAssignments, setRoleAssignments] = useState<UserRoleAssignment[]>([]);\n const [permissionAssignments, setPermissionAssignments] = useState<UserPermissionAssignment[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n // Current permission context\n const [currentContext, setCurrentContext] = useState<PermissionContext>({\n type: 'system',\n organizationId: activeOrganization?.id,\n });\n\n // Error handler\n const handleError = useCallback((err: any) => {\n const authError: AuthError = {\n code: err.code || 'UNKNOWN_ERROR',\n message: err.message || 'An unknown error occurred',\n details: err.details,\n field: err.field,\n };\n setError(authError);\n }, []);\n\n // Load user permissions and roles\n const loadPermissions = useCallback(async () => {\n if (!sdk.auth || !user) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n // Load user roles and permissions\n const [userRoles, userPermissions] = await Promise.all([\n sdk.auth.getUserRoles(user.id),\n sdk.auth.getUserPermissions(user.id),\n ]);\n\n setRoleAssignments(userRoles);\n setPermissionAssignments(userPermissions);\n\n // Extract role names and permission names\n const roleNames = userRoles.map(ra => ra.role.name);\n const permissionNames = userPermissions.map(pa => pa.permission.name);\n\n // Also include permissions from roles\n const rolePermissions = userRoles.flatMap(ra =>\n ra.role.permissions?.map(p => p.name) || []\n );\n\n setRoles(roleNames);\n setPermissions([...new Set([...permissionNames, ...rolePermissions])]);\n\n } catch (err) {\n handleError(err);\n } finally {\n setIsLoading(false);\n }\n }, [sdk.auth, user, handleError]);\n\n // Load permissions when user or organization changes\n useEffect(() => {\n loadPermissions();\n }, [loadPermissions]);\n\n // Update context when organization changes\n useEffect(() => {\n if (activeOrganization) {\n setCurrentContext(prev => ({\n ...prev,\n organizationId: activeOrganization.id,\n }));\n }\n }, [activeOrganization]);\n\n // Permission checking functions\n const hasPermission = useCallback((permission: string, context?: PermissionContext): boolean => {\n const checkContext = context || currentContext;\n\n // Check direct permissions\n const hasDirectPermission = permissionAssignments.some(pa => {\n if (pa.permission.name !== permission) return false;\n\n // Check context match\n switch (checkContext.type) {\n case 'system':\n return pa.contextType === 'system';\n case 'organization':\n return pa.contextType === 'organization' &&\n pa.resourceId === checkContext.organizationId;\n case 'application':\n return pa.contextType === 'application' &&\n pa.resourceId === checkContext.applicationId;\n default:\n return false;\n }\n });\n\n if (hasDirectPermission) return true;\n\n // Check permissions from roles\n const hasRolePermission = roleAssignments.some(ra => {\n // Check context match for role\n let contextMatch = false;\n switch (checkContext.type) {\n case 'system':\n contextMatch = ra.contextType === 'system';\n break;\n case 'organization':\n contextMatch = ra.contextType === 'organization' &&\n ra.resourceId === checkContext.organizationId;\n break;\n case 'application':\n contextMatch = ra.contextType === 'application' &&\n ra.resourceId === checkContext.applicationId;\n break;\n }\n\n if (!contextMatch) return false;\n\n // Check if role has the permission\n return ra.role.permissions?.some(p => p.name === permission) || false;\n });\n\n return hasRolePermission;\n }, [permissionAssignments, roleAssignments, currentContext]);\n\n const hasRole = useCallback((role: string, context?: PermissionContext): boolean => {\n const checkContext = context || currentContext;\n\n return roleAssignments.some(ra => {\n if (ra.role.name !== role) return false;\n\n // Check context match\n switch (checkContext.type) {\n case 'system':\n return ra.contextType === 'system';\n case 'organization':\n return ra.contextType === 'organization' &&\n ra.resourceId === checkContext.organizationId;\n case 'application':\n return ra.contextType === 'application' &&\n ra.resourceId === checkContext.applicationId;\n default:\n return false;\n }\n });\n }, [roleAssignments, currentContext]);\n\n const hasAnyPermission = useCallback((permissionList: string[], context?: PermissionContext): boolean => {\n return permissionList.some(permission => hasPermission(permission, context));\n }, [hasPermission]);\n\n const hasAllPermissions = useCallback((permissionList: string[], context?: PermissionContext): boolean => {\n return permissionList.every(permission => hasPermission(permission, context));\n }, [hasPermission]);\n\n const can = useCallback((action: string, resource: string, context?: PermissionContext): boolean => {\n const permission = `${resource}:${action}`;\n return hasPermission(permission, context);\n }, [hasPermission]);\n\n // Context-aware checking\n const canInOrganization = useCallback((permission: string, organizationId?: string): boolean => {\n const orgId = organizationId || activeOrganization?.id;\n if (!orgId) return false;\n\n return hasPermission(permission, {\n type: 'organization',\n organizationId: orgId,\n });\n }, [hasPermission, activeOrganization]);\n\n const canInApplication = useCallback((permission: string, applicationId: string): boolean => {\n return hasPermission(permission, {\n type: 'application',\n applicationId,\n });\n }, [hasPermission]);\n\n const hasSystemPermission = useCallback((permission: string): boolean => {\n return hasPermission(permission, {type: 'system'});\n }, [hasPermission]);\n\n // Role checking helpers\n const isSystemAdmin = useMemo(() => {\n return hasRole(SYSTEM_ROLES.SUPER_ADMIN) || hasRole(SYSTEM_ROLES.ADMIN);\n }, [hasRole]);\n\n const isOrganizationOwner = useCallback((organizationId?: string): boolean => {\n const orgId = organizationId || activeOrganization?.id;\n if (!orgId) return false;\n\n return hasRole(ORGANIZATION_ROLES.OWNER, {\n type: 'organization',\n organizationId: orgId,\n });\n }, [hasRole, activeOrganization]);\n\n const isOrganizationAdmin = useCallback((organizationId?: string): boolean => {\n const orgId = organizationId || activeOrganization?.id;\n if (!orgId) return false;\n\n return hasRole(ORGANIZATION_ROLES.ADMIN, {\n type: 'organization',\n organizationId: orgId,\n }) || isOrganizationOwner(orgId);\n }, [hasRole, isOrganizationOwner, activeOrganization]);\n\n const isOrganizationMember = useCallback((organizationId?: string): boolean => {\n const orgId = organizationId || activeOrganization?.id;\n if (!orgId) return false;\n\n return roleAssignments.some(ra =>\n ra.contextType === 'organization' &&\n ra.resourceId === orgId\n );\n }, [roleAssignments, activeOrganization]);\n\n // Requirement functions (throw if not met)\n const requirePermission = useCallback((permission: string, context?: PermissionContext): void => {\n if (!hasPermission(permission, context)) {\n throw new Error(`Permission required: ${permission}`);\n }\n }, [hasPermission]);\n\n const requireRole = useCallback((role: string, context?: PermissionContext): void => {\n if (!hasRole(role, context)) {\n throw new Error(`Role required: ${role}`);\n }\n }, [hasRole]);\n\n const requireAnyPermission = useCallback((permissionList: string[], context?: PermissionContext): void => {\n if (!hasAnyPermission(permissionList, context)) {\n throw new Error(`One of these permissions required: ${permissionList.join(', ')}`);\n }\n }, [hasAnyPermission]);\n\n const requireAllPermissions = useCallback((permissionList: string[], context?: PermissionContext): void => {\n if (!hasAllPermissions(permissionList, context)) {\n throw new Error(`All of these permissions required: ${permissionList.join(', ')}`);\n }\n }, [hasAllPermissions]);\n\n // Refresh permissions\n const refreshPermissions = useCallback(async (): Promise<void> => {\n await loadPermissions();\n }, [loadPermissions]);\n\n // Set context\n const setContext = useCallback((context: PermissionContext): void => {\n setCurrentContext(context);\n }, []);\n\n return {\n // Permission state\n permissions,\n roles,\n roleAssignments,\n permissionAssignments,\n isLoaded: !!user,\n isLoading,\n error,\n\n // Permission checking\n hasPermission,\n hasRole,\n hasAnyPermission,\n hasAllPermissions,\n can,\n\n // Context-aware checking\n canInOrganization,\n canInApplication,\n hasSystemPermission,\n\n // Role checking\n isSystemAdmin,\n isOrganizationOwner,\n isOrganizationAdmin,\n isOrganizationMember,\n\n // Permission management\n refreshPermissions,\n\n // Convenience methods\n requirePermission,\n requireRole,\n requireAnyPermission,\n requireAllPermissions,\n\n // Current context\n currentContext,\n setContext,\n };\n}\n\n// ============================================================================\n// Specialized Permission Hooks\n// ============================================================================\n\n/**\n * Hook for organization-specific permissions\n */\nexport function useOrganizationPermissions(organizationId?: string) {\n const {\n canInOrganization,\n isOrganizationOwner,\n isOrganizationAdmin,\n isOrganizationMember,\n hasRole,\n activeOrganization,\n } = usePermissions();\n\n const orgId = organizationId || activeOrganization?.id;\n\n return {\n organizationId: orgId,\n isOwner: isOrganizationOwner(orgId),\n isAdmin: isOrganizationAdmin(orgId),\n isMember: isOrganizationMember(orgId),\n\n // Common organization permissions\n canManageMembers: canInOrganization('organization:members:manage', orgId),\n canInviteMembers: canInOrganization('organization:members:invite', orgId),\n canRemoveMembers: canInOrganization('organization:members:remove', orgId),\n canManageSettings: canInOrganization('organization:settings:manage', orgId),\n canManageBilling: canInOrganization('organization:billing:manage', orgId),\n canViewAudit: canInOrganization('organization:audit:read', orgId),\n canDeleteOrganization: canInOrganization('organization:delete', orgId),\n\n // Role checking for organization\n hasOrganizationRole: (role: string) => hasRole(role, {\n type: 'organization',\n organizationId: orgId,\n }),\n };\n}\n\n/**\n * Hook for system-level permissions\n */\nexport function useSystemPermissions() {\n const {\n hasSystemPermission,\n isSystemAdmin,\n hasRole,\n userType,\n } = usePermissions();\n\n // System permissions are only available to internal users\n const canAccessSystem = userType === 'internal';\n\n return {\n canAccessSystem,\n isSystemAdmin,\n\n // Common system permissions\n canManageUsers: canAccessSystem && hasSystemPermission('system:users:manage'),\n canManageOrganizations: canAccessSystem && hasSystemPermission('system:organizations:manage'),\n canManageSystem: canAccessSystem && hasSystemPermission('system:manage'),\n canViewSystemAudit: canAccessSystem && hasSystemPermission('system:audit:read'),\n canManageBilling: canAccessSystem && hasSystemPermission('system:billing:manage'),\n\n // Role checking for system\n hasSystemRole: (role: string) => hasRole(role, {type: 'system'}),\n isSuperAdmin: hasRole(SYSTEM_ROLES.SUPER_ADMIN, {type: 'system'}),\n isSupport: hasRole(SYSTEM_ROLES.SUPPORT, {type: 'system'}),\n };\n}\n\n/**\n * Hook for permission-based conditional rendering\n */\nexport function usePermissionGuard() {\n const {\n hasPermission,\n hasRole,\n hasAnyPermission,\n hasAllPermissions,\n requirePermission,\n requireRole,\n } = usePermissions();\n\n const PermissionGuard = useCallback(({\n permission,\n role,\n anyPermissions,\n allPermissions,\n context,\n fallback = null,\n children,\n }: {\n permission?: string;\n role?: string;\n anyPermissions?: string[];\n allPermissions?: string[];\n context?: PermissionContext;\n fallback?: React.ReactNode;\n children: React.ReactNode;\n }) => {\n let hasAccess = true;\n\n if (permission) {\n hasAccess = hasAccess && hasPermission(permission, context);\n }\n\n if (role) {\n hasAccess = hasAccess && hasRole(role, context);\n }\n\n if (anyPermissions) {\n hasAccess = hasAccess && hasAnyPermission(anyPermissions, context);\n }\n\n if (allPermissions) {\n hasAccess = hasAccess && hasAllPermissions(allPermissions, context);\n }\n\n return hasAccess ? <>{children}</> : <>{fallback}</>;\n }, [hasPermission, hasRole, hasAnyPermission, hasAllPermissions]);\n\n return {\n PermissionGuard,\n requirePermission,\n requireRole,\n };\n}"],"names":["PERMISSION_ACTIONS","PERMISSION_RESOURCES","SYSTEM_ROLES","ORGANIZATION_ROLES","usePermissions","user","activeOrganization","sdk","useAuth","permissions","setPermissions","useState","roles","setRoles","roleAssignments","setRoleAssignments","permissionAssignments","setPermissionAssignments","isLoading","setIsLoading","error","setError","currentContext","setCurrentContext","handleError","useCallback","err","authError","loadPermissions","userRoles","userPermissions","roleNames","ra","permissionNames","pa","rolePermissions","p","useEffect","prev","hasPermission","permission","context","checkContext","contextMatch","hasRole","role","hasAnyPermission","permissionList","hasAllPermissions","can","action","resource","canInOrganization","organizationId","orgId","canInApplication","applicationId","hasSystemPermission","isSystemAdmin","useMemo","isOrganizationOwner","isOrganizationAdmin","isOrganizationMember","requirePermission","requireRole","requireAnyPermission","requireAllPermissions","refreshPermissions","setContext","useOrganizationPermissions","useSystemPermissions","userType","canAccessSystem","usePermissionGuard","anyPermissions","allPermissions","fallback","children","hasAccess","jsx","Fragment"],"mappings":"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"}