From b722e913f5a189d384bbd8d70426b6e705c25aee Mon Sep 17 00:00:00 2001 From: Joan Manuel Jaramillo Avila <89425013+LifeRIP@users.noreply.github.com> Date: Tue, 17 Jun 2025 21:54:47 -0500 Subject: [PATCH 1/2] feat: Adds user access validation and improves message ordering - Enforces user access validation for direct chats, ensuring unauthorized users cannot access messages. - Revises message retrieval logic for direct and room chats to return messages in descending order and subsequently reverse them for ascending order in the response. --- internal/handlers/chat_handler.go | 14 ++++++++++ internal/repositories/message_repository.go | 29 ++++++++++++++++----- internal/services/directchat_service.go | 2 +- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/internal/handlers/chat_handler.go b/internal/handlers/chat_handler.go index 59b138b..468ceb5 100644 --- a/internal/handlers/chat_handler.go +++ b/internal/handlers/chat_handler.go @@ -245,12 +245,26 @@ func (h *ChatHandler) GetUserDirectChats(w http.ResponseWriter, r *http.Request) // @Param limit query int false "Límite de mensajes a obtener" default(50) // @Success 200 {array} models.Message "Lista de mensajes del chat directo" // @Failure 401 {string} string "No autorizado" +// @Failure 403 {string} string "Acceso prohibido" // @Failure 404 {string} string "Chat no encontrado" // @Failure 500 {string} string "Error interno del servidor" // @Router /chat/direct/{chatId}/messages [get] func (h *ChatHandler) GetDirectChatMessages(w http.ResponseWriter, r *http.Request) { chatID := chi.URLParam(r, "chatId") + // Obtener el ID del usuario del contexto + userID, ok := r.Context().Value("userID").(string) + if !ok { + http.Error(w, "User ID not found in context", http.StatusInternalServerError) + return + } + + // Verificar si el usuario pertenece al chat directo + if !h.DirectChatService.DirectChatRepo.IsUserInDirectChat(chatID, userID) { + http.Error(w, "Unauthorized access to this chat", http.StatusForbidden) + return + } + limitStr := r.URL.Query().Get("limit") limit := 50 // valor por defecto diff --git a/internal/repositories/message_repository.go b/internal/repositories/message_repository.go index cc6d5b9..c50c6f4 100644 --- a/internal/repositories/message_repository.go +++ b/internal/repositories/message_repository.go @@ -139,17 +139,18 @@ func (r *MessageRepository) GetRoomMessages(roomID string, limit int, cursor str return response, nextCursor, nil } -// GetDirectChatMessages obtiene los mensajes de un chat directo -func (r *MessageRepository) GetDirectChatMessages(directChatID string, limit int) ([]models.MessageResponse, error) { +// GetDirectChatMessagesSimple obtiene los mensajes de un chat directo sin paginación +func (r *MessageRepository) GetDirectChatMessagesSimple(directChatID string, limit int) ([]models.MessageResponse, error) { ctx := context.Background() var messages []models.Message var response []models.MessageResponse + // Obtener mensajes en orden descendente (más recientes primero) messagesRef := r.FirestoreClient.Client. Collection("directChats").Doc(directChatID). Collection("messages"). - OrderBy("createdAt", firestore.Asc). + OrderBy("createdAt", firestore.Desc). Limit(limit) docs, err := messagesRef.Documents(ctx).GetAll() @@ -182,6 +183,8 @@ func (r *MessageRepository) GetDirectChatMessages(directChatID string, limit int } } + // Crear respuestas con DisplayName + var responseTemp []models.MessageResponse for _, message := range messages { msgMap := models.MessageResponse{ Message: message, @@ -192,7 +195,12 @@ func (r *MessageRepository) GetDirectChatMessages(directChatID string, limit int msgMap.DisplayName = displayName } - response = append(response, msgMap) + responseTemp = append(responseTemp, msgMap) + } + + // Invertir el orden para que queden en orden ascendente (más antiguos primero) + for i := len(responseTemp) - 1; i >= 0; i-- { + response = append(response, responseTemp[i]) } return response, nil @@ -205,10 +213,11 @@ func (r *MessageRepository) GetRoomMessagesSimple(roomID string, limit int) ([]m var messages []models.Message var response []models.MessageResponse + // Obtener mensajes en orden descendente (más recientes primero) messagesRef := r.FirestoreClient.Client. Collection("rooms").Doc(roomID). Collection("messages"). - OrderBy("createdAt", firestore.Asc). + OrderBy("createdAt", firestore.Desc). Limit(limit) docs, err := messagesRef.Documents(ctx).GetAll() @@ -243,13 +252,19 @@ func (r *MessageRepository) GetRoomMessagesSimple(roomID string, limit int) ([]m } } - // Construir la respuesta con los displayNames + // Crear respuestas con DisplayName + var responseTemp []models.MessageResponse for _, message := range messages { msgResponse := models.MessageResponse{ Message: message, DisplayName: userDataCache[message.UserID], // Puede estar vacío si no se encontró } - response = append(response, msgResponse) + responseTemp = append(responseTemp, msgResponse) + } + + // Invertir el orden para que queden en orden ascendente (más antiguos primero) + for i := len(responseTemp) - 1; i >= 0; i-- { + response = append(response, responseTemp[i]) } return response, nil diff --git a/internal/services/directchat_service.go b/internal/services/directchat_service.go index c6006eb..03fb897 100644 --- a/internal/services/directchat_service.go +++ b/internal/services/directchat_service.go @@ -69,7 +69,7 @@ func (s *DirectChatService) GetUserDirectChatsWithSenderNames(userID string) ([] // GetDirectChatMessages obtiene los mensajes de un chat directo func (s *DirectChatService) GetDirectChatMessages(directChatID string, limit int) ([]models.MessageResponse, error) { - return s.MessageRepo.GetDirectChatMessages(directChatID, limit) + return s.MessageRepo.GetDirectChatMessagesSimple(directChatID, limit) } // FindOrCreateDirectChat encuentra un chat directo entre dos usuarios o lo crea si no existe From c60b71b15703326705361129ba1fe7bc004b2e3f Mon Sep 17 00:00:00 2001 From: Joan Manuel Jaramillo Avila <89425013+LifeRIP@users.noreply.github.com> Date: Tue, 17 Jun 2025 21:55:47 -0500 Subject: [PATCH 2/2] feat: Add 403 Forbidden response and displayNames to Swagger documentation --- docs/docs.go | 12 ++++++++++++ docs/swagger.json | 12 ++++++++++++ docs/swagger.yaml | 8 ++++++++ 3 files changed, 32 insertions(+) diff --git a/docs/docs.go b/docs/docs.go index 06bcd0c..7f53303 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -252,6 +252,12 @@ const docTemplate = `{ "type": "string" } }, + "403": { + "description": "Acceso prohibido", + "schema": { + "type": "string" + } + }, "404": { "description": "Chat no encontrado", "schema": { @@ -834,6 +840,12 @@ const docTemplate = `{ "createdAt": { "type": "string" }, + "displayNames": { + "type": "array", + "items": { + "type": "string" + } + }, "id": { "type": "string" }, diff --git a/docs/swagger.json b/docs/swagger.json index f1a79d3..9c54e57 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -245,6 +245,12 @@ "type": "string" } }, + "403": { + "description": "Acceso prohibido", + "schema": { + "type": "string" + } + }, "404": { "description": "Chat no encontrado", "schema": { @@ -827,6 +833,12 @@ "createdAt": { "type": "string" }, + "displayNames": { + "type": "array", + "items": { + "type": "string" + } + }, "id": { "type": "string" }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 24948a1..c6e2846 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -27,6 +27,10 @@ definitions: properties: createdAt: type: string + displayNames: + items: + type: string + type: array id: type: string isDeleted: @@ -273,6 +277,10 @@ paths: description: No autorizado schema: type: string + "403": + description: Acceso prohibido + schema: + type: string "404": description: Chat no encontrado schema: