10 KiB
Executable file
10 KiB
Executable file
Backend - GoHorse Jobs API
Last Updated: 2024-12-29
API REST desenvolvida em Go seguindo princípios de Clean Architecture e DDD.
🏗️ Arquitetura
backend/
├── cmd/
│ ├── api/ # Entrypoint principal
│ └── manual_migrate/ # Migration runner
│
├── internal/
│ ├── api/ # Clean Architecture Layer
│ │ ├── handlers/ # HTTP Handlers (Admin, Auth, Settings, Storage, Tickets)
│ │ └── middleware/ # Auth, CORS, Rate Limiting, Sanitize
│ │
│ ├── core/ # Domain Layer (DDD)
│ │ ├── domain/entity/ # Entidades (User, Company, Email)
│ │ ├── ports/ # Interfaces (Repositories)
│ │ └── usecases/ # Casos de uso (Auth, Register)
│ │
│ ├── infrastructure/ # Infrastructure Layer
│ │ ├── auth/ # JWT Service implementation
│ │ └── persistence/ # Repository implementations (Postgres)
│ │
│ ├── services/ # Business logic services (Email, Notification, Tickets)
│ │
│ ├── dto/ # Data Transfer Objects
│ ├── models/ # GORM models (Legacy/Transition)
│ ├── router/ # Route configuration
│ └── utils/ # Helpers (JWT, Sanitizer)
│
├── migrations/ # SQL Migrations (30+)
├── tests/ # E2E and Integration tests
└── docs/ # Swagger documentation
📊 Diagrama de Fluxo (C4 Simplificado)
graph TD
Client[📱 Clients Frontend/App] -->|JSON/HTTP| Router[🚦 Router Mux]
subgraph CoreBackend [Core Backend]
Router --> Middleware[🛡️ Middleware Auth/CORS]
Middleware --> Handlers[🎮 HTTP Handlers]
Handlers --> UseCases[🧠 Services & UseCases]
UseCases --> Repos[💾 Repositories]
UseCases --> Adapters[🔌 External Adapters]
end
Repos --> DB[(🐘 PostgreSQL)]
Adapters --> Firebase[🔥 Firebase FCM]
Adapters --> LavinMQ[📨 LavinMQ]
Adapters --> Storage[☁️ S3/R2 Storage]
Adapters --> Stripe[💳 Stripe]
🚀 Deployment & CI/CD (Forgejo)
O deployment é automatizado via Forgejo Actions.
Workflow: Deploy Backend (Dev)
Arquivo: .forgejo/workflows/deploy.yaml
Este workflow é disparado automaticamente ao realizar um push para o branch dev com alterações na pasta backend/.
Etapas do CI/CD:
- Trigger: Push no branch
dev(apenas alterações embackend/**). - Runner: Executa no ambiente
docker(verifique as labels do seu runner). - SSH Action: Conecta no servidor de desenvolvimento (Apolo) via SSH.
- Atualização de Código:
- Navega até
/mnt/data/gohorsejobs(ou caminho configurado). - Faz
git fetchegit checkout dev. git pull origin dev.
- Navega até
- Build & Restart (Podman):
- Constrói a imagem:
podman build -t localhost/gohorsejobs-backend-dev ./backend - Reinicia o serviço:
sudo systemctl restart gohorsejobs-backend-dev - Limpeza:
podman image prune -f
- Constrói a imagem:
Secrets Necessários (Forgejo):
HOST: IP do servidor.USERNAME: Usuário SSH.SSH_KEY: Chave privada SSH.PORT: Porta SSH (ex: 22).
🔧 Services
| Service | Arquivo | Descrição |
|---|---|---|
| AdminService | admin_service.go |
CRUD de empresas, usuários, candidatos, tags, email templates |
| JobService | job_service.go |
CRUD de vagas com filtros avançados |
| ApplicationService | application_service.go |
Gestão de candidaturas |
| TicketService | ticket_service.go |
(Novo) Sistema de tickets de suporte |
| ChatService | chat_service.go |
Mensagens e conversas (Appwrite) |
| NotificationService | notification_service.go |
Notificações push |
| EmailService | email_service.go |
Produtor de emails via LavinMQ |
| FCMService | fcm_service.go |
Firebase Cloud Messaging |
| StorageService | storage_service.go |
Pre-signed URLs (S3/R2) |
| CredentialsService | credentials_service.go |
(Novo) Gestão de credenciais criptografadas |
| CloudflareService | cloudflare_service.go |
Cache purge via API |
| SettingsService | settings_service.go |
System settings |
| AppwriteService | appwrite_service.go |
Integração Appwrite Realtime |
| AuditService | audit_service.go |
Logs de auditoria |
🔒 Segurança
Middlewares Implementados
| Middleware | Arquivo | Descrição |
|---|---|---|
| Auth | middleware/auth.go |
Validação JWT + RBAC |
| CORS | middleware/cors.go |
Whitelist de origens via CORS_ORIGINS |
| Rate Limiting | middleware/rate_limit.go |
100 req/min por IP |
| Security Headers | middleware/security_headers.go |
OWASP headers (XSS, CSP, etc.) |
| Sanitize | middleware/sanitize.go |
XSS sanitization em JSON bodies |
Autenticação
- JWT com expiração configurável
- Password Pepper via
PASSWORD_PEPPERenv var - HttpOnly Cookies para refresh tokens
- RSA Encryption para credenciais sensíveis
📡 Endpoints (API Reference)
🔐 Auth & Core
| Método | Endpoint | Descrição | Roles |
|---|---|---|---|
POST |
/api/v1/auth/login |
Autenticação de usuário | Public |
POST |
/api/v1/auth/register |
Registro de Candidato | Public |
POST |
/api/v1/auth/register/company |
Registro de Empresa | Public |
GET |
/api/v1/users/me |
Dados do usuário logado | Auth |
PATCH |
/api/v1/users/me/profile |
Atualizar perfil | Auth |
GET |
/api/v1/notifications |
Listar notificações | Auth |
POST |
/api/v1/tokens |
Salvar token FCM | Auth |
💼 Jobs (Vagas)
| Método | Endpoint | Descrição | Roles |
|---|---|---|---|
GET |
/api/v1/jobs |
Listar vagas (filtros) | Public |
GET |
/api/v1/jobs/{id} |
Detalhes da vaga | Public |
POST |
/api/v1/jobs |
Criar nova vaga | Recruiter |
PUT |
/api/v1/jobs/{id} |
Editar vaga | Recruiter |
DELETE |
/api/v1/jobs/{id} |
Remover vaga | Recruiter |
📝 Applications (Candidaturas)
| Método | Endpoint | Descrição | Roles |
|---|---|---|---|
POST |
/api/v1/applications |
Candidatar-se a uma vaga | Candidate |
GET |
/api/v1/applications |
Minhas candidaturas | Auth |
GET |
/api/v1/applications/{id} |
Detalhes da candidatura | Auth |
PUT |
/api/v1/applications/{id}/status |
Atualizar status | Recruiter |
DELETE |
/api/v1/applications/{id} |
Desistir/Remover | Auth |
🎫 Support (Tickets)
| Método | Endpoint | Descrição | Roles |
|---|---|---|---|
GET |
/api/v1/support/tickets |
Meus tickets de suporte | Auth |
POST |
/api/v1/support/tickets |
Abrir novo ticket | Auth |
GET |
/api/v1/support/tickets/{id} |
Ver conversa do ticket | Auth |
POST |
/api/v1/support/tickets/{id}/messages |
Enviar mensagem | Auth |
PATCH |
/api/v1/support/tickets/{id}/close |
Fechar ticket | Auth |
💬 Chat & Locais
| Método | Endpoint | Descrição | Roles |
|---|---|---|---|
GET |
/api/v1/conversations |
Listar conversas | Auth |
GET |
/api/v1/conversations/{id}/messages |
Ver mensagens | Auth |
POST |
/api/v1/conversations/{id}/messages |
Enviar mensagem | Auth |
GET |
/api/v1/locations/search |
Buscar cidade/estado | Public |
🛡️ Admin & System
| Método | Endpoint | Descrição | Roles |
|---|---|---|---|
GET |
/api/v1/users |
Listar todos usuários | Admin |
GET |
/api/v1/jobs/moderation |
Moderação de vagas | Admin |
GET |
/api/v1/system/credentials |
Ver credenciais (mascaradas) | Admin |
POST |
/api/v1/system/credentials |
Salvar credencial | Admin |
POST |
/api/v1/system/cloudflare/purge |
Limpar cache CDN | Admin |
GET |
/api/v1/admin/email-templates |
Gerenciar emails | Admin |
🗄️ Migrations
O projeto usa um sistema de migrations manuais via cmd/manual_migrate.
Executar Migrations
go run ./cmd/manual_migrate
💻 Desenvolvimento Local
Pré-requisitos
- Go 1.22+
- Docker & Docker Compose OU Podman
- PostgreSQL
Executar com Go
# Copiar .env
cp .env.example .env
# Executar migrations
go run ./cmd/manual_migrate
# Iniciar servidor
go run ./cmd/api
Executar com Podman
# Build
podman build -t gohorse-backend ./backend
# Run
podman run -p 8080:8080 --env-file ./backend/.env gohorse-backend
Testes
# Todos os testes
go test ./...
# Com cobertura
go test -cover ./...
❓ Troubleshooting (CI/CD & Runner)
O Workflow não inicia (Waiting for runner...)
- Causa: Nenhuma maquina registrada com o label correto.
- Solução:
- Verifique, no arquivo
.forgejo/workflows/deploy.yaml, o camporuns-on. - Se estiver como
docker, seuact_runnerdeve ter suporte a este label (ex:labels: "docker:docker://node:16-bullseye,ubuntu-latest:docker://node:16-bullseye"noconfig.yaml). - Se o runner for genérico, use
ubuntu-latest.
- Verifique, no arquivo
Falha de SSH (ssh: handshake failed)
- Solução:
- Verifique se a chave pública (
id_rsa.pub) correspondente àSSH_KEYdo secret está no arquivo~/.ssh/authorized_keysda máquina de destino. - Confira se o IP (
HOST) está acessível da rede onde o runner está.
- Verifique se a chave pública (
Falha de Build no Podman
- Causa: Falta de permissão ou serviço parado.
- Solução:
- Rode
podman logs -f <conteiner>na máquina de destino. - Verifique se o usuário tem permissão de usar podman (rootless ou sudo).
- Rode