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
138 lines
5.5 KiB
HTML
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 %} |