From 1ad571e1c14ba3117f9df941d76809a629969969 Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Sat, 3 Jan 2026 19:41:44 -0300 Subject: [PATCH] Allow admins to access ticket details --- .../internal/api/handlers/core_handlers.go | 14 ++++++++--- backend/internal/services/ticket_service.go | 24 ++++++++++++++----- .../internal/services/ticket_service_test.go | 4 ++-- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/backend/internal/api/handlers/core_handlers.go b/backend/internal/api/handlers/core_handlers.go index 43e9412..881f2a6 100644 --- a/backend/internal/api/handlers/core_handlers.go +++ b/backend/internal/api/handlers/core_handlers.go @@ -695,7 +695,7 @@ func (h *CoreHandlers) CreateTicket(w http.ResponseWriter, r *http.Request) { // Create initial message if provided if req.Message != "" { - _, _ = h.ticketService.AddMessage(r.Context(), ticket.ID, userID, req.Message) + _, _ = h.ticketService.AddMessage(r.Context(), ticket.ID, userID, req.Message, false) } w.WriteHeader(http.StatusCreated) @@ -759,7 +759,11 @@ func (h *CoreHandlers) GetTicket(w http.ResponseWriter, r *http.Request) { } } - ticket, messages, err := h.ticketService.GetTicket(r.Context(), id, userID) + roleVal := r.Context().Value(middleware.ContextRoles) + roles := middleware.ExtractRoles(roleVal) + isAdmin := hasAdminRole(roles) + + ticket, messages, err := h.ticketService.GetTicket(r.Context(), id, userID, isAdmin) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return @@ -810,7 +814,11 @@ func (h *CoreHandlers) AddMessage(w http.ResponseWriter, r *http.Request) { return } - msg, err := h.ticketService.AddMessage(r.Context(), id, userID, req.Message) + roleVal := r.Context().Value(middleware.ContextRoles) + roles := middleware.ExtractRoles(roleVal) + isAdmin := hasAdminRole(roles) + + msg, err := h.ticketService.AddMessage(r.Context(), id, userID, req.Message, isAdmin) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return diff --git a/backend/internal/services/ticket_service.go b/backend/internal/services/ticket_service.go index c4eee9c..07c0bd5 100644 --- a/backend/internal/services/ticket_service.go +++ b/backend/internal/services/ticket_service.go @@ -61,15 +61,21 @@ func (s *TicketService) ListTickets(ctx context.Context, userID string) ([]model return tickets, nil } -func (s *TicketService) GetTicket(ctx context.Context, ticketID string, userID string) (*models.Ticket, []models.TicketMessage, error) { +func (s *TicketService) GetTicket(ctx context.Context, ticketID string, userID string, isAdmin bool) (*models.Ticket, []models.TicketMessage, error) { // 1. Get Ticket queryTicket := ` SELECT id, user_id, subject, status, priority, created_at, updated_at FROM tickets - WHERE id = $1 AND user_id = $2 + WHERE id = $1 ` + args := []any{ticketID} + if !isAdmin { + queryTicket += " AND user_id = $2" + args = append(args, userID) + } + var t models.Ticket - err := s.DB.QueryRowContext(ctx, queryTicket, ticketID, userID).Scan( + err := s.DB.QueryRowContext(ctx, queryTicket, args...).Scan( &t.ID, &t.UserID, &t.Subject, &t.Status, &t.Priority, &t.CreatedAt, &t.UpdatedAt, ) if err != nil { @@ -106,10 +112,16 @@ func (s *TicketService) GetTicket(ctx context.Context, ticketID string, userID s return &t, messages, nil } -func (s *TicketService) AddMessage(ctx context.Context, ticketID string, userID string, message string) (*models.TicketMessage, error) { - // Verify ticket ownership first (or admin access, but keeping simple for now) +func (s *TicketService) AddMessage(ctx context.Context, ticketID string, userID string, message string, isAdmin bool) (*models.TicketMessage, error) { + // Verify ticket ownership first (or admin access) var count int - err := s.DB.QueryRowContext(ctx, "SELECT COUNT(*) FROM tickets WHERE id = $1 AND user_id = $2", ticketID, userID).Scan(&count) + query := "SELECT COUNT(*) FROM tickets WHERE id = $1 AND user_id = $2" + args := []any{ticketID, userID} + if isAdmin { + query = "SELECT COUNT(*) FROM tickets WHERE id = $1" + args = []any{ticketID} + } + err := s.DB.QueryRowContext(ctx, query, args...).Scan(&count) if err != nil { return nil, err } diff --git a/backend/internal/services/ticket_service_test.go b/backend/internal/services/ticket_service_test.go index c36281e..4afedb2 100644 --- a/backend/internal/services/ticket_service_test.go +++ b/backend/internal/services/ticket_service_test.go @@ -53,7 +53,7 @@ func TestTicketService_CRUD(t *testing.T) { WithArgs("ticket-id"). WillReturnResult(sqlmock.NewResult(1, 1)) - msg, err := service.AddMessage(ctx, "ticket-id", "user-id", "reply") + msg, err := service.AddMessage(ctx, "ticket-id", "user-id", "reply", false) assert.NoError(t, err) assert.NotNil(t, msg) @@ -89,7 +89,7 @@ func TestTicketService_Extended(t *testing.T) { WillReturnRows(sqlmock.NewRows([]string{"id", "ticket_id", "user_id", "message", "created_at"}). AddRow("msg-1", "ticket-id", "user-id", "msg body", time.Now())) - tTicket, tMsgs, err := service.GetTicket(ctx, "ticket-id", "user-id") + tTicket, tMsgs, err := service.GetTicket(ctx, "ticket-id", "user-id", false) assert.NoError(t, err) assert.Equal(t, "ticket-id", tTicket.ID) assert.Len(t, tMsgs, 1)