diff --git a/cmd/api/main.go b/cmd/api/main.go index 16e1c8e..a96cdac 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -77,6 +77,7 @@ func main() { router.Handle(endpoint.ADD_CONTACT_ENDPOINT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.AddContact))) router.Handle(endpoint.GET_CONTACT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.GetContact))) router.Handle(endpoint.ADD_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.AddMessage))) + router.Handle(endpoint.GET_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.GetMessage))) // Start server server := &http.Server{ diff --git a/internal/handler/endpoint/endpoint.go b/internal/handler/endpoint/endpoint.go index ff6d1c8..3613aee 100644 --- a/internal/handler/endpoint/endpoint.go +++ b/internal/handler/endpoint/endpoint.go @@ -2,5 +2,6 @@ package endpoint const MESSAGE_DRAFT_ENDPOINT = "/api/v1/message/draft" const ADD_MESSAGE = "/api/v1/message/new" +const GET_MESSAGE = "/api/v1/message" const GET_CONTACT = "/api/v1/contact" const ADD_CONTACT_ENDPOINT = "/api/v1/contact/new" diff --git a/internal/handler/message.go b/internal/handler/message.go index 3222cfc..36e5b29 100644 --- a/internal/handler/message.go +++ b/internal/handler/message.go @@ -20,6 +20,11 @@ type AddMessageResponse struct { Data []message.Message `json:"data"` } +type GetMessageResponse struct { + Message string `json:"message"` + Data []message.Message `json:"data"` +} + type MessageHandler struct { MessageStore store.MessageStore } @@ -70,3 +75,79 @@ func (m *MessageHandler) AddMessage(w http.ResponseWriter, r *http.Request) { RespondWithJSON(w, statusCode, &resp) } + +func (c *MessageHandler) GetMessage(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + var id, userId uuid.UUID + queryParams := r.URL.Query() + + // Check if parameter exists + if _, exists := queryParams["id"]; !exists { + if _, exists := queryParams["user_id"]; !exists { + fmt.Fprintf(w, "Name parameter not provided") + http.Error(w, "Query params", http.StatusBadRequest) + return + } else { + var err error + userId, err = uuid.Parse(queryParams.Get("user_id")) + if err != nil { + fmt.Fprintf(w, "Name parameter exists: %s", userId) + } + } + } else { + var err error + idTmp := queryParams.Get("id") + id, err = uuid.Parse(idTmp) + if err != nil { + fmt.Println("Error:", err) + http.Error(w, "Error parsing Id", http.StatusBadRequest) + return + } + } + + var statusCode int + var resp GetMessageResponse + + ctx := r.Context() + + if id != uuid.Nil { + fmt.Println("Checking with Id") + if con, err := c.MessageStore.GetMessageByID(ctx, id); err == nil { + statusCode = http.StatusOK + resp.Message = "Successful" + resp.Data = append(resp.Data, *con) + } else { + statusCode = http.StatusInternalServerError + resp.Message = err.Error() + } + } else if userId != uuid.Nil { + fmt.Println("Checking with User Id") + if contacts, err := c.MessageStore.GetAllMessages(ctx); err == nil { + for _, con := range contacts { + if con.UserId == userId { + resp.Data = append(resp.Data, *con) + } + } + + if len(resp.Data) > 0 { + statusCode = http.StatusOK + resp.Message = "Successful" + } else { + statusCode = http.StatusNotFound + resp.Message = "Contact not found" + } + } else { + statusCode = http.StatusInternalServerError + resp.Message = err.Error() + } + } else { + statusCode = http.StatusBadRequest + resp.Message = "Invalid query parameter" + } + + RespondWithJSON(w, statusCode, &resp) +} diff --git a/internal/handler/message_test.go b/internal/handler/message_test.go index a1ab699..60ac9b2 100644 --- a/internal/handler/message_test.go +++ b/internal/handler/message_test.go @@ -2,11 +2,13 @@ package handler import ( "encoding/json" + "fmt" "net/http" "net/http/httptest" "strings" "testing" + "git.kundeng.us/phoenix/textsender-models/pkg/message" "github.com/google/uuid" "github.com/stretchr/testify/assert" @@ -41,3 +43,32 @@ func TestCreateMessageWithMock(t *testing.T) { assert.NotNil(t, response.Data[0].Id, "Id should not be nil") } + +func TestGetMessageWithMock(t *testing.T) { + mockstore := NewMockMessageStore() + testUserId := uuid.New() + + testCon := message.Message{Content: "Who is the one that benefits?", UserId: testUserId} + ctx := t.Context() + if err := mockstore.CreateMessage(ctx, &testCon); err != nil { + assert.NoError(t, err, "Error creating message") + return + } + + url := fmt.Sprintf("%s?user_id=%s", endpoint.GET_MESSAGE, testCon.UserId) + req, _ := http.NewRequest("GET", url, nil) + rr := httptest.NewRecorder() + + messageHandler := NewMessageHandler(mockstore) + messageHandler.GetMessage(rr, req) + + assert.Equal(t, http.StatusOK, rr.Code) + + var response GetMessageResponse + err := json.Unmarshal(rr.Body.Bytes(), &response) + assert.NoError(t, err, "Error getting message %v", err) + + assert.NotEmpty(t, response.Data, "No Message retrieved") + + assert.NotNil(t, response.Data[0].Id, "Id should not be nil") +} diff --git a/internal/handler/mock_store_test.go b/internal/handler/mock_store_test.go index 9c3abc1..da3fc88 100644 --- a/internal/handler/mock_store_test.go +++ b/internal/handler/mock_store_test.go @@ -158,6 +158,36 @@ func (m *MockMessageStore) CreateMessage(ctx context.Context, msg *message.Messa return nil } +func (m *MockMessageStore) GetAllMessages(ctx context.Context) ([]*message.Message, error) { + m.mu.Lock() + defer m.mu.Unlock() + + if m.Error != nil { + return nil, m.Error + } + + var msgs []*message.Message + + for _, msg := range m.Messages { + msgs = append(msgs, msg) + } + + return msgs, nil +} + +func (m *MockMessageStore) GetMessageByID(ctx context.Context, id uuid.UUID) (*message.Message, error) { + m.mu.Lock() + defer m.mu.Unlock() + + if m.Error != nil { + return nil, m.Error + } + + msg := m.Messages[id] + + return msg, nil +} + func (m *MockMessageStore) MessageExists(ctx context.Context, msg *message.Message) (bool, error) { m.mu.Lock() defer m.mu.Unlock() diff --git a/internal/store/message_store.go b/internal/store/message_store.go index 42560e9..b262a51 100644 --- a/internal/store/message_store.go +++ b/internal/store/message_store.go @@ -4,13 +4,17 @@ import ( "context" "fmt" + "github.com/google/uuid" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "git.kundeng.us/phoenix/textsender-models/pkg/message" ) type MessageStore interface { + GetMessageByID(ctx context.Context, id uuid.UUID) (*message.Message, error) CreateMessage(ctx context.Context, msg *message.Message) error + GetAllMessages(ctx context.Context) ([]*message.Message, error) MessageExists(ctx context.Context, msg *message.Message) (bool, error) } @@ -45,3 +49,48 @@ func (m *PGMessageStore) MessageExists(ctx context.Context, msg *message.Message return exists, nil } } + +func (m *PGMessageStore) GetAllMessages(ctx context.Context) ([]*message.Message, error) { + query := `SELECT id, content, user_id FROM messages` + + rows, err := m.db.Query(ctx, query) + if err != nil { + return nil, fmt.Errorf("querying all messages: %w", err) + } + defer rows.Close() + + var messages []*message.Message + for rows.Next() { + var msg message.Message + if err := rows.Scan( + &msg.Id, &msg.Content, &msg.UserId, + ); err != nil { + return nil, fmt.Errorf("scanning message row: %w", err) + } + messages = append(messages, &msg) + } + + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("iterating message rows: %w", err) + } + + return messages, nil +} + +func (m *PGMessageStore) GetMessageByID(ctx context.Context, id uuid.UUID) (*message.Message, error) { + query := `SELECT id, content, user_id FROM messages WHERE id = $1` + + var msg message.Message + err := m.db.QueryRow(ctx, query, id).Scan( + &msg.Id, &msg.Content, &msg.UserId, + ) + + if err == pgx.ErrNoRows { + return nil, nil + } + if err != nil { + return nil, fmt.Errorf("getting message by ID: %w", err) + } + + return &msg, nil +}