# Estratégia de Controle de Permissões Granular
## Visão Geral
Esta documentação descreve a estratégia implementada para controle de permissões granular no sistema, permitindo que usuários vejam apenas dados e elementos para os quais têm autorização, sem quebrar templates ou causar erros.
## Arquitetura da Solução
### 1. Context Processors
**Arquivo**: `functions/template_helpers.py`
Os context processors disponibilizam automaticamente as permissões do usuário em todos os templates:
```python
# Disponível em todos os templates
user_can('permission_name') # Verifica permissão específica
user_has_role('role_name') # Verifica role específica
is_admin # Booleano se é admin
current_user_data # Dados completos do usuário
```
### 2. Template Filters
Filtros Jinja2 para uso direto nos templates:
```jinja2
{{ 'view_cell_data' | has_permission }}
{{ militantes | safe_data('view_cell_data', []) }}
{{ 'militante' | can_manage }}
```
### 3. Safe Data Controllers
Decorators que retornam dados vazios em caso de falta de permissão:
```python
@safe_data_controller(Permission.VIEW_CELL_DATA, empty_data={'militantes': []})
def listar():
# Lógica normal do controller
return render_template('template.html', militantes=militantes)
```
### 4. Template Macros
Componentes reutilizáveis para elementos condicionais:
```jinja2
{% from 'components/permission_wrapper.html' import permission_button %}
{{ permission_button('create_cell_member', url_for('militante.novo'), 'Novo Militante') }}
```
## Implementação por Camadas
### Camada 1: Controllers (Backend)
```python
# Filtragem de dados baseada em permissões
if current_user.is_admin:
# Admin vê todos os dados
militantes = query.all()
elif current_user.has_permission(Permission.VIEW_CR_REPORTS):
# CR vê apenas do seu CR
militantes = query.filter(cr_id=current_user.cr_id).all()
else:
# Sem permissão - lista vazia
militantes = []
```
### Camada 2: Templates (Frontend)
```jinja2
{% if user_can('view_cell_data') %}
{% endif %}
{% if user_can('view_cell_data') %}
{% if militantes %}
{% else %}
Nenhum dado disponível
{% endif %}
{% else %}
Sem permissão para visualizar
{% endif %}
```
### Camada 3: JavaScript (Interação)
```javascript
// Verificações no frontend
if (userPermissions.includes('manage_cell_members')) {
// Habilitar funcionalidades de edição
enableEditFeatures();
}
```
## Níveis de Permissão
### 1. Visualização de Dados
- `view_own_data`: Apenas próprios dados
- `view_cell_data`: Dados da célula
- `view_sector_reports`: Dados do setor
- `view_cr_reports`: Dados do CR
- `view_cc_reports`: Dados nacionais
### 2. Gerenciamento
- `manage_cell_members`: Gerenciar membros da célula
- `manage_sector_cells`: Gerenciar células do setor
- `create_cell_member`: Criar novos membros
- `register_cell_payment`: Registrar pagamentos
### 3. Administração
- `system_config`: Configurações do sistema
- `manage_cc_crs`: Gerenciar CRs
- `create_cc_cr`: Criar novos CRs
## Regras Especiais de Permissão
### 1. Administrador (Admin)
- **Acesso Total**: Tem todas as permissões do sistema
- **Bypass de Verificações**: Sempre retorna `true` para qualquer verificação de permissão
- **Acesso a Configurações**: Pode configurar o sistema e gerenciar usuários
### 2. Tesoureiro
- **Regra Especial**: Tesoureiro pode fazer tudo que o secretário da instância pode fazer
- **Permissões Automáticas**: Quando um militante tem responsabilidade de `TESOUREIRO`, automaticamente recebe:
- `view_cell_data`: Visualizar dados da célula
- `manage_cell_members`: Gerenciar membros da célula
- `create_cell_member`: Criar novos membros
- `view_cell_reports`: Visualizar relatórios da célula
- `manage_cell_reports`: Gerenciar relatórios da célula
- `register_cell_payment`: Registrar pagamentos da célula
### 3. Hierarquia de Instâncias
- **Célula** → **Setor** → **CR** → **CC**
- Usuários de níveis superiores têm acesso aos dados dos níveis inferiores
- Secretários podem gerenciar todas as instâncias de seu nível e abaixo
## Padrões de Uso
### 1. Menus Condicionais
```jinja2
{% if user_can('view_cell_data') %}
{% endif %}
```
## Tratamento de Erros
### 1. Dados Não Encontrados
```jinja2
{% if user_can('view_cell_data') %}
{% if data %}
{% else %}
Nenhum registro encontrado
{% endif %}
{% endif %}
```
### 2. Permissão Negada
```jinja2
{% if not user_can('required_permission') %}
Você não tem permissão para acessar esta funcionalidade
{% endif %}
```
### 3. Fallbacks Graceful
```python
# Controller com fallback
@safe_data_controller('view_cell_data', empty_data={'militantes': []})
def listar():
# Se não tiver permissão, retorna lista vazia
# Template não quebra, apenas não mostra dados
pass
```
## Vantagens da Estratégia
### 1. **Segurança por Camadas**
- Verificação no backend (controllers)
- Verificação no frontend (templates)
- Verificação no JavaScript (interação)
### 2. **Graceful Degradation**
- Templates nunca quebram
- Dados vazios em vez de erros
- Mensagens informativas para usuário
### 3. **Flexibilidade**
- Permissões granulares
- Fácil de estender
- Reutilização de componentes
### 4. **Manutenibilidade**
- Lógica centralizada
- Padrões consistentes
- Fácil debugging
### 5. **UX Melhorada**
- Interface adapta-se às permissões
- Sem elementos inacessíveis visíveis
- Feedback claro sobre limitações
## Exemplo Completo de Implementação
### Controller
```python
@militante_bp.route("/militantes")
@require_login
@safe_data_controller(Permission.VIEW_CELL_DATA, empty_data={'militantes': []})
def listar():
# Filtragem baseada em permissões
if current_user.is_admin:
militantes = query.all()
elif current_user.has_permission(Permission.VIEW_CELL_DATA):
militantes = query.filter(celula_id=current_user.celula_id).all()
else:
militantes = []
return render_template('militantes.html', militantes=militantes)
```
### Template
```jinja2
{% extends "base.html" %}
{% block content %}
Militantes
{% if user_can('create_cell_member') %}
Novo Militante
{% endif %}
{% if user_can('view_cell_data') %}
{% if militantes %}
Nome
Email
{% if user_can('manage_cell_members') %}
Ações
{% endif %}
{% for militante in militantes %}
{{ militante.nome }}
{{ militante.email }}
{% if user_can('manage_cell_members') %}
{% endif %}
{% endfor %}
{% else %}
Nenhum militante encontrado
{% endif %}
{% else %}
Você não tem permissão para visualizar militantes
{% endif %}
{% endblock %}
```
## Conclusão
Esta estratégia garante que:
1. **Nunca há erros de template** - dados sempre estão disponíveis (mesmo que vazios)
2. **Segurança é mantida** - usuários só veem o que podem
3. **UX é preservada** - interface clara sobre limitações
4. **Código é limpo** - padrões reutilizáveis e consistentes
5. **Manutenção é fácil** - lógica centralizada e bem documentada
6. **Tesoureiros têm poder adequado** - podem fazer tudo que secretários fazem
A implementação permite desenvolvimento ágil sem comprometer segurança ou experiência do usuário.