@shield-acl/react
Version:
Sistema ACL (Access Control List) inteligente e granular para aplicações React
353 lines (273 loc) • 7.29 kB
Markdown
# @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