API REST para gerenciamento de tarefas com autenticação JWT, tarefas por usuário, PostgreSQL, Redis e processamento assíncrono com Celery.
O TaskFlow API é um projeto Backend Python criado para demonstrar:
- APIs REST com FastAPI.
- Arquitetura limpa (Clean Architecture) com DDD (Domain-Driven Design).
- Separação clara entre domínio, casos de uso, adaptadores e interface.
- Autenticação completa com JWT.
- Registro e login de usuários.
- Rotas protegidas com dependency de usuário autenticado.
- Tarefas associadas ao usuário logado.
- Modelagem relacional com SQLAlchemy 2.0.
- Validação de dados com Pydantic.
- PostgreSQL como banco de dados principal.
- Redis como broker/backend do Celery.
- Tarefa assíncrona de envio real de email ao criar uma tarefa.
- Ambiente reproduzível com Docker Compose.
- Swagger automático em
/docs. - Base preparada para Alembic e migrations futuras.
O projeto foi organizado seguindo princípios de Clean Architecture e DDD:
app/domain/- entidades do domínio e contratos de repositório/serviço.app/use_cases/- lógica de aplicação, orquestração de casos de uso.app/adapters/- implementações de infraestrutura, como repositórios SQLAlchemy e serviço de notificação Celery.app/api/- camada de interface HTTP com FastAPI.app/core/- configurações, segurança, dependências e acesso a banco de dados.app/schemas/- modelos de entrada/saída do FastAPI para validação e serialização.app/models/- modelos ORM SQLAlchemy usados pelos adaptadores.
- Python 3.11+
- FastAPI
- SQLAlchemy 2.0
- Alembic
- PostgreSQL
- Redis
- Celery
- JWT
- Passlib + bcrypt
- Docker
- Docker Compose
- Uvicorn
- SMTP
taskflow-api/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── worker.py
│ ├── core/
│ │ ├── __init__.py
│ │ ├── config.py
│ │ ├── database.py
│ │ ├── dependencies.py
│ │ └── security.py
│ ├── domain/
│ │ ├── __init__.py
│ │ ├── entities/
│ │ │ ├── __init__.py
│ │ │ ├── task.py
│ │ │ └── user.py
│ │ ├── repositories/
│ │ │ ├── __init__.py
│ │ │ ├── task_repository.py
│ │ │ └── user_repository.py
│ │ └── services/
│ │ ├── __init__.py
│ │ └── notification_service.py
│ ├── adapters/
│ │ ├── __init__.py
│ │ ├── repositories/
│ │ │ ├── __init__.py
│ │ │ ├── sqlalchemy_task_repository.py
│ │ │ └── sqlalchemy_user_repository.py
│ │ └── services/
│ │ ├── __init__.py
│ │ └── celery_notification_service.py
│ ├── models/
│ │ ├── __init__.py
│ │ ├── task.py
│ │ └── user.py
│ ├── schemas/
│ │ ├── __init__.py
│ │ ├── task.py
│ │ ├── token.py
│ │ └── user.py
│ ├── use_cases/
│ │ ├── __init__.py
│ │ ├── authenticate_user.py
│ │ ├── create_task.py
│ │ ├── delete_task.py
│ │ ├── get_task.py
│ │ ├── list_tasks.py
│ │ ├── register_user.py
│ │ └── update_task.py
│ ├── services/
│ │ ├── __init__.py
│ │ └── email.py
│ ├── tasks/
│ │ ├── __init__.py
│ │ └── notifications.py
│ └── api/
│ ├── __init__.py
│ └── endpoints/
│ ├── __init__.py
│ ├── auth.py
│ └── tasks.py
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── .env.example
└── README.md
Crie o arquivo .env:
cp .env.example .envConfigure as variáveis de PostgreSQL, Redis e SMTP no .env. Para desenvolvimento local com PostgreSQL e Redis rodando via Docker, use POSTGRES_HOST=localhost e REDIS_HOST=localhost.
Suba os containers:
docker compose up --buildA API ficará disponível em:
http://localhost:8000
Swagger:
http://localhost:8000/docs
ReDoc:
http://localhost:8000/redoc
| Serviço | Descrição |
|---|---|
api |
Aplicação FastAPI |
postgres |
Banco PostgreSQL |
redis |
Broker/backend para Celery |
celery_worker |
Worker para tarefas assíncronas |
Crie um usuário:
curl -X POST "http://localhost:8000/auth/register" -H "Content-Type: application/json" -d '{
"name": "Anthony",
"email": "anthony@example.com",
"password": "strongpassword"
}'Faça login:
curl -X POST "http://localhost:8000/auth/login" -H "Content-Type: application/x-www-form-urlencoded" -d "username=anthony@example.com&password=strongpassword"Use o token retornado nas rotas protegidas:
Authorization: Bearer <access_token>
| Método | Rota | Protegida | Descrição |
|---|---|---|---|
| GET | / |
Não | Status da API |
| POST | /auth/register |
Não | Cria usuário |
| POST | /auth/login |
Não | Autentica usuário e retorna JWT |
| POST | /tasks/ |
Sim | Cria tarefa para o usuário logado |
| GET | /tasks/ |
Sim | Lista tarefas do usuário logado |
| GET | /tasks/{task_id} |
Sim | Busca tarefa do usuário logado |
| PUT | /tasks/{task_id} |
Sim | Atualiza tarefa do usuário logado |
| DELETE | /tasks/{task_id} |
Sim | Remove tarefa do usuário logado |
{
"title": "Criar autenticação JWT",
"description": "Adicionar register, login e rotas protegidas",
"status": "pending",
"priority": "high",
"deadline": "2026-12-31T23:59:00"
}Valores aceitos para status:
pendingin_progressdonecanceled
Valores aceitos para priority:
lowmediumhigh
curl -X POST "http://localhost:8000/tasks/" -H "Content-Type: application/json" -H "Authorization: Bearer <access_token>" -d '{
"title": "Estudar FastAPI",
"description": "Criar um projeto completo para portfólio",
"status": "pending",
"priority": "high",
"deadline": "2026-12-31T23:59:00"
}'Ao criar uma tarefa, a API dispara uma task Celery chamada send_task_created_email. A task usa Redis como fila e envia um email real via SMTP em segundo plano.
O envio de email é feito com SMTP. Você pode usar Mailtrap para testes, Gmail com App Password, SendGrid SMTP, Brevo ou outro provedor compatível.
Variáveis usadas no .env:
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=your-smtp-user
SMTP_PASSWORD=your-smtp-password
SMTP_FROM_EMAIL=noreply@example.com
SMTP_FROM_NAME=TaskFlow API
SMTP_USE_TLS=true
SMTP_USE_SSL=falseExemplo com Mailtrap Sandbox:
SMTP_HOST=sandbox.smtp.mailtrap.io
SMTP_PORT=587
SMTP_USERNAME=seu_usuario_mailtrap
SMTP_PASSWORD=sua_senha_mailtrap
SMTP_FROM_EMAIL=noreply@taskflow.local
SMTP_FROM_NAME=TaskFlow API
SMTP_USE_TLS=true
SMTP_USE_SSL=falseCom a API e o worker Celery rodando, crie uma tarefa autenticada em /tasks/. O worker executará a task e enviará o email para o email do usuário logado.
As tabelas são criadas automaticamente no startup com Base.metadata.create_all(bind=engine). Isso é útil para desenvolvimento inicial, mas em produção o ideal é usar Alembic com migrations versionadas.
Se você já rodou uma versão anterior do projeto com o mesmo volume Docker, recrie o volume do PostgreSQL para aplicar o novo schema com usuários e owner_id:
docker compose down -v
docker compose up --build