tsk-12: Added endpoint to get message (#18)
Closes #12 Reviewed-on: phoenix/textsender-api#18 Co-authored-by: phoenix <kundeng00@pm.me> Co-committed-by: phoenix <kundeng00@pm.me>
This commit is contained in:
@@ -77,6 +77,7 @@ func main() {
|
|||||||
router.Handle(endpoint.ADD_CONTACT_ENDPOINT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.AddContact)))
|
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.GET_CONTACT, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(contactHandler.GetContact)))
|
||||||
router.Handle(endpoint.ADD_MESSAGE, mdlware.AuthMiddleware(jwtService)(http.HandlerFunc(messageHandler.AddMessage)))
|
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
|
// Start server
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
|
|||||||
@@ -2,5 +2,6 @@ package endpoint
|
|||||||
|
|
||||||
const MESSAGE_DRAFT_ENDPOINT = "/api/v1/message/draft"
|
const MESSAGE_DRAFT_ENDPOINT = "/api/v1/message/draft"
|
||||||
const ADD_MESSAGE = "/api/v1/message/new"
|
const ADD_MESSAGE = "/api/v1/message/new"
|
||||||
|
const GET_MESSAGE = "/api/v1/message"
|
||||||
const GET_CONTACT = "/api/v1/contact"
|
const GET_CONTACT = "/api/v1/contact"
|
||||||
const ADD_CONTACT_ENDPOINT = "/api/v1/contact/new"
|
const ADD_CONTACT_ENDPOINT = "/api/v1/contact/new"
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ type AddMessageResponse struct {
|
|||||||
Data []message.Message `json:"data"`
|
Data []message.Message `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetMessageResponse struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Data []message.Message `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
type MessageHandler struct {
|
type MessageHandler struct {
|
||||||
MessageStore store.MessageStore
|
MessageStore store.MessageStore
|
||||||
}
|
}
|
||||||
@@ -70,3 +75,79 @@ func (m *MessageHandler) AddMessage(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
RespondWithJSON(w, statusCode, &resp)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.kundeng.us/phoenix/textsender-models/pkg/message"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/stretchr/testify/assert"
|
"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")
|
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")
|
||||||
|
}
|
||||||
|
|||||||
@@ -158,6 +158,36 @@ func (m *MockMessageStore) CreateMessage(ctx context.Context, msg *message.Messa
|
|||||||
return nil
|
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) {
|
func (m *MockMessageStore) MessageExists(ctx context.Context, msg *message.Message) (bool, error) {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|||||||
@@ -4,13 +4,17 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
|
||||||
"git.kundeng.us/phoenix/textsender-models/pkg/message"
|
"git.kundeng.us/phoenix/textsender-models/pkg/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MessageStore interface {
|
type MessageStore interface {
|
||||||
|
GetMessageByID(ctx context.Context, id uuid.UUID) (*message.Message, error)
|
||||||
CreateMessage(ctx context.Context, msg *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)
|
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
|
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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user