forked from NdoleStudio/httpsms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmessage_thread_handler.go
More file actions
184 lines (160 loc) · 7.93 KB
/
message_thread_handler.go
File metadata and controls
184 lines (160 loc) · 7.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package handlers
import (
"fmt"
"github.com/NdoleStudio/httpsms/pkg/repositories"
"github.com/google/uuid"
"github.com/NdoleStudio/httpsms/pkg/requests"
"github.com/NdoleStudio/httpsms/pkg/services"
"github.com/NdoleStudio/httpsms/pkg/telemetry"
"github.com/NdoleStudio/httpsms/pkg/validators"
"github.com/davecgh/go-spew/spew"
"github.com/gofiber/fiber/v2"
"github.com/palantir/stacktrace"
)
// MessageThreadHandler handles message-thead http requests.
type MessageThreadHandler struct {
handler
logger telemetry.Logger
tracer telemetry.Tracer
validator *validators.MessageThreadHandlerValidator
service *services.MessageThreadService
}
// NewMessageThreadHandler creates a new MessageThreadHandler
func NewMessageThreadHandler(
logger telemetry.Logger,
tracer telemetry.Tracer,
validator *validators.MessageThreadHandlerValidator,
service *services.MessageThreadService,
) (h *MessageThreadHandler) {
return &MessageThreadHandler{
logger: logger.WithService(fmt.Sprintf("%T", h)),
tracer: tracer,
validator: validator,
service: service,
}
}
// RegisterRoutes registers the routes for the MessageHandler
func (h *MessageThreadHandler) RegisterRoutes(router fiber.Router, middlewares ...fiber.Handler) {
router.Get("/v1/message-threads", h.computeRoute(middlewares, h.Index)...)
router.Put("/v1/message-threads/:messageThreadID", h.computeRoute(middlewares, h.Update)...)
router.Delete("/v1/message-threads/:messageThreadID", h.computeRoute(middlewares, h.Delete)...)
}
// Index returns message threads for a phone number
// @Summary Get message threads for a phone number
// @Description Get list of contacts which a phone number has communicated with (threads). It will be sorted by timestamp in descending order.
// @Security ApiKeyAuth
// @Tags MessageThreads
// @Accept json
// @Produce json
// @Param owner query string true "owner phone number" default(+18005550199)
// @Param skip query int false "number of messages to skip" minimum(0)
// @Param query query string false "filter message threads containing query"
// @Param limit query int false "number of messages to return" minimum(1) maximum(20)
// @Success 200 {object} responses.MessageThreadsResponse
// @Failure 400 {object} responses.BadRequest
// @Failure 401 {object} responses.Unauthorized
// @Failure 422 {object} responses.UnprocessableEntity
// @Failure 500 {object} responses.InternalServerError
// @Router /message-threads [get]
func (h *MessageThreadHandler) Index(c *fiber.Ctx) error {
ctx, span := h.tracer.StartFromFiberCtx(c)
defer span.End()
ctxLogger := h.tracer.CtxLogger(h.logger, span)
ctxLogger.Info(c.OriginalURL())
var request requests.MessageThreadIndex
if err := c.QueryParser(&request); err != nil {
msg := fmt.Sprintf("cannot marshall params [%s] into %T", c.OriginalURL(), request)
ctxLogger.Warn(stacktrace.Propagate(err, msg))
return h.responseBadRequest(c, err)
}
if errors := h.validator.ValidateMessageThreadIndex(ctx, request.Sanitize()); len(errors) != 0 {
msg := fmt.Sprintf("validation errors [%s], while fetching message threads [%+#v]", spew.Sdump(errors), request)
ctxLogger.Warn(stacktrace.NewError(msg))
return h.responseUnprocessableEntity(c, errors, "validation errors while fetching message threads")
}
threads, err := h.service.GetThreads(ctx, request.ToGetParams(h.userIDFomContext(c)))
if err != nil {
msg := fmt.Sprintf("cannot get message threads with params [%+#v]", request)
ctxLogger.Error(stacktrace.Propagate(err, msg))
return h.responseInternalServerError(c)
}
return h.responseOK(c, fmt.Sprintf("fetched %d message %s", len(*threads), h.pluralize("thread", len(*threads))), threads)
}
// Update an entities.MessageThread
// @Summary Update a message thread
// @Description Updates the details of a message thread
// @Security ApiKeyAuth
// @Tags MessageThreads
// @Accept json
// @Produce json
// @Param messageThreadID path string true "ID of the message thread" default(32343a19-da5e-4b1b-a767-3298a73703ca)
// @Param payload body requests.MessageThreadUpdate true "Payload of message thread details to update"
// @Success 200 {object} responses.PhoneResponse
// @Failure 400 {object} responses.BadRequest
// @Failure 401 {object} responses.Unauthorized
// @Failure 422 {object} responses.UnprocessableEntity
// @Failure 500 {object} responses.InternalServerError
// @Router /message-threads/{messageThreadID} [put]
func (h *MessageThreadHandler) Update(c *fiber.Ctx) error {
ctx, span, ctxLogger := h.tracer.StartFromFiberCtxWithLogger(c, h.logger)
defer span.End()
var request requests.MessageThreadUpdate
if err := c.BodyParser(&request); err != nil {
msg := fmt.Sprintf("cannot marshall params [%s] into %T", c.OriginalURL(), request)
ctxLogger.Warn(stacktrace.Propagate(err, msg))
return h.responseBadRequest(c, err)
}
request.MessageThreadID = c.Params("messageThreadID")
if errors := h.validator.ValidateUpdate(ctx, request); len(errors) != 0 {
msg := fmt.Sprintf("validation errors [%s], while updating message thread [%+#v]", spew.Sdump(errors), request)
ctxLogger.Warn(stacktrace.NewError(msg))
return h.responseUnprocessableEntity(c, errors, "validation errors while updating message thread")
}
thread, err := h.service.UpdateStatus(ctx, request.ToUpdateParams(h.userIDFomContext(c)))
if err != nil {
msg := fmt.Sprintf("cannot update message thread with params [%+#v]", request)
ctxLogger.Error(stacktrace.Propagate(err, msg))
return h.responseInternalServerError(c)
}
return h.responseOK(c, "message thread updated successfully", thread)
}
// Delete a message thread
// @Summary Delete a message thread from the database.
// @Description Delete a message thread from the database and also deletes all the messages in the thread.
// @Security ApiKeyAuth
// @Tags MessageThreads
// @Accept json
// @Produce json
// @Param messageThreadID path string true "ID of the message thread" default(32343a19-da5e-4b1b-a767-3298a73703ca)
// @Success 204 {object} responses.NoContent
// @Failure 400 {object} responses.BadRequest
// @Failure 401 {object} responses.Unauthorized
// @Failure 404 {object} responses.NotFound
// @Failure 422 {object} responses.UnprocessableEntity
// @Failure 500 {object} responses.InternalServerError
// @Router /message-threads/{messageThreadID} [delete]
func (h *MessageThreadHandler) Delete(c *fiber.Ctx) error {
ctx, span, ctxLogger := h.tracer.StartFromFiberCtxWithLogger(c, h.logger)
defer span.End()
messageThreadID := c.Params("messageThreadID")
if errors := h.validator.ValidateUUID(messageThreadID, "messageThreadID"); len(errors) != 0 {
msg := fmt.Sprintf("validation errors [%s], while deleting a thread thread with ID [%s]", spew.Sdump(errors), messageThreadID)
ctxLogger.Warn(stacktrace.NewError(msg))
return h.responseUnprocessableEntity(c, errors, "validation errors while deleting a thread thread")
}
thread, err := h.service.GetThread(ctx, h.userIDFomContext(c), uuid.MustParse(messageThreadID))
if stacktrace.GetCode(err) == repositories.ErrCodeNotFound {
return h.responseNotFound(c, fmt.Sprintf("cannot find thread thread with ID [%s]", messageThreadID))
}
if err != nil {
msg := fmt.Sprintf("cannot find thread thread with id [%s]", messageThreadID)
ctxLogger.Error(h.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg)))
return h.responseInternalServerError(c)
}
if err = h.service.DeleteThread(ctx, c.OriginalURL(), thread); err != nil {
msg := fmt.Sprintf("cannot delete thread thread with ID [%s] for user with ID [%s]", messageThreadID, thread.UserID)
ctxLogger.Error(h.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg)))
return h.responseInternalServerError(c)
}
return h.responseNoContent(c, "thread thread deleted successfully")
}