gohorsejobs/backend/internal/handlers/activity_log_handler.go
Tiago Yamamoto 9ee9f6855c feat: implementar múltiplas features
Backend:
- Password reset flow (forgot/reset endpoints, tokens table)
- Profile management (PUT /users/me, skills, experience, education)
- Tickets system (CRUD, messages, stats)
- Activity logs (list, stats)
- Document validator (CNPJ, CPF, EIN support)
- Input sanitizer (XSS prevention)
- Full-text search em vagas (plainto_tsquery)
- Filtros avançados (location, salary, workMode)
- Ordenação (date, salary, relevance)

Frontend:
- Forgot/Reset password pages
- Candidate profile edit page
- Sanitize utilities (sanitize.ts)

Backoffice:
- TicketsModule proxy
- ActivityLogsModule proxy
- Dockerfile otimizado (multi-stage, non-root, healthcheck)

Migrations:
- 013: Profile fields to users
- 014: Password reset tokens
- 015: Tickets table
- 016: Activity logs table
2025-12-27 11:19:47 -03:00

102 lines
3 KiB
Go

package handlers
import (
"encoding/json"
"net/http"
"strconv"
"time"
"github.com/rede5/gohorsejobs/backend/internal/models"
"github.com/rede5/gohorsejobs/backend/internal/services"
)
type ActivityLogHandler struct {
service *services.ActivityLogService
}
func NewActivityLogHandler(service *services.ActivityLogService) *ActivityLogHandler {
return &ActivityLogHandler{service: service}
}
// GetActivityLogs lists activity logs
// @Summary List Activity Logs
// @Description Get activity logs with optional filters
// @Tags Activity Logs
// @Produce json
// @Param user_id query int false "Filter by user ID"
// @Param action query string false "Filter by action"
// @Param resource_type query string false "Filter by resource type"
// @Param start_date query string false "Start date (RFC3339)"
// @Param end_date query string false "End date (RFC3339)"
// @Param limit query int false "Limit results"
// @Param offset query int false "Offset for pagination"
// @Success 200 {array} models.ActivityLog
// @Router /api/v1/activity-logs [get]
func (h *ActivityLogHandler) GetActivityLogs(w http.ResponseWriter, r *http.Request) {
filter := models.ActivityLogFilter{}
if userID := r.URL.Query().Get("user_id"); userID != "" {
if id, err := strconv.Atoi(userID); err == nil {
filter.UserID = &id
}
}
if action := r.URL.Query().Get("action"); action != "" {
filter.Action = &action
}
if resourceType := r.URL.Query().Get("resource_type"); resourceType != "" {
filter.ResourceType = &resourceType
}
if startDate := r.URL.Query().Get("start_date"); startDate != "" {
if t, err := time.Parse(time.RFC3339, startDate); err == nil {
filter.StartDate = &t
}
}
if endDate := r.URL.Query().Get("end_date"); endDate != "" {
if t, err := time.Parse(time.RFC3339, endDate); err == nil {
filter.EndDate = &t
}
}
if limit := r.URL.Query().Get("limit"); limit != "" {
if l, err := strconv.Atoi(limit); err == nil {
filter.Limit = l
}
}
if offset := r.URL.Query().Get("offset"); offset != "" {
if o, err := strconv.Atoi(offset); err == nil {
filter.Offset = o
}
}
logs, err := h.service.List(filter)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(logs)
}
// GetActivityLogStats gets statistics
// @Summary Get Activity Stats
// @Description Get activity log statistics for dashboard
// @Tags Activity Logs
// @Produce json
// @Success 200 {object} models.ActivityLogStats
// @Router /api/v1/activity-logs/stats [get]
func (h *ActivityLogHandler) GetActivityLogStats(w http.ResponseWriter, r *http.Request) {
stats, err := h.service.GetStats()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(stats)
}