gohorsejobs/backend/BACKEND.md
2025-12-29 10:41:03 -03:00

10 KiB
Executable file

Backend - GoHorse Jobs API

Go PostgreSQL

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:

  1. Trigger: Push no branch dev (apenas alterações em backend/**).
  2. Runner: Executa no ambiente docker (verifique as labels do seu runner).
  3. SSH Action: Conecta no servidor de desenvolvimento (Apolo) via SSH.
  4. Atualização de Código:
    • Navega até /mnt/data/gohorsejobs (ou caminho configurado).
    • Faz git fetch e git checkout dev.
    • git pull origin dev.
  5. 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

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_PEPPER env 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:
    1. Verifique, no arquivo .forgejo/workflows/deploy.yaml, o campo runs-on.
    2. Se estiver como docker, seu act_runner deve ter suporte a este label (ex: labels: "docker:docker://node:16-bullseye,ubuntu-latest:docker://node:16-bullseye" no config.yaml).
    3. Se o runner for genérico, use ubuntu-latest.

Falha de SSH (ssh: handshake failed)

  • Solução:
    1. Verifique se a chave pública (id_rsa.pub) correspondente à SSH_KEY do secret está no arquivo ~/.ssh/authorized_keys da máquina de destino.
    2. Confira se o IP (HOST) está acessível da rede onde o runner está.

Falha de Build no Podman

  • Causa: Falta de permissão ou serviço parado.
  • Solução:
    1. Rode podman logs -f <conteiner> na máquina de destino.
    2. Verifique se o usuário tem permissão de usar podman (rootless ou sudo).