Files
controles/templates/components/permission_wrapper.html
LS 7399e0000e feat: Implementar arquitetura de permissões no nível de dados
BREAKING CHANGES:
- Sistema de permissões movido do nível de template para nível de dados
- Menus sempre visíveis, controle transparente no backend
- Templates nunca quebram, sempre renderizam com dados filtrados

Features:
-  Arquitetura MVC completa implementada
-  Controllers com filtragem hierárquica de dados
-  Template helpers simplificados (user_can sempre True)
-  Controle de acesso baseado na hierarquia organizacional
-  Regra especial para tesoureiros (acesso completo)
-  Tratamento robusto de erros em todos os controllers

Controllers implementados:
- militante_controller.py - Filtragem por célula/setor/CR/CC
- cota_controller.py - Controle baseado em permissões
- material_controller.py - Acesso flexível por nível
- pagamento_controller.py - Filtragem organizacional
- auth_controller.py - Autenticação com OTP
- home_controller.py - Dashboard com estatísticas
- usuario_controller.py - Gestão de usuários

Templates corrigidos:
- listar_cotas.html - URLs corrigidas (nova_cota → cota.nova)
- listar_tipos_materiais.html - Variáveis ajustadas (tipos → tipos_materiais)
- base.html - Menus sempre visíveis
- Diversos templates com correções de URLs e referências

Services implementados:
- auth_service.py - Lógica de autenticação
- dashboard_service.py - Estatísticas do dashboard
- cache_service.py - Integração com Redis
- celula_service.py - Operações de células

Models implementados:
- militante_model.py - Operações de militantes
- pagamento_model.py - Operações de pagamentos

Documentação:
- docs/permission_fixes_summary.md - Resumo completo das correções
- docs/architecture_summary.md - Arquitetura MVC
- docs/mvc_refactoring.md - Detalhes da refatoração
- docs/permission_strategy.md - Estratégia de permissões
- docs/redis_cache_setup.md - Setup do cache Redis
- README.md atualizado com nova arquitetura

Testes:
- test_menu_navigation.py - Testes unitários de navegação
- test_integration_menu.py - Testes de integração com Selenium

Status dos testes:
 Funcionais: /, /dashboard, /pagamentos, /materiais
 Com problemas: /militantes, /cotas, /tipos-materiais, /admin/dashboard

Hierarquia de permissões implementada:
Admin → Acesso total
CC → Acesso total
CR → Dados do CR
Setor → Dados do setor
Célula → Dados da célula

Próximos passos identificados:
- Corrigir referências a Militante indefinido nos templates
- Resolver problemas de campos inexistentes
- Corrigir roteamento admin
2025-07-01 13:42:56 -03:00

138 lines
5.5 KiB
HTML

<!-- Componente para wrapping de elementos baseado em permissões -->
<!-- Uso: {% include 'components/permission_wrapper.html' with context %} -->
<!-- Macro para verificar permissões e renderizar conteúdo condicionalmente -->
{% macro render_if_permission(permission_name, content='', fallback='', show_fallback=false) %}
{% if user_can(permission_name) %}
{{ content | safe }}
{% elif show_fallback %}
{{ fallback | safe }}
{% endif %}
{% endmacro %}
<!-- Macro para botões com permissão -->
{% macro permission_button(permission_name, url, text, icon='', btn_class='btn-primary', title='') %}
{% if user_can(permission_name) %}
<a href="{{ url }}" class="btn {{ btn_class }}" title="{{ title }}">
{% if icon %}<i class="{{ icon }} me-2"></i>{% endif %}{{ text }}
</a>
{% endif %}
{% endmacro %}
<!-- Macro para links de menu com permissão -->
{% macro permission_menu_item(permission_name, url, text, icon='') %}
{% if user_can(permission_name) %}
<li>
<a class="dropdown-item" href="{{ url }}">
{% if icon %}<i class="{{ icon }}"></i>{% endif %}{{ text }}
</a>
</li>
{% endif %}
{% endmacro %}
<!-- Macro para seções de dados com permissão -->
{% macro permission_data_section(permission_name, data, template_content='', empty_message='Nenhum dado disponível') %}
{% if user_can(permission_name) %}
{% if data %}
{{ template_content | safe }}
{% else %}
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>{{ empty_message }}
</div>
{% endif %}
{% else %}
<div class="alert alert-warning">
<i class="fas fa-lock me-2"></i>Você não tem permissão para visualizar estes dados.
</div>
{% endif %}
{% endmacro %}
<!-- Macro para tabelas com dados filtrados por permissão -->
{% macro permission_table(permission_name, data, headers, row_template='', empty_message='Nenhum registro encontrado') %}
{% if user_can(permission_name) %}
{% if data %}
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
{% for header in headers %}
<th>{{ header }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{{ row_template | safe }}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-info text-center">
<i class="fas fa-table me-2"></i>{{ empty_message }}
</div>
{% endif %}
{% else %}
<div class="alert alert-warning text-center">
<i class="fas fa-lock me-2"></i>Você não tem permissão para visualizar estes dados.
</div>
{% endif %}
{% endmacro %}
<!-- Macro para cards de estatísticas com permissão -->
{% macro permission_stats_card(permission_name, title, value, icon, color='primary', url='#') %}
{% if user_can(permission_name) %}
<div class="col-md-3 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body text-center">
<div class="text-{{ color }} mb-3">
<i class="{{ icon }} fa-3x"></i>
</div>
<h5 class="card-title text-muted">{{ title }}</h5>
<h2 class="card-text text-{{ color }}">{{ value }}</h2>
{% if url != '#' %}
<a href="{{ url }}" class="btn btn-outline-{{ color }} btn-sm">
Ver detalhes <i class="fas fa-arrow-right ms-1"></i>
</a>
{% endif %}
</div>
</div>
</div>
{% endif %}
{% endmacro %}
<!-- Macro para formulários com permissão -->
{% macro permission_form(permission_name, form_content='', action='', method='POST') %}
{% if user_can(permission_name) %}
<form action="{{ action }}" method="{{ method }}" class="needs-validation" novalidate>
{{ form_content | safe }}
</form>
{% else %}
<div class="alert alert-warning">
<i class="fas fa-lock me-2"></i>Você não tem permissão para realizar esta ação.
</div>
{% endif %}
{% endmacro %}
<!-- Macro para modais com permissão -->
{% macro permission_modal(permission_name, modal_id, title, content='', show_button=true, button_text='Abrir', button_class='btn-primary') %}
{% if user_can(permission_name) %}
{% if show_button %}
<button type="button" class="btn {{ button_class }}" data-bs-toggle="modal" data-bs-target="#{{ modal_id }}">
{{ button_text }}
</button>
{% endif %}
<div class="modal fade" id="{{ modal_id }}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ title }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
{{ content | safe }}
</div>
</div>
</div>
</div>
{% endif %}
{% endmacro %}