internal/handler/email_log_handler.go
Rama main · réplica de lectura del repositorio original.
package handler
import (
"net/http"
"strconv"
"time"
"github.com/go-chi/chi/v5"
"github.com/johnzastrow/actalog/internal/domain"
"github.com/johnzastrow/actalog/internal/service"
"github.com/johnzastrow/actalog/pkg/logger"
"github.com/johnzastrow/actalog/pkg/middleware"
)
// EmailLogHandler handles email log endpoints
type EmailLogHandler struct {
emailLogService *service.EmailLogService
logger *logger.Logger
}
// NewEmailLogHandler creates a new email log handler
func NewEmailLogHandler(emailLogService *service.EmailLogService, logger *logger.Logger) *EmailLogHandler {
return &EmailLogHandler{
emailLogService: emailLogService,
logger: logger,
}
}
// ListEmailLogs handles GET /api/admin/email-logs
// Returns a paginated list of email logs with optional filters
func (h *EmailLogHandler) ListEmailLogs(w http.ResponseWriter, r *http.Request) {
// Verify admin authorization
_, ok := middleware.GetUserID(r.Context())
if !ok {
respondError(w, http.StatusUnauthorized, "Unauthorized")
return
}
// Parse query parameters
query := r.URL.Query()
// Pagination
limit := 50
offset := 0
if limitStr := query.Get("limit"); limitStr != "" {
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
limit = l
}
}
if offsetStr := query.Get("offset"); offsetStr != "" {
if o, err := strconv.Atoi(offsetStr); err == nil && o >= 0 {
offset = o
}
}
// Build filters
filters := domain.EmailLogFilters{}
if emailType := query.Get("type"); emailType != "" {
filters.EmailType = &emailType
}
if recipient := query.Get("recipient"); recipient != "" {
filters.RecipientEmail = &recipient
}
if successStr := query.Get("success"); successStr != "" {
if success, err := strconv.ParseBool(successStr); err == nil {
filters.Success = &success
}
}
if startDateStr := query.Get("start_date"); startDateStr != "" {
if startDate, err := time.Parse("2006-01-02", startDateStr); err == nil {
filters.StartDate = &startDate
}
}
if endDateStr := query.Get("end_date"); endDateStr != "" {
if endDate, err := time.Parse("2006-01-02", endDateStr); err == nil {
// Add one day to include the end date
endDate = endDate.Add(24 * time.Hour)
filters.EndDate = &endDate
}
}
// Get logs
logs, err := h.emailLogService.List(filters, limit, offset)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to fetch email logs")
return
}
// Get total count
count, err := h.emailLogService.Count(filters)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to count email logs")
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"logs": logs,
"count": count,
"limit": limit,
"offset": offset,
})
}
// GetEmailLog handles GET /api/admin/email-logs/{id}
// Returns a single email log by ID with full debug info
func (h *EmailLogHandler) GetEmailLog(w http.ResponseWriter, r *http.Request) {
// Verify admin authorization
_, ok := middleware.GetUserID(r.Context())
if !ok {
respondError(w, http.StatusUnauthorized, "Unauthorized")
return
}
// Get ID from URL
idStr := chi.URLParam(r, "id")
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
respondError(w, http.StatusBadRequest, "Invalid email log ID")
return
}
// Get log
log, err := h.emailLogService.GetByID(id)
if err != nil {
respondError(w, http.StatusNotFound, "Email log not found")
return
}
respondJSON(w, http.StatusOK, log)
}
// GetEmailStats handles GET /api/admin/email-logs/stats
// Returns statistics about email logs
func (h *EmailLogHandler) GetEmailStats(w http.ResponseWriter, r *http.Request) {
// Verify admin authorization
_, ok := middleware.GetUserID(r.Context())
if !ok {
respondError(w, http.StatusUnauthorized, "Unauthorized")
return
}
stats, err := h.emailLogService.GetEmailStats()
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to get email statistics")
return
}
respondJSON(w, http.StatusOK, stats)
}
// CleanupEmailLogs handles POST /api/admin/email-logs/cleanup
// Removes email logs older than the retention period
func (h *EmailLogHandler) CleanupEmailLogs(w http.ResponseWriter, r *http.Request) {
// Verify admin authorization
_, ok := middleware.GetUserID(r.Context())
if !ok {
respondError(w, http.StatusUnauthorized, "Unauthorized")
return
}
// Use default retention period (90 days)
deleted, err := h.emailLogService.CleanupOldLogs(service.EmailLogRetentionDays)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to cleanup email logs")
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"message": "Email logs cleaned up successfully",
"deleted_count": deleted,
"retention_days": service.EmailLogRetentionDays,
})
}
// GetRecentFailures handles GET /api/admin/email-logs/failures
// Returns recent failed email attempts
func (h *EmailLogHandler) GetRecentFailures(w http.ResponseWriter, r *http.Request) {
// Verify admin authorization
_, ok := middleware.GetUserID(r.Context())
if !ok {
respondError(w, http.StatusUnauthorized, "Unauthorized")
return
}
// Parse limit
limit := 20
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
limit = l
}
}
failures, err := h.emailLogService.GetRecentFailures(limit)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to fetch recent failures")
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"failures": failures,
"count": len(failures),
})
}