Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions api/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,13 @@ const docTemplate = `{
"description": "include matching contact details",
"name": "contacts",
"in": "query"
},
{
"type": "boolean",
"default": false,
"description": "only include threads with unread messages",
"name": "unread_only",
"in": "query"
}
],
"responses": {
Expand Down Expand Up @@ -1203,6 +1210,62 @@ const docTemplate = `{
}
},
"/message-threads/{messageThreadID}": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns a conversation belonging to the authenticated user, including matching contact details when available.",
"produces": [
"application/json"
],
"tags": [
"MessageThreads"
],
"summary": "Get a message thread",
"parameters": [
{
"type": "string",
"description": "ID of the message thread",
"name": "messageThreadID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/responses.MessageThreadResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/responses.Unauthorized"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/responses.NotFound"
}
},
"422": {
"description": "Unprocessable Entity",
"schema": {
"$ref": "#/definitions/responses.UnprocessableEntity"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/responses.InternalServerError"
}
}
}
},
"put": {
"security": [
{
Expand Down Expand Up @@ -4204,6 +4267,7 @@ const docTemplate = `{
"entities.Phone": {
"type": "object",
"required": [
"archive_new_outgoing_message_threads",
"created_at",
"id",
"max_send_attempts",
Expand All @@ -4216,6 +4280,11 @@ const docTemplate = `{
"user_id"
],
"properties": {
"archive_new_outgoing_message_threads": {
"description": "ArchiveNewOutgoingMessageThreads archives new conversations started by an outgoing message on this phone.",
"type": "boolean",
"example": false
},
"created_at": {
"type": "string",
"example": "2022-06-05T14:26:02.302718+03:00"
Expand Down Expand Up @@ -4975,6 +5044,11 @@ const docTemplate = `{
"unarchive_thread"
],
"properties": {
"archive_new_outgoing_message_threads": {
"description": "ArchiveNewOutgoingMessageThreads archives new conversations started by an outgoing message on this phone.",
"type": "boolean",
"example": false
},
"fcm_token": {
"description": "FcmToken is either a Firebase registration token or a public HTTPS adapter callback URL.",
"type": "string",
Expand Down
74 changes: 74 additions & 0 deletions api/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,13 @@
"description": "include matching contact details",
"name": "contacts",
"in": "query"
},
{
"type": "boolean",
"default": false,
"description": "only include threads with unread messages",
"name": "unread_only",
"in": "query"
}
],
"responses": {
Expand Down Expand Up @@ -1200,6 +1207,62 @@
}
},
"/message-threads/{messageThreadID}": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns a conversation belonging to the authenticated user, including matching contact details when available.",
"produces": [
"application/json"
],
"tags": [
"MessageThreads"
],
"summary": "Get a message thread",
"parameters": [
{
"type": "string",
"description": "ID of the message thread",
"name": "messageThreadID",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/responses.MessageThreadResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/responses.Unauthorized"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/responses.NotFound"
}
},
"422": {
"description": "Unprocessable Entity",
"schema": {
"$ref": "#/definitions/responses.UnprocessableEntity"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/responses.InternalServerError"
}
}
}
},
"put": {
"security": [
{
Expand Down Expand Up @@ -4201,6 +4264,7 @@
"entities.Phone": {
"type": "object",
"required": [
"archive_new_outgoing_message_threads",
"created_at",
"id",
"max_send_attempts",
Expand All @@ -4213,6 +4277,11 @@
"user_id"
],
"properties": {
"archive_new_outgoing_message_threads": {
"description": "ArchiveNewOutgoingMessageThreads archives new conversations started by an outgoing message on this phone.",
"type": "boolean",
"example": false
},
"created_at": {
"type": "string",
"example": "2022-06-05T14:26:02.302718+03:00"
Expand Down Expand Up @@ -4972,6 +5041,11 @@
"unarchive_thread"
],
"properties": {
"archive_new_outgoing_message_threads": {
"description": "ArchiveNewOutgoingMessageThreads archives new conversations started by an outgoing message on this phone.",
"type": "boolean",
"example": false
},
"fcm_token": {
"description": "FcmToken is either a Firebase registration token or a public HTTPS adapter callback URL.",
"type": "string",
Expand Down
53 changes: 53 additions & 0 deletions api/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,11 @@ definitions:
type: object
entities.Phone:
properties:
archive_new_outgoing_message_threads:
description: ArchiveNewOutgoingMessageThreads archives new conversations started
by an outgoing message on this phone.
example: false
type: boolean
created_at:
example: "2022-06-05T14:26:02.302718+03:00"
type: string
Expand Down Expand Up @@ -452,6 +457,7 @@ definitions:
example: WB7DRDWrJZRGbYrv2CKGkqbzvqdC
type: string
required:
- archive_new_outgoing_message_threads
- created_at
- id
- max_send_attempts
Expand Down Expand Up @@ -990,6 +996,11 @@ definitions:
type: object
requests.PhoneUpsert:
properties:
archive_new_outgoing_message_threads:
description: ArchiveNewOutgoingMessageThreads archives new conversations started
by an outgoing message on this phone.
example: false
type: boolean
fcm_token:
description: FcmToken is either a Firebase registration token or a public
HTTPS adapter callback URL.
Expand Down Expand Up @@ -2510,6 +2521,11 @@ paths:
in: query
name: contacts
type: boolean
- default: false
description: only include threads with unread messages
in: query
name: unread_only
type: boolean
produces:
- application/json
responses:
Expand Down Expand Up @@ -2583,6 +2599,43 @@ paths:
summary: Delete a message thread from the database.
tags:
- MessageThreads
get:
description: Returns a conversation belonging to the authenticated user, including
matching contact details when available.
parameters:
- description: ID of the message thread
in: path
name: messageThreadID
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/responses.MessageThreadResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/responses.Unauthorized'
"404":
description: Not Found
schema:
$ref: '#/definitions/responses.NotFound'
"422":
description: Unprocessable Entity
schema:
$ref: '#/definitions/responses.UnprocessableEntity'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/responses.InternalServerError'
security:
- ApiKeyAuth: []
summary: Get a message thread
tags:
- MessageThreads
put:
consumes:
- application/json
Expand Down
3 changes: 3 additions & 0 deletions api/pkg/entities/phone.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ type Phone struct {
// UnarchiveThread moves an archived message thread back to the inbox when a new message is received on this phone.
UnarchiveThread bool `json:"unarchive_thread" gorm:"default:false" example:"false"`

// ArchiveNewOutgoingMessageThreads archives new conversations started by an outgoing message on this phone.
ArchiveNewOutgoingMessageThreads bool `json:"archive_new_outgoing_message_threads" gorm:"default:false" example:"false"`

CreatedAt time.Time `json:"created_at" example:"2022-06-05T14:26:02.302718+03:00"`
UpdatedAt time.Time `json:"updated_at" example:"2022-06-05T14:26:10.303278+03:00"`
}
Expand Down
37 changes: 36 additions & 1 deletion api/pkg/handlers/message_thread_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func NewMessageThreadHandler(
// RegisterRoutes registers the routes for the MessageHandler
func (h *MessageThreadHandler) RegisterRoutes(router fiber.Router, middlewares ...fiber.Handler) {
h.register(router, fiber.MethodGet, "/v1/message-threads", middlewares, h.Index)
h.register(router, fiber.MethodGet, "/v1/message-threads/:messageThreadID", middlewares, h.Get)
h.register(router, fiber.MethodPut, "/v1/message-threads/:messageThreadID", middlewares, h.Update)
h.register(router, fiber.MethodDelete, "/v1/message-threads/:messageThreadID", middlewares, h.Delete)
}
Expand All @@ -58,6 +59,7 @@ func (h *MessageThreadHandler) RegisterRoutes(router fiber.Router, middlewares .
// @Param query query string false "filter message threads containing query"
// @Param limit query int false "number of messages to return" minimum(1) maximum(20)
// @Param contacts query bool false "include matching contact details"
// @Param unread_only query bool false "only include threads with unread messages" default(false)
// @Success 200 {object} responses.MessageThreadsResponse
// @Failure 400 {object} responses.BadRequest
// @Failure 401 {object} responses.Unauthorized
Expand Down Expand Up @@ -92,6 +94,39 @@ func (h *MessageThreadHandler) Index(c fiber.Ctx) error {
return h.responseOK(c, fmt.Sprintf("fetched %d message %s", len(*threads), h.pluralize("thread", len(*threads))), threads)
}

// Get returns a single entities.MessageThread independently of list filters and pagination.
// @Summary Get a message thread
// @Description Returns a conversation belonging to the authenticated user, including matching contact details when available.
// @Security ApiKeyAuth
// @Tags MessageThreads
// @Produce json
// @Param messageThreadID path string true "ID of the message thread"
// @Success 200 {object} responses.MessageThreadResponse
// @Failure 401 {object} responses.Unauthorized
// @Failure 404 {object} responses.NotFound
// @Failure 422 {object} responses.UnprocessableEntity
// @Failure 500 {object} responses.InternalServerError
// @Router /message-threads/{messageThreadID} [get]
func (h *MessageThreadHandler) Get(c fiber.Ctx) error {
ctx, span, ctxLogger := h.tracer.StartFromFiberCtxWithLogger(c, h.logger)
defer span.End()

id := c.Params("messageThreadID")
if errors := h.validator.ValidateUUID(id, "messageThreadID"); len(errors) != 0 {
ctxLogger.Warn(stacktrace.NewErrorf("invalid message thread ID [%s]", id))
return h.responseUnprocessableEntity(c, errors, "validation errors while fetching a message thread")
}
thread, err := h.service.GetThread(ctx, h.userIDFomContext(c), uuid.MustParse(id), true)
if stacktrace.GetCode(err) == repositories.ErrCodeNotFound {
return h.responseNotFound(c, fmt.Sprintf("cannot find message thread with ID [%s]", id))
}
if err != nil {
ctxLogger.Error(stacktrace.Propagatef(err, "cannot fetch message thread [%s]", id))
return h.responseInternalServerError(c)
}
return h.responseOK(c, "message thread fetched successfully", thread)
}

// Update an entities.MessageThread
// @Summary Update a message thread
// @Description Updates the details of a message thread
Expand Down Expand Up @@ -161,7 +196,7 @@ func (h *MessageThreadHandler) Delete(c fiber.Ctx) error {
return h.responseUnprocessableEntity(c, errors, "validation errors while deleting a thread thread")
}

thread, err := h.service.GetThread(ctx, h.userIDFomContext(c), uuid.MustParse(messageThreadID))
thread, err := h.service.GetThread(ctx, h.userIDFomContext(c), uuid.MustParse(messageThreadID), false)
if stacktrace.GetCode(err) == repositories.ErrCodeNotFound {
return h.responseNotFound(c, fmt.Sprintf("cannot find thread thread with ID [%s]", messageThreadID))
}
Expand Down
Loading
Loading