349 lines
9.6 KiB
Markdown
349 lines
9.6 KiB
Markdown
# 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 2.3.3
|
|
- **Frontend**: Bootstrap 5, HTML5, CSS3, JavaScript
|
|
- **Database**: SQLite + SQLAlchemy 2.0.21
|
|
- **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 |