# Sistema de Controles OCI Sistema web para gestão organizacional (militantes, estrutura hierárquica, cotas, pagamentos e materiais), com autenticação por senha + OTP, permissões RBAC e cache Redis. ## 🔧 Tecnologias - **Backend**: Flask 3.0.2 - **Frontend**: Bootstrap 5, HTML5, CSS3, JavaScript - **Database**: SQLite + SQLAlchemy 2.0+ (>= 2.0.36) - **Cache**: Redis 7.4.4 (opcional fora do Docker) - **Authentication**: Flask-Login + OTP (pyotp) - **Container**: Docker + Docker Compose - **Server**: Gunicorn ## 🚀 Status Atual - Sistema com Arquitetura de Permissões (RBAC) - Sistema de permissões implementado no nível de dados - Estrutura organizacional completa - Aplicação Flask rodando com Docker - Redis cache integrado e funcionando - Banco de dados SQLite inicializado - Usuário admin configurado com OTP - 30 militantes de teste criados - Menus sempre visíveis, controle transparente ## 🏗️ Arquitetura de Permissões O sistema implementa uma estratégia de controle de permissões no **nível de dados**, garantindo que: - **Menus permanecem sempre visíveis** - Não há restrições na interface - **Dados são filtrados por hierarquia** - Admin → CC → CR → Setor → Célula - **Templates nunca quebram** - Sempre renderizam, mesmo com dados vazios ## ⚙️ Instalação - Pré-requisitos - Docker + Docker Compose (para fluxo com containers) - Porta 5000 disponível para a aplicação - Porta 6379 disponível para Redis - Python 3.10+ (recomendado) - `pip` - `make` ## 🐳 Primeiro Inicio com Docker (recomendado) ### 0. Clone o repositorio ```bash git clone git@gitea.comunatec.org:comunatec/controles.git cd controles ``` ### 1. Resete o banco ```bash make docker-db-reset ``` ### 2. Adicione dados fakes para testes (opcional) ```bash make docker-db-seed-fake ``` ### 3. Subir aplicação ```bash make dev-up ``` ### 4. Acompanhar logs - Aplicação: `logs/controles.log` - Cache: `logs/cache.log` - Docker: `docker-compose logs` ```bash make docker-logs # Toda a aplicação docker-compose logs redis # Somente o redis make cache-status # INFO do redis ``` ### 5. Descer aplicação ```bash make dev-down ``` ## 🐍 Primeiro Inicio - Execução Local (Sem Docker) ### 0. Clone o repositorio ```bash git clone git@gitea.comunatec.org:comunatec/controles.git cd controles ``` ### 1. Ambiente Python ```bash python -m venv .venv source .venv/bin/activate # Linux/Mac # ou venv\Scripts\activate # Windows pip install -r requirements.txt ``` ### 2. Crie o `.env` na raiz Exemplo: ```env # Usando OTP padrão para não trocar toda hora no desenvolvimento ADMIN_OTP_SECRET=JBSWY3DPEHPK3PXP # Para usar o mesmo banco que o Docker (Linux/WSL permite bind-mount) DATABASE_URL=sqlite:///data/database.db REDIS_URL=redis://redis:6379/0 FLASK_APP=app.py FLASK_ENV=development SECRET_KEY=troque_esta_chave APP_UID=1000 APP_GID=1000 MAIL_SERVER=seu_servidor_smtp MAIL_PORT=587 MAIL_USE_TLS=True MAIL_USERNAME=seu_email MAIL_PASSWORD=sua_senha ``` Se Redis não estiver disponível localmente, a aplicação continua rodando sem cache. ### 3. Inicialize o banco e rode ```bash make db-reset make db-seed-fake # opcional make run # ou make run-gunicorn # server de produção ``` ## 🔐 Acesso ao Sistema ### Credenciais do Admin - **URL**: http://localhost:5000 - **Usuário**: admin - **Senha**: admin123 - **OTP Secret**: JBSWY3DPEHPK3PXP ### Configuração OTP 1. Instale um aplicativo autenticador (Google Authenticator, Microsoft Authenticator) 2. Configure manualmente: - Descrição da chave (Codinome): Controles-OCI-admin - Segredo OTP (Sua Chave): JBSWY3DPEHPK3PXP - Tipo: TOTP - Algoritmo: SHA1 - Dígitos: 6 - Intervalo: 30 segundos **OU** use o QR Code gerado em `/tmp/admin_qr.png` ou `/data/admin_qr.png` ou `admin_qr.png`. PS: Google Authenticator só tem "Codinome" e "Sua Chave" de config, e tá tudo bem. ## Testes Automatizados ```bash # ambiente já configurado pip install -r tests/requirements-test.txt pytest ``` Também existe `run_tests.sh`, que monta um venv e executa a suíte automaticamente. - TODO: Talvez trocar o nome para venv_test ## 📁 Estrutura de arquivos O sistema busca seguir padrão MVC (Model-View-Controller), atualmente está: ``` controles/ ├── controllers/ # Controladores (lógica de rotas) ├── data/ # Banco de dados (e talvez qr_code admin) ├── docs/ # Documentações da arquitetura ├── functions/ # Funções utilitárias ├── logs/ # Logs de aplicação, redis... ├── migrations/ # Alterações de banco para não perder dados (produção) ├── models/ # Modelos (operações de banco) ├── routes/ # Rotas de aplicação ├── scripts/ # Scripts de gerenciamento ├── services/ # Serviços (lógica de negócio) ├── sql/ # Migrate para o rbac ├── static/ # Arquivos estáticos (icon/css/js) ├── templates/ # Views (templates HTML) ├── tests/ # Testes automatizados ├── utils/ # Funções sem regra de negócio ou dependencia de domínio ├── app.py # Ponto de entrada da aplicação ├── docker-compose.yml # Configuração Docker ├── Dockerfile # Imagem Docker └── requirements.txt # Dependências Python ``` - TODO: temos duas rotas (routes e controllers)? Unificar futuramente. - TODO: sql/migrate_db parece utilizar outro banco. ## 🤝 Contribuição 1. Crie uma branch para sua feature 2. Commit suas mudanças 3. Push sua branch para o Gitea 4. Outro camarada verifica a branch 5. Abra um Pull Request para a branch solicitada ## 📄 Licença Este projeto é privado para uso da OCI. ## 🔍 Troubleshooting 1. **Redis não conecta** ```bash docker-compose logs redis docker-compose restart redis ``` - Redis está indisponível localmente, mas app continua executando mesmo fora do Docker. 2. **Cache não funciona** ```bash make cache-status make cache-clear ``` 3. **Aplicação não inicia** ```bash docker-compose logs app docker-compose down && docker-compose up -d ``` 4. **Modificações no banco local não alteram o banco no Docker** - Linux bind mount no grupo de usuario errado: ajuste `APP_UID`/`APP_GID` no `Dockerfile` para seu grupo de usuarios (padrão=1000). - Docker com engine do Windows não consegue fazer bind mount, então alterações no banco local não refletem no banco do Docker, use as operações dentro do docker com make docker-* ou no windows instale o wsl2 e instale o Docker com apenas a engine "Docker no WSL". ## Estrutura de Permissões (RBAC) O sistema utiliza um sistema de controle de acesso baseado em papéis (RBAC), onde a verificação de ações são feitas com permissões (permission), e as permissões são pré-definidas com base em papeis (role). Que possuem a seguinte hierarquia: ### Níveis de Papéis 1. **Militante Básico** (Nível 1) - Visualizar próprios dados - Editar próprios dados - Visualizar dados da célula 2. **Secretário de Célula** (Nível 2) - Todas as permissões do Militante Básico - Gerenciar membros da célula - Criar membros na célula - Visualizar relatórios da célula 3. **Membro de Setor** (Nível 3) - Todas as permissões do Secretário de Célula - Visualizar relatórios do setor 4. **Secretário de Setor** (Nível 4) - Todas as permissões do Membro de Setor - Gerenciar células do setor - Criar células no setor 5. **Membro de CR** (Nível 5) - Todas as permissões do Secretário de Setor - Visualizar relatórios do CR 6. **Secretário de CR** (Nível 6) - Todas as permissões do Membro de CR - Gerenciar setores do CR - Criar setores no CR 7. **Membro do CC** (Nível 7) - Todas as permissões do Secretário de CR - Visualizar relatórios nacionais 8. **Secretário Geral** (Nível 8) - Todas as permissões do Membro do CC - Gerenciar CRs - Criar CRs - Configurar sistema ## Uso do RBAC ### Decoradores de Permissão O sistema fornece três decoradores para controle de acesso: 1. `@require_permission(permission_name)` - Verifica se o usuário tem uma permissão específica - Exemplo: `@require_permission('create_cell_member')` 2. `@require_role(role_name)` - Verifica se o usuário tem um papel específico - Exemplo: `@require_role('Secretário de Célula')` 3. `@require_minimum_role(min_level)` - Verifica se o usuário tem um papel com nível mínimo - Exemplo: `@require_minimum_role(Role.SECRETARIO_CR)` ### Verificando Permissões e Papéis no Código ```python # Verificar se um usuário tem uma permissão if user.has_permission(Permission.CREATE_CELL_MEMBER): # Faça algo # Verificar se um usuário tem um papel if user.has_role(Role.SECRETARIO_CELULA): # Faça algo # Obter o papel mais alto do usuário highest_role = user.get_highest_role() # Verificar se o usuário tem nível secretário de célula ou superior if user.has_minimum_role(Role.SECRETARIO_CELULA): # Faça algo ``` ## Documentação Complementar - Documentação complementar: `docs/README.md` - RBAC: `docs/rbac.md` - Estratégia de permissões: `docs/permission_strategy.md` - Redis e cache: `docs/redis_cache_setup.md` - Histórico de correções de permissões: `docs/permission_fixes_summary.md` ## Segurança - Todas as senhas são armazenadas com hash bcrypt - Sessões expiram após período de inatividade - Controle de acesso granular baseado em papéis - Proteção contra CSRF - Validação de entrada de dados