135 lines
5.9 KiB
Markdown
135 lines
5.9 KiB
Markdown
# MeowSpool Backend — TODO
|
|
|
|
> Última atualização: 14/03/2026
|
|
|
|
---
|
|
|
|
## Crítico — Funcionalidades Quebradas
|
|
|
|
### Auth: Email e Reset de Senha
|
|
|
|
Todos os três handlers abaixo retornam `200 OK` sem executar nenhuma lógica real.
|
|
Dependem de infraestrutura compartilhada que ainda não existe (ver "Bloqueadores").
|
|
|
|
- [ ] **`forgot_password_handler`** (`src/adapters/inbound/auth_handler.rs:131`)
|
|
- Gerar token de reset seguro (UUID v4 ou CSPRNG)
|
|
- Salvar na tabela `password_reset_tokens` (ver migration abaixo)
|
|
- Enviar email com link de reset via serviço de email
|
|
- Token deve ter TTL de 1h e ser invalidado após uso
|
|
|
|
- [ ] **`verify_email_handler`** (`src/adapters/inbound/auth_handler.rs:138`)
|
|
- Validar token recebido contra tabela `email_verification_tokens`
|
|
- Chamar `user_repo.verify_email(user_id)` (método já implementado no repo)
|
|
- Marcar token como usado / deletar após validação
|
|
- Retornar `400 Bad Request` para token inválido ou expirado
|
|
|
|
- [ ] **`reset_password_handler`** (`src/adapters/inbound/auth_handler.rs:143`)
|
|
- Validar token recebido contra tabela `password_reset_tokens`
|
|
- Verificar TTL e se já foi usado
|
|
- Hash da nova senha com Argon2id
|
|
- Atualizar `password_hash` via `user_repo.update()`
|
|
- Invalidar token após uso
|
|
|
|
### Bloqueadores das features de Auth acima
|
|
|
|
- [ ] **Migration: `password_reset_tokens`**
|
|
|
|
```sql
|
|
CREATE TABLE password_reset_tokens (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
token TEXT NOT NULL UNIQUE,
|
|
used_at TIMESTAMPTZ,
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX ON password_reset_tokens (token);
|
|
```
|
|
|
|
- [ ] **Migration: `email_verification_tokens`**
|
|
|
|
```sql
|
|
CREATE TABLE email_verification_tokens (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
token TEXT NOT NULL UNIQUE,
|
|
used_at TIMESTAMPTZ,
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX ON email_verification_tokens (token);
|
|
```
|
|
|
|
- [ ] **Serviço de email** (`src/infrastructure/email_service.rs` — novo arquivo)
|
|
- Adicionar dependência: `lettre` (SMTP) ou integração com API (Resend, SendGrid, Mailgun)
|
|
- Adicionar vars de ambiente no `config.rs`: `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `EMAIL_FROM`
|
|
- Implementar `send_password_reset_email(to, reset_link)`
|
|
- Implementar `send_verification_email(to, code)`
|
|
|
|
### Perfil de Usuário
|
|
|
|
- [ ] **`update_me_handler`** (`src/adapters/inbound/user_handler.rs:64`)
|
|
- Handler valida formato de email mas não persiste nada
|
|
- Implementar chamada a `user_repo.update()` com os campos recebidos
|
|
- Considerar campos permitidos: `name` (se adicionado ao domínio), `email`
|
|
- Revalidar unicidade de email antes de atualizar
|
|
|
|
---
|
|
|
|
## Médio — Segurança
|
|
|
|
- [ ] **Google OAuth: validar `aud` claim** (`src/adapters/inbound/auth_handler.rs:159`)
|
|
- O parâmetro `_client_id` é recebido mas ignorado
|
|
- Após obter o payload do tokeninfo do Google, verificar que `aud == GOOGLE_CLIENT_ID`
|
|
- Rejeitar com `401 Unauthorized` se o `aud` não corresponder
|
|
- Sem isso, qualquer Google token válido de qualquer app é aceito
|
|
|
|
- [ ] **Logout: invalidar refresh token** (`src/adapters/inbound/auth_handler.rs:121`)
|
|
- Atualmente retorna `204 No Content` sem nenhuma ação
|
|
- Opção A (simples): tabela `revoked_tokens` no PostgreSQL com TTL via `expires_at`
|
|
- Opção B (recomendada): Redis com `SET revoked:{jti} 1 EX <ttl>`
|
|
- Middleware de auth deve checar blocklist ao validar tokens
|
|
- Adicionar campo `jti` (JWT ID) aos tokens para identificação única
|
|
|
|
---
|
|
|
|
## Baixo — Qualidade e Completude
|
|
|
|
- [ ] **Sort de filamentos não aplicado** (`src/adapters/outbound/postgres_filament_repo.rs`)
|
|
- `SortOrder` enum está definido em `ports/filament_repository.rs`
|
|
- SQL em `list()` sempre usa `ORDER BY created_at DESC`, ignorando o campo `sort`
|
|
- `filament_handler.rs:203` tem `// TODO: parse sort string para SortOrder` — completar o parse
|
|
- Aplicar o `SortOrder` no SQL com match: `net_weight_g ASC`, `net_weight_g DESC`, `created_at DESC`
|
|
|
|
- [ ] **Paginação: retornar total de itens**
|
|
- `FilamentRepository::count()` está implementado no repo mas nunca é chamado
|
|
- `list_filaments_handler` não retorna metadados de paginação
|
|
- Adicionar ao response: `{ data: [...], total: N, page: N, per_page: N }`
|
|
- Chamar `repo.count(user_id, filter)` em paralelo com `repo.list()`
|
|
|
|
- [ ] **`GET /spool-presets/:id` — handler ausente**
|
|
- Rota está registrada no `router.rs`
|
|
- Nenhum handler correspondente existe em `spool_preset_handler.rs`
|
|
- Implementar `get_preset_handler` ou remover a rota do router
|
|
|
|
- [ ] **Testes**
|
|
- Sem nenhum teste unitário ou de integração no projeto
|
|
- Prioridade: `AuthService` (hash, JWT), `FilamentService` (cálculos de peso, conflito offline), handlers de auth
|
|
- Usar `sqlx::test` para testes de repositório com banco real em transação
|
|
|
|
---
|
|
|
|
## Referência Rápida — Arquivos por Área
|
|
|
|
| Área | Arquivo |
|
|
| --------------------- | ------------------------------------------------- |
|
|
| Handlers de auth | `src/adapters/inbound/auth_handler.rs` |
|
|
| Handler de usuário | `src/adapters/inbound/user_handler.rs` |
|
|
| Handler de filamentos | `src/adapters/inbound/filament_handler.rs` |
|
|
| Handler de presets | `src/adapters/inbound/spool_preset_handler.rs` |
|
|
| Repo de usuário | `src/adapters/outbound/postgres_user_repo.rs` |
|
|
| Repo de filamentos | `src/adapters/outbound/postgres_filament_repo.rs` |
|
|
| Serviço de auth | `src/application/auth_service.rs` |
|
|
| Config / env vars | `src/config.rs` |
|
|
| Migrations | `backend/migrations/` |
|