UNPKG

@shield-acl/react

Version:

Sistema ACL (Access Control List) inteligente e granular para aplicações React

353 lines (273 loc) 7.29 kB
# @shield-acl/react <div align="center"> <img src="https://raw.githubusercontent.com/andersondrosa/andersondrosa/refs/heads/main/images/shield-acl.png" alt="Shield ACL React" width="400" /> </div> <div align="center"> <p><strong>Componentes e hooks React para integração com Shield ACL</strong></p> <p>API declarativa e hooks modernos para controle de permissões em aplicações React.</p> </div> ## Características - 🎨 **Componentes Declarativos**: Can, Cannot, CanAny, CanAll para renderização condicional - 🪝 **Hooks Modernos**: useCan, usePermissions, useACL e muitos outros - ⚡ **Performance Otimizada**: Memoização inteligente e re-renders mínimos - 🎯 **TypeScript First**: Totalmente tipado com IntelliSense completo - 🔄 **React 19 Ready**: Compatível com React 16.8+ até React 19 - 🧩 **Extensível**: Sistema de componentes e hooks customizáveis ## Instalação ```bash npm install @shield-acl/react @shield-acl/core # ou yarn add @shield-acl/react @shield-acl/core # ou pnpm add @shield-acl/react @shield-acl/core ``` ## Uso Rápido ### 1. Setup do Provider ```tsx import { ACL } from '@shield-acl/core' import { ACLProvider } from '@shield-acl/react' // Criar instância do ACL const acl = new ACL() // Definir roles acl.defineRole({ name: 'admin', permissions: [{ action: '*', resource: '*' }] }) acl.defineRole({ name: 'user', permissions: [ { action: 'read', resource: 'posts' }, { action: 'create', resource: 'posts' } ] }) // Wrap sua aplicação function App() { const [user] = useState({ id: 1, roles: ['user'] }) return ( <ACLProvider acl={acl} user={user}> <YourApp /> </ACLProvider> ) } ``` ### 2. Componentes de Renderização Condicional ```tsx import { Can, Cannot, CanAny, CanAll } from '@shield-acl/react' function PostList() { return ( <div> {/* Renderiza apenas se pode ler posts */} <Can action="read" resource="posts"> <PostGrid /> </Can> {/* Renderiza se NÃO pode deletar */} <Cannot action="delete" resource="posts"> <p>Você não tem permissão para deletar posts</p> </Cannot> {/* Renderiza se tem QUALQUER uma das permissões */} <CanAny permissions={[ { action: 'create', resource: 'posts' }, { action: 'edit', resource: 'posts' } ]}> <EditButton /> </CanAny> {/* Renderiza se tem TODAS as permissões */} <CanAll permissions={[ { action: 'read', resource: 'users' }, { action: 'manage', resource: 'roles' } ]}> <AdminPanel /> </CanAll> </div> ) } ``` ### 3. Hooks ```tsx import { useCan, usePermissions, useACL } from '@shield-acl/react' function PostEditor({ post }) { // Hook básico const canEdit = useCan('edit', 'posts', { resource: { authorId: post.authorId } }) // Múltiplas permissões const permissions = usePermissions() const canModerate = permissions.some(p => p.action === 'moderate' && p.resource === 'posts' ) // Acesso direto ao ACL const { engine, user } = useACL() if (!canEdit) { return <p>Sem permissão para editar</p> } return <Editor post={post} /> } ``` ## API Completa ### Componentes #### `<Can>` Renderiza children apenas se o usuário tem a permissão. ```tsx <Can action="edit" resource="posts" context={{ authorId: userId }} fallback={<NoPermission />} > <EditForm /> </Can> ``` #### `<Cannot>` Renderiza children apenas se o usuário NÃO tem a permissão. ```tsx <Cannot action="delete" resource="posts"> <p>Você não pode deletar posts</p> </Cannot> ``` #### `<CanAny>` Renderiza se o usuário tem QUALQUER uma das permissões. ```tsx <CanAny permissions={[ { action: 'create', resource: 'posts' }, { action: 'edit', resource: 'posts' } ]}> <ActionButton /> </CanAny> ``` #### `<CanAll>` Renderiza se o usuário tem TODAS as permissões. ```tsx <CanAll permissions={[ { action: 'read', resource: 'analytics' }, { action: 'export', resource: 'reports' } ]}> <ExportButton /> </CanAll> ``` ### Hooks Principais #### `useCan(action, resource?, context?)` Verifica uma permissão específica. ```tsx const canDelete = useCan('delete', 'posts') const canEdit = useCan('edit', 'posts', { resource: post }) ``` #### `usePermissions()` Retorna todas as permissões do usuário atual. ```tsx const permissions = usePermissions() const isAdmin = permissions.some(p => p.action === '*') ``` #### `useACL()` Acesso direto ao engine ACL e usuário. ```tsx const { engine, user, setUser } = useACL() ``` #### `useEvaluate(action, resource?, context?)` Retorna resultado detalhado da avaliação. ```tsx const result = useEvaluate('publish', 'posts') // { allowed: true, reason: 'Matched role permission', matchedRule: {...} } ``` ### Hooks Avançados #### `useCanMultiple(permissions)` Verifica múltiplas permissões de uma vez. ```tsx const results = useCanMultiple([ { action: 'read', resource: 'posts' }, { action: 'create', resource: 'comments' } ]) // { 'read:posts': true, 'create:comments': false } ``` #### `useCanAny(permissions)` Verifica se tem QUALQUER uma das permissões. ```tsx const canEditContent = useCanAny([ { action: 'edit', resource: 'posts' }, { action: 'edit', resource: 'pages' } ]) ``` #### `useCanAll(permissions)` Verifica se tem TODAS as permissões. ```tsx const isFullAdmin = useCanAll([ { action: 'manage', resource: 'users' }, { action: 'manage', resource: 'roles' } ]) ``` #### `useRoleHierarchy()` Obtém a hierarquia completa de roles do usuário. ```tsx const hierarchy = useRoleHierarchy() // ['user', 'moderator', 'admin'] ``` #### `usePermissionChange(callback, dependencies)` Monitora mudanças nas permissões. ```tsx usePermissionChange(() => { console.log('Permissões mudaram!') }, ['posts']) ``` ## Componentes Utilitários ### HOC withCan ```tsx const ProtectedButton = withCan(Button, { action: 'delete', resource: 'posts', fallback: <DisabledButton /> }) ``` ### PermissionClass ```tsx <PermissionClass action="publish" resource="posts" className="can-publish" deniedClassName="cannot-publish" > <article className="post">...</article> </PermissionClass> ``` ## Performance ### Memoização Automática Todos os hooks são otimizados com memoização: ```tsx // Só re-renderiza se o resultado mudar const canEdit = useCan('edit', 'posts') // Context é memoizado profundamente const canDelete = useCan('delete', 'posts', { resource: { id: post.id, authorId: post.authorId } }) ``` ### Batch Updates Mudanças no usuário ou permissões são batched: ```tsx // Uma única re-renderização setUser({ ...user, roles: ['admin'], permissions: [...] }) ``` ## Testes ```bash # Rodar testes pnpm test # Coverage pnpm test:coverage # Watch mode pnpm test:watch ``` ## Documentação Adicional - [Documentação Completa dos Hooks](./docs/REACT-HOOKS.md) - Guia detalhado de todos os hooks disponíveis - [Roadmap de Implementação](./TODO-REACT-HOOKS.md) - Status de desenvolvimento dos hooks ## Compatibilidade - React 16.8+ (precisa de hooks) - React 17.x - React 18.x - React 19.x (totalmente compatível) - TypeScript 4.5+ ## Licença MIT © Anderson D. Rosa