diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..4cc48bc
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,75 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+---
+
+## [0.0.8] - 2023-10-17 (CHB-11)
+
+### Added
+
+- Added CORS permissions so local Angular can connect to local Go by [Arturo Vial](https://github.com/ratolibre1)
+
+## [0.0.7] - 2023-10-17 (CHB-9)
+
+### Added
+
+- Added new endpoint to get full list of chatrooms by [Arturo Vial](https://github.com/ratolibre1)
+
+## [0.0.6] - 2023-10-17 (CHB-7)
+
+### Added
+
+- Added new endpoints to validate login details and return a JWT token by [Arturo Vial](https://github.com/ratolibre1)
+- Added Auth module by [Arturo Vial](https://github.com/ratolibre1)
+- Added functions to find users by email, hash and validate passwords by [Arturo Vial](https://github.com/ratolibre1)
+
+## [0.0.5] - 2023-10-16 (CHB-6)
+
+### Added
+
+- Added new endpoints to enter and leave chatrooms by [Arturo Vial](https://github.com/ratolibre1)
+- Added Chatrooms and Users modules by [Arturo Vial](https://github.com/ratolibre1)
+
+### Changed
+
+- Cleaned some English errors in original project by [Arturo Vial](https://github.com/ratolibre1)
+
+### Removed
+
+- Removed some calls to original User package (to be removed in the future) by [Arturo Vial](https://github.com/ratolibre1)
+
+## [0.0.4] - 2023-10-15 (CHB-3)
+
+### Added
+
+- Sending a command-like message gets its own workflow instead of storing it by [Arturo Vial](https://github.com/ratolibre1)
+
+### Changed
+
+- Renamed the module to "chat-hex" by [Arturo Vial](https://github.com/ratolibre1)
+
+## [0.0.3] - 2023-10-15 (CHB-2)
+
+### Added
+
+- Added new endpoint to list messages from a specific chatroom by [Arturo Vial](https://github.com/ratolibre1)
+
+## [0.0.2] - 2023-10-14 (CHB-1)
+
+### Added
+
+- Added Messages folders and endpoint to send a message by [Arturo Vial](https://github.com/ratolibre1)
+
+## [0.0.1] - 2023-10-14
+
+### Added
+
+- Hexagonal Architecture scaffolding forked from [Github](https://github.com/favians/go-hexagonal) by [Arturo Vial](https://github.com/ratolibre1)
+
+### Changed
+
+- Cleaned some stuff, ensured connection with DB by [Arturo Vial](https://github.com/ratolibre1)
diff --git a/README.md b/README.md
index 0ca8cc6..727225b 100644
--- a/README.md
+++ b/README.md
@@ -1,55 +1,11 @@
-# Sample Golang API Server
-
-Sample REST API build using echo server.
-
-The code implementation was inspired by port and adapter pattern or known as [hexagonal](blog.octo.com/en/hexagonal-architecture-three-principles-and-an-implementation-example):
-
-- **Business**
Contains all the logic in domain business. Also called this as a service. All the interface of repository needed and the implementation of the service itself will be put here.
-- **Modules**
Contains implementation of interfaces that defined at the business (also called as server-side adapters in hexagonal's term)
-- **API**
API http handler or controller (also called user-side adapters in hexagonal's term)
-
-# Data initialization
-
-To describe about how port and adapter interaction (separation concerned), this example will have two databases supported. There are MySQL and MongoDB.
-
-MongoDB will become a default databaese in this example. If you want to change into MySQL, update the configuration inside
-[config.yaml](https://raw.githubusercontent.com/muhsinshodiq/golang-sample-api/master/config/config.yaml) file.
-
### MongoDB
-Please execute script below to create a new collection called `items` including the index needed
+Please execute script below to create the collections required to run the app
```mongodb
-db.createCollection('items');
-db.items.createIndex({"tags": 1});
-db.items.createIndex({"modified_at": 1, "_id": 1});
-```
-
-### MySQL
-
-Please execute script below to create `item` and `item_tag` table in your database
-
-```sql
-CREATE TABLE `item` (
- `id` varchar(24) NOT NULL DEFAULT '',
- `name` text NOT NULL,
- `description` text NOT NULL,
- `created_at` datetime NOT NULL,
- `created_by` varchar(50) NOT NULL DEFAULT '',
- `modified_at` datetime NOT NULL,
- `modified_by` varchar(50) NOT NULL DEFAULT '',
- `version` int(11) NOT NULL DEFAULT '1',
- PRIMARY KEY (`id`),
- KEY `modified_at` (`modified_at`,`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-
-CREATE TABLE `item_tag` (
- `item_id` varchar(24) NOT NULL DEFAULT '',
- `tag` varchar(50) NOT NULL DEFAULT '',
- PRIMARY KEY (`item_id`,`tag`),
- KEY `tag` (`tag`),
- CONSTRAINT `item_tag_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+db.createCollection('users');
+db.createCollection('messages');
+db.createCollection('chatrooms');
```
# How To Run Server
@@ -59,14 +15,3 @@ Just execute code below in your console
```console
./run.sh
```
-
-# How To Consume The API
-
-There are 4 availables API that ready to use:
-
-- GET `/v1/items/:id`
-- GET `/v1/items/[tag-name]`
-- POST `/v1/items`
-- PUT `/v1/items`
-
-To make it easier please download [Insomnia Core](https://insomnia.rest) app and import [this collection](https://raw.githubusercontent.com/muhsinshodiq/golang-sample-api/master/insomnia.json).
diff --git a/api/common/error_business_response.go b/api/common/error_business_response.go
index 3974228..cb03823 100644
--- a/api/common/error_business_response.go
+++ b/api/common/error_business_response.go
@@ -1,7 +1,7 @@
package common
import (
- "go-hexagonal/business"
+ "chat-hex/business"
"net/http"
)
@@ -12,6 +12,7 @@ const (
errHasBeenModified errorBusinessResponseCode = "data_has_been modified"
errNotFound errorBusinessResponseCode = "data_not_found"
errInvalidSpec errorBusinessResponseCode = "invalid_spec"
+ ErrInvalidCommand errorBusinessResponseCode = "invalid_command"
)
//BusinessResponse default payload response
@@ -21,7 +22,7 @@ type BusinessResponse struct {
Data interface{} `json:"data"`
}
-//NewErrorBusinessResponse Response return choosen http status like 400 bad request 422 unprocessable entity, ETC, based on responseCode
+//NewErrorBusinessResponse Response return chosen http status like 400 bad request 422 unprocessable entity, ETC, based on responseCode
func NewErrorBusinessResponse(err error) (int, BusinessResponse) {
return errorMapping(err)
}
@@ -35,8 +36,10 @@ func errorMapping(err error) (int, BusinessResponse) {
return newNotFoundResponse()
case business.ErrInvalidSpec:
return newValidationResponse(err.Error())
+ case business.ErrInvalidCommand:
+ return newValidationResponse(err.Error())
case business.ErrHasBeenModified:
- return newHasBeedModifiedResponse()
+ return newHasBeenModifiedResponse()
}
}
@@ -49,8 +52,8 @@ func newInternalServerErrorResponse() (int, BusinessResponse) {
}
}
-//newHasBeedModifiedResponse failed to validate request payload
-func newHasBeedModifiedResponse() (int, BusinessResponse) {
+//newHasBeenModifiedResponse failed to validate request payload
+func newHasBeenModifiedResponse() (int, BusinessResponse) {
return http.StatusBadRequest, BusinessResponse{
errHasBeenModified,
"Data has been modified",
diff --git a/api/insomnia.json b/api/insomnia.json
deleted file mode 100644
index bb269cd..0000000
--- a/api/insomnia.json
+++ /dev/null
@@ -1 +0,0 @@
-{"_type":"export","__export_format":4,"__export_date":"2020-08-21T02:47:11.306Z","__export_source":"insomnia.desktop.app:v2020.3.3","resources":[{"_id":"req_1c9b323b350c4e7686691fec9a1c704a","authentication":{},"body":{},"created":1597464771713,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1597464771714,"method":"GET","modified":1597977851048,"name":"Get Item By ID","parameters":[],"parentId":"fld_689377616fa049498b9dcaf20772b9e1","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ ITEM_TEST_HOST }}/v1/items/5f3f34f77611be3eb089e266","_type":"request"},{"_id":"fld_689377616fa049498b9dcaf20772b9e1","created":1597464693939,"description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1597464693939,"modified":1597978012668,"name":"Golang Sample API","parentId":"wrk_6fb5cf0f746044b2bdfe8bba6ba2ef73","_type":"request_group"},{"_id":"wrk_6fb5cf0f746044b2bdfe8bba6ba2ef73","created":1597464672977,"description":"","modified":1597464672977,"name":"Playground","parentId":null,"scope":null,"_type":"workspace"},{"_id":"req_f41a666217ea4bb2919066f9077f1618","authentication":{},"body":{},"created":1597464962599,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1596770774963,"method":"GET","modified":1597486085313,"name":"Find Items By Tag","parameters":[],"parentId":"fld_689377616fa049498b9dcaf20772b9e1","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ ITEM_TEST_HOST }}/v1/items/tag/tag99","_type":"request"},{"_id":"req_713c323624964879a174a70a8fb0771f","authentication":{},"body":{"mimeType":"application/json","text":"{\n\t\"name\": \"New item\",\n\t\"description\": \"new\",\n\t\"tags\": []\n}"},"created":1597467138311,"description":"","headers":[{"id":"pair_0afa504b87d1493388d95ff4a4279953","name":"Content-Type","value":"application/json"}],"isPrivate":false,"metaSortKey":-1596423776587.5,"method":"POST","modified":1597467404785,"name":"Create New Item","parameters":[],"parentId":"fld_689377616fa049498b9dcaf20772b9e1","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ ITEM_TEST_HOST }}/v1/items","_type":"request"},{"_id":"req_504bc4a0d77a481c893169b7448025f7","authentication":{},"body":{"mimeType":"application/json","text":"{\n\t\"name\": \"New Item (updated2)\",\n\t\"description\": \"Description (updated)\",\n\t\"tags\": [\"tag99\"],\n\t\"version\": 1\n}"},"created":1597471472348,"description":"","headers":[{"id":"pair_0afa504b87d1493388d95ff4a4279953","name":"Content-Type","value":"application/json"}],"isPrivate":false,"metaSortKey":-1596250277399.75,"method":"PUT","modified":1597977860143,"name":"Update Item","parameters":[],"parentId":"fld_689377616fa049498b9dcaf20772b9e1","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ ITEM_TEST_HOST }}/v1/items/5f3f34f77611be3eb089e266","_type":"request"},{"_id":"env_78c71dbf04e35be6defe8946da09238e9868f15e","color":null,"created":1597464673272,"data":{"ITEM_TEST_HOST":"http://localhost:1323"},"dataPropertyOrder":{"&":["ITEM_TEST_HOST"]},"isPrivate":false,"metaSortKey":1597464673272,"modified":1597464735914,"name":"Base Environment","parentId":"wrk_6fb5cf0f746044b2bdfe8bba6ba2ef73","_type":"environment"},{"_id":"jar_78c71dbf04e35be6defe8946da09238e9868f15e","cookies":[],"created":1597464673277,"modified":1597464673277,"name":"Default Jar","parentId":"wrk_6fb5cf0f746044b2bdfe8bba6ba2ef73","_type":"cookie_jar"},{"_id":"spc_0200e9dc6d41429c82ff51946f56442c","contentType":"yaml","contents":"","created":1597464673003,"fileName":"Playground","modified":1597464673003,"parentId":"wrk_6fb5cf0f746044b2bdfe8bba6ba2ef73","_type":"api_spec"}]}
\ No newline at end of file
diff --git a/api/router.go b/api/router.go
index ec8be04..7499980 100644
--- a/api/router.go
+++ b/api/router.go
@@ -1,23 +1,46 @@
package api
import (
- "go-hexagonal/api/v1/user"
+ "chat-hex/api/v1/auth"
+ "chat-hex/api/v1/chatrooms"
+ "chat-hex/api/v1/messages"
+ "chat-hex/api/v1/users"
+ "chat-hex/middlewares"
echo "github.com/labstack/echo/v4"
)
-//RegisterPath Register all V1 API with routing path
-func RegisterPath(e *echo.Echo, userController *user.Controller) {
- if userController == nil {
- panic("user controller cannot be nil")
+//RegisterPaths Register all V1 API with routing path
+func RegisterPaths(e *echo.Echo, authController *auth.Controller, usersController *users.Controller, chatroomsController *chatrooms.Controller, messagesController *messages.Controller) {
+ if authController == nil {
+ panic("auth controller cannot be nil")
}
- //user
- userV1 := e.Group("v1/users")
- userV1.GET("/:id", userController.FindUserByID)
- userV1.GET("", userController.FindAllUserWithPagination)
- userV1.POST("", userController.InsertUser)
- userV1.PUT("/:id", userController.UpdateUser)
+ if usersController == nil {
+ panic("users controller cannot be nil")
+ }
+
+ if messagesController == nil {
+ panic("messages controller cannot be nil")
+ }
+
+ //auth
+ authV1 := e.Group("v1/auth")
+ authV1.POST("/token", authController.GenerateToken)
+
+ //users
+ usersV1 := e.Group("v1/users")
+ usersV1.PATCH("/enter-chatroom", middlewares.Auth(usersController.EnterChatroom, authController.AuthError))
+ usersV1.PATCH("/leave-chatroom", middlewares.Auth(usersController.LeaveChatroom, authController.AuthError))
+
+ //chatrooms
+ chatroomsV1 := e.Group("v1/chatrooms")
+ chatroomsV1.GET("", middlewares.Auth(chatroomsController.GetChatrooms, authController.AuthError))
+
+ //messages
+ messagesV1 := e.Group("v1/messages")
+ messagesV1.POST("", middlewares.Auth(messagesController.InsertMessage, authController.AuthError))
+ messagesV1.GET("/:chatroom", middlewares.Auth(messagesController.GetMessagesByChatroom, authController.AuthError))
//health check
e.GET("/health", func(c echo.Context) error {
diff --git a/api/v1/auth/controller.go b/api/v1/auth/controller.go
new file mode 100644
index 0000000..785ef55
--- /dev/null
+++ b/api/v1/auth/controller.go
@@ -0,0 +1,52 @@
+package auth
+
+import (
+ "chat-hex/api/common"
+ "chat-hex/api/v1/auth/requests"
+ "chat-hex/business/auth"
+ "chat-hex/business/users"
+
+ "github.com/labstack/echo/v4"
+)
+
+type Controller struct {
+ service auth.Service
+ usersService users.Service
+}
+
+func NewController(service auth.Service, usersService users.Service) *Controller {
+ return &Controller{
+ service,
+ usersService,
+ }
+}
+
+func (controller *Controller) GenerateToken(c echo.Context) error {
+ generateTokenRequest := new(requests.GenerateTokenRequest)
+
+ err := c.Bind(generateTokenRequest)
+ if err != nil {
+ return c.JSON(common.NewBadRequestResponse())
+ }
+
+ user, err := controller.usersService.FindUserByEmail(generateTokenRequest.Email)
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+
+ err = controller.usersService.CheckPassword(user.Password, generateTokenRequest.Password)
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+
+ response, err := controller.service.GenerateJWT(*generateTokenRequest.ToGenerateTokenSpec())
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+
+ return c.JSON(common.NewSuccessResponse(response))
+}
+
+func (controller *Controller) AuthError(c echo.Context) error {
+ return c.JSON(common.NewForbiddenResponse())
+}
\ No newline at end of file
diff --git a/api/v1/auth/requests/generate_token.go b/api/v1/auth/requests/generate_token.go
new file mode 100644
index 0000000..c87e5fa
--- /dev/null
+++ b/api/v1/auth/requests/generate_token.go
@@ -0,0 +1,17 @@
+package requests
+
+import "chat-hex/business/auth"
+
+type GenerateTokenRequest struct {
+ Email string `json:"email"`
+ Password string `json:"password"`
+}
+
+func (req *GenerateTokenRequest) ToGenerateTokenSpec() *auth.GenerateTokenSpec {
+ var generateTokenSpec auth.GenerateTokenSpec
+
+ generateTokenSpec.Email = req.Email
+ generateTokenSpec.Password = req.Password
+
+ return &generateTokenSpec
+}
\ No newline at end of file
diff --git a/api/v1/chatrooms/controller.go b/api/v1/chatrooms/controller.go
new file mode 100644
index 0000000..6f502d3
--- /dev/null
+++ b/api/v1/chatrooms/controller.go
@@ -0,0 +1,30 @@
+package chatrooms
+
+import (
+ "chat-hex/api/common"
+ "chat-hex/api/v1/chatrooms/responses"
+ "chat-hex/business/chatrooms"
+
+ "github.com/labstack/echo/v4"
+)
+
+type Controller struct {
+ service chatrooms.Service
+}
+
+func NewController(service chatrooms.Service) *Controller {
+ return &Controller{
+ service,
+ }
+}
+
+func (controller *Controller) GetChatrooms(c echo.Context) error {
+ chatrooms, err := controller.service.GetChatrooms()
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+
+ response := responses.NewGetChatroomsResponse(chatrooms)
+
+ return c.JSON(common.NewSuccessResponse(response))
+}
\ No newline at end of file
diff --git a/api/v1/chatrooms/responses/get_chatrooms.go b/api/v1/chatrooms/responses/get_chatrooms.go
new file mode 100644
index 0000000..d9e230e
--- /dev/null
+++ b/api/v1/chatrooms/responses/get_chatrooms.go
@@ -0,0 +1,33 @@
+package responses
+
+import "chat-hex/business/chatrooms"
+
+type chatroomResponse struct {
+ Name string `json:"name"`
+ Desc string `json:"desc"`
+ Code string `json:"code"`
+}
+
+type getChatroomsResponse struct {
+ Chatrooms []chatroomResponse `json:"chatrooms"`
+}
+
+func NewGetChatroomsResponse(chatrooms []chatrooms.Chatroom) getChatroomsResponse {
+ getChatroomsResponse := getChatroomsResponse{}
+
+ for _, value := range chatrooms {
+ var chatroomResponse chatroomResponse
+
+ chatroomResponse.Name = value.Name
+ chatroomResponse.Desc = value.Desc
+ chatroomResponse.Code = value.Code
+
+ getChatroomsResponse.Chatrooms = append(getChatroomsResponse.Chatrooms, chatroomResponse)
+ }
+
+ if getChatroomsResponse.Chatrooms == nil {
+ getChatroomsResponse.Chatrooms = []chatroomResponse{}
+ }
+
+ return getChatroomsResponse
+}
\ No newline at end of file
diff --git a/api/v1/messages/controller.go b/api/v1/messages/controller.go
new file mode 100644
index 0000000..ed6caf8
--- /dev/null
+++ b/api/v1/messages/controller.go
@@ -0,0 +1,60 @@
+package messages
+
+import (
+ "chat-hex/api/common"
+ "chat-hex/api/v1/messages/requests"
+ "chat-hex/api/v1/messages/responses"
+ "chat-hex/business/commands"
+ "chat-hex/business/messages"
+
+ "github.com/labstack/echo/v4"
+)
+
+type Controller struct {
+ service messages.Service
+ commandsService commands.Service
+}
+
+func NewController(service messages.Service, commandsService commands.Service) *Controller {
+ return &Controller{
+ service,
+ commandsService,
+ }
+}
+
+func (controller *Controller) InsertMessage(c echo.Context) error {
+ insertMessageRequest := new(requests.InsertMessageRequest)
+
+ err := c.Bind(insertMessageRequest)
+ if err != nil {
+ return c.JSON(common.NewBadRequestResponse())
+ }
+
+ messageHasCommandStructure := controller.service.MessageHasCommandStructure(*insertMessageRequest.ToInsertMessageSpec())
+ if messageHasCommandStructure {
+ err = controller.commandsService.ProcessCommand(*insertMessageRequest.ToCommandSpec())
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+ } else {
+ err = controller.service.InsertMessage(*insertMessageRequest.ToInsertMessageSpec())
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+ }
+
+ return c.JSON(common.NewSuccessResponseWithoutData())
+}
+
+func (controller *Controller) GetMessagesByChatroom(c echo.Context) error {
+ chatroom := c.Param("chatroom")
+
+ messages, err := controller.service.GetMessagesByChatroom(chatroom)
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+
+ response := responses.NewGetMessagesByChatroomResponse(messages)
+
+ return c.JSON(common.NewSuccessResponse(response))
+}
\ No newline at end of file
diff --git a/api/v1/messages/requests/insert_message.go b/api/v1/messages/requests/insert_message.go
new file mode 100644
index 0000000..833573e
--- /dev/null
+++ b/api/v1/messages/requests/insert_message.go
@@ -0,0 +1,32 @@
+package requests
+
+import (
+ "chat-hex/business/commands"
+ "chat-hex/business/messages"
+)
+
+type InsertMessageRequest struct {
+ Content string `json:"content"`
+ Sender string `json:"sender"`
+ Chatroom string `json:"chatroom"`
+}
+
+func (req *InsertMessageRequest) ToInsertMessageSpec() *messages.InsertMessageSpec {
+ var insertMessageSpec messages.InsertMessageSpec
+
+ insertMessageSpec.Content = req.Content
+ insertMessageSpec.Sender = req.Sender
+ insertMessageSpec.Chatroom = req.Chatroom
+
+ return &insertMessageSpec
+}
+
+func (req *InsertMessageRequest) ToCommandSpec() *commands.CommandSpec {
+ var commandSpec commands.CommandSpec
+
+ commandSpec.Content = req.Content
+ commandSpec.Sender = req.Sender
+ commandSpec.Chatroom = req.Chatroom
+
+ return &commandSpec
+}
\ No newline at end of file
diff --git a/api/v1/messages/responses/get_messages_by_chatroom.go b/api/v1/messages/responses/get_messages_by_chatroom.go
new file mode 100644
index 0000000..a933a34
--- /dev/null
+++ b/api/v1/messages/responses/get_messages_by_chatroom.go
@@ -0,0 +1,38 @@
+package responses
+
+import (
+ "chat-hex/business/messages"
+ "time"
+)
+
+type getMessageResponse struct {
+ Id string `json:"id"`
+ Content string `json:"content"`
+ Sender string `json:"sender"`
+ Timestamp time.Time `json:"timestamp"`
+}
+
+type getMessagesByChatroomResponse struct {
+ Messages []getMessageResponse `json:"messages"`
+}
+
+func NewGetMessagesByChatroomResponse(messages []messages.Message) getMessagesByChatroomResponse {
+ getMessagesByChatroomResponse := getMessagesByChatroomResponse{}
+
+ for _, value := range messages {
+ var getMessageResponse getMessageResponse
+
+ getMessageResponse.Id = value.Id
+ getMessageResponse.Content = value.Content
+ getMessageResponse.Sender = value.Sender
+ getMessageResponse.Timestamp = value.Timestamp
+
+ getMessagesByChatroomResponse.Messages = append(getMessagesByChatroomResponse.Messages, getMessageResponse)
+ }
+
+ if getMessagesByChatroomResponse.Messages == nil {
+ getMessagesByChatroomResponse.Messages = []getMessageResponse{}
+ }
+
+ return getMessagesByChatroomResponse
+}
\ No newline at end of file
diff --git a/api/v1/user/controller.go b/api/v1/user/controller.go
index 07d4a4b..b3f808d 100644
--- a/api/v1/user/controller.go
+++ b/api/v1/user/controller.go
@@ -1,10 +1,10 @@
package user
import (
- "go-hexagonal/api/common"
- "go-hexagonal/api/v1/user/request"
- "go-hexagonal/api/v1/user/response"
- "go-hexagonal/business/user"
+ "chat-hex/api/common"
+ "chat-hex/api/v1/user/request"
+ "chat-hex/api/v1/user/response"
+ "chat-hex/business/user"
"strconv"
echo "github.com/labstack/echo/v4"
diff --git a/api/v1/user/request/insert_user.go b/api/v1/user/request/insert_user.go
index e5a4643..5ac27b0 100644
--- a/api/v1/user/request/insert_user.go
+++ b/api/v1/user/request/insert_user.go
@@ -1,6 +1,6 @@
package request
-import "go-hexagonal/business/user"
+import "chat-hex/business/user"
//InsertUserRequest create User request payload
type InsertUserRequest struct {
diff --git a/api/v1/user/response/get_all_user.go b/api/v1/user/response/get_all_user.go
index 934df8a..87b399f 100644
--- a/api/v1/user/response/get_all_user.go
+++ b/api/v1/user/response/get_all_user.go
@@ -1,6 +1,6 @@
package response
-import "go-hexagonal/business/user"
+import "chat-hex/business/user"
type getAllUserResponse struct {
Meta meta `json:"meta"`
diff --git a/api/v1/user/response/get_user.go b/api/v1/user/response/get_user.go
index ec22c59..fd9581b 100644
--- a/api/v1/user/response/get_user.go
+++ b/api/v1/user/response/get_user.go
@@ -1,7 +1,7 @@
package response
import (
- "go-hexagonal/business/user"
+ "chat-hex/business/user"
"time"
)
diff --git a/api/v1/users/controller.go b/api/v1/users/controller.go
new file mode 100644
index 0000000..b79d1be
--- /dev/null
+++ b/api/v1/users/controller.go
@@ -0,0 +1,51 @@
+package users
+
+import (
+ "chat-hex/api/common"
+ "chat-hex/api/v1/users/requests"
+ "chat-hex/business/users"
+
+ "github.com/labstack/echo/v4"
+)
+
+type Controller struct {
+ service users.Service
+}
+
+func NewController(service users.Service) *Controller {
+ return &Controller{
+ service,
+ }
+}
+
+func (controller *Controller) EnterChatroom(c echo.Context) error {
+ enterChatroomRequest := new(requests.EnterChatroomRequest)
+
+ err := c.Bind(enterChatroomRequest)
+ if err != nil {
+ return c.JSON(common.NewBadRequestResponse())
+ }
+
+ err = controller.service.EnterChatroom(*enterChatroomRequest.ToEnterChatroomSpec())
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+
+ return nil
+}
+
+func (controller *Controller) LeaveChatroom(c echo.Context) error {
+ leaveChatroomRequest := new(requests.LeaveChatroomRequest)
+
+ err := c.Bind(leaveChatroomRequest)
+ if err != nil {
+ return c.JSON(common.NewBadRequestResponse())
+ }
+
+ err = controller.service.LeaveChatroom(*leaveChatroomRequest.ToLeaveChatroomSpec())
+ if err != nil {
+ return c.JSON(common.NewErrorBusinessResponse(err))
+ }
+
+ return nil
+}
diff --git a/api/v1/users/requests/enter_chatroom.go b/api/v1/users/requests/enter_chatroom.go
new file mode 100644
index 0000000..eed178f
--- /dev/null
+++ b/api/v1/users/requests/enter_chatroom.go
@@ -0,0 +1,17 @@
+package requests
+
+import "chat-hex/business/users"
+
+type EnterChatroomRequest struct {
+ Email string `json:"email"`
+ Chatroom string `json:"chatroom"`
+}
+
+func (req *EnterChatroomRequest) ToEnterChatroomSpec() *users.EnterChatroomSpec {
+ var enterChatroomSpec users.EnterChatroomSpec
+
+ enterChatroomSpec.Email = req.Email
+ enterChatroomSpec.Chatroom = req.Chatroom
+
+ return &enterChatroomSpec
+}
\ No newline at end of file
diff --git a/api/v1/users/requests/leave_chatroom.go b/api/v1/users/requests/leave_chatroom.go
new file mode 100644
index 0000000..3a90019
--- /dev/null
+++ b/api/v1/users/requests/leave_chatroom.go
@@ -0,0 +1,17 @@
+package requests
+
+import "chat-hex/business/users"
+
+type LeaveChatroomRequest struct {
+ Email string `json:"email"`
+ Chatroom string `json:"chatroom"`
+}
+
+func (req *LeaveChatroomRequest) ToLeaveChatroomSpec() *users.LeaveChatroomSpec {
+ var leaveChatroomSpec users.LeaveChatroomSpec
+
+ leaveChatroomSpec.Email = req.Email
+ leaveChatroomSpec.Chatroom = req.Chatroom
+
+ return &leaveChatroomSpec
+}
\ No newline at end of file
diff --git a/app/main.go b/app/main.go
index 2ac3763..e169cd2 100644
--- a/app/main.go
+++ b/app/main.go
@@ -1,21 +1,31 @@
package main
import (
+ "chat-hex/config"
+ "chat-hex/modules/mongodb"
"context"
"fmt"
- "go-hexagonal/config"
- "go-hexagonal/modules/mongodb"
- "go-hexagonal/api"
- userController "go-hexagonal/api/v1/user"
- userService "go-hexagonal/business/user"
- userRepository "go-hexagonal/modules/user"
+ "chat-hex/api"
+ authController "chat-hex/api/v1/auth"
+ chatroomsController "chat-hex/api/v1/chatrooms"
+ messagesController "chat-hex/api/v1/messages"
+ usersController "chat-hex/api/v1/users"
+ authService "chat-hex/business/auth"
+ chatroomsService "chat-hex/business/chatrooms"
+ commandsService "chat-hex/business/commands"
+ messagesService "chat-hex/business/messages"
+ usersService "chat-hex/business/users"
+ chatroomsRepository "chat-hex/modules/chatrooms"
+ messagesRepository "chat-hex/modules/messages"
+ usersRepository "chat-hex/modules/users"
"os"
"os/signal"
"time"
echo "github.com/labstack/echo/v4"
+ "github.com/labstack/echo/v4/middleware"
"github.com/labstack/gommon/log"
"go.mongodb.org/mongo-driver/mongo"
)
@@ -60,20 +70,37 @@ func main() {
//initialize database connection based on given config
dbConnection := newDatabaseConnection(config)
- //initiate item repository
- userRepo := userRepository.NewMongoDBRepository(dbConnection)
-
- //initiate item service
- userService := userService.NewService(userRepo)
-
- //initiate item controller
- userController := userController.NewController(userService)
-
//create echo http
e := echo.New()
-
- //register API path and handler
- api.RegisterPath(e, userController)
+ e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
+ AllowOrigins: []string{"*"},
+ AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept},
+ }))
+
+ //initiate chatrooms
+ chatroomsRepo := chatroomsRepository.NewMongoDBRepository(dbConnection)
+ chatroomsService := chatroomsService.NewService(chatroomsRepo)
+ chatroomsController := chatroomsController.NewController(chatroomsService)
+
+ //initiate users
+ usersRepo := usersRepository.NewMongoDBRepository(dbConnection)
+ usersService := usersService.NewService(usersRepo, chatroomsService)
+ usersController := usersController.NewController(usersService)
+
+ //initiate auth
+ authService := authService.NewService()
+ authController := authController.NewController(authService, usersService)
+
+ //initiate commands
+ commandsService := commandsService.NewService()
+
+ //initiate messages
+ messagesRepo := messagesRepository.NewMongoDBRepository(dbConnection)
+ messagesService := messagesService.NewService(messagesRepo)
+ messagesController := messagesController.NewController(messagesService, commandsService)
+
+ //register paths
+ api.RegisterPaths(e, authController, usersController, chatroomsController, messagesController)
// run server
go func() {
diff --git a/business/auth/interface.go b/business/auth/interface.go
new file mode 100644
index 0000000..38b2a94
--- /dev/null
+++ b/business/auth/interface.go
@@ -0,0 +1,6 @@
+package auth
+
+type Service interface {
+ GenerateJWT(generateTokenSpec GenerateTokenSpec) (string, error)
+ ValidateToken(signedToken string) error
+}
\ No newline at end of file
diff --git a/business/auth/service.go b/business/auth/service.go
new file mode 100644
index 0000000..4753346
--- /dev/null
+++ b/business/auth/service.go
@@ -0,0 +1,63 @@
+package auth
+
+import (
+ "errors"
+ "time"
+
+ "github.com/dgrijalva/jwt-go"
+)
+
+type GenerateTokenSpec struct {
+ Email string `validate:"required"`
+ Password string `validate:"required"`
+}
+
+var jwtKey = []byte("chat-hex-key")
+
+type JWTClaim struct {
+ Email string `json:"email"`
+ jwt.StandardClaims
+}
+
+type service struct{}
+
+func NewService() Service {
+ return &service{}
+}
+
+func (s *service) GenerateJWT(generateTokenSpec GenerateTokenSpec) (string, error) {
+ expirationTime := time.Now().Add(1 * time.Hour)
+ claims := &JWTClaim{
+ Email: generateTokenSpec.Email,
+ StandardClaims: jwt.StandardClaims{
+ ExpiresAt: expirationTime.Unix(),
+ },
+ }
+
+ token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
+ return token.SignedString(jwtKey)
+}
+
+func (s *service) ValidateToken(signedToken string) error {
+ token, err := jwt.ParseWithClaims(
+ signedToken,
+ &JWTClaim{},
+ func(token *jwt.Token) (interface{}, error) {
+ return []byte(jwtKey), nil
+ },
+ )
+ if err != nil {
+ return err
+ }
+
+ claims, ok := token.Claims.(*JWTClaim)
+ if !ok {
+ return errors.New("couldn't parse claims")
+ }
+
+ if claims.ExpiresAt < time.Now().Local().Unix() {
+ return errors.New("token expired")
+ }
+
+ return nil
+}
\ No newline at end of file
diff --git a/business/chatrooms/chatroom.go b/business/chatrooms/chatroom.go
new file mode 100644
index 0000000..1117068
--- /dev/null
+++ b/business/chatrooms/chatroom.go
@@ -0,0 +1,22 @@
+package chatrooms
+
+type Chatroom struct {
+ Id string
+ Name string
+ Desc string
+ Code string
+}
+
+func NewChatroom(
+ id string,
+ name string,
+ desc string,
+ code string) Chatroom {
+
+ return Chatroom{
+ Id: id,
+ Name: name,
+ Desc: desc,
+ Code: code,
+ }
+}
\ No newline at end of file
diff --git a/business/chatrooms/interface.go b/business/chatrooms/interface.go
new file mode 100644
index 0000000..3b31dc9
--- /dev/null
+++ b/business/chatrooms/interface.go
@@ -0,0 +1,11 @@
+package chatrooms
+
+type Service interface {
+ FindChatroomByCode(code string) (*Chatroom, error)
+ GetChatrooms() ([]Chatroom, error)
+}
+
+type Repository interface {
+ FindChatroomByCode(code string) (*Chatroom, error)
+ GetChatrooms() ([]Chatroom, error)
+}
\ No newline at end of file
diff --git a/business/chatrooms/service.go b/business/chatrooms/service.go
new file mode 100644
index 0000000..6c2c13c
--- /dev/null
+++ b/business/chatrooms/service.go
@@ -0,0 +1,27 @@
+package chatrooms
+
+type service struct {
+ repository Repository
+}
+
+func NewService(repository Repository) Service {
+ return &service{repository}
+}
+
+func (s *service) FindChatroomByCode(code string) (*Chatroom, error) {
+ chatroom, err := s.repository.FindChatroomByCode(code)
+ if err != nil {
+ return nil, err
+ }
+
+ return chatroom, nil
+}
+
+func (s *service) GetChatrooms() ([]Chatroom, error) {
+ chatrooms, err := s.repository.GetChatrooms()
+ if err != nil {
+ return nil, err
+ }
+
+ return chatrooms, nil
+}
\ No newline at end of file
diff --git a/business/commands/command.go b/business/commands/command.go
new file mode 100644
index 0000000..6940dd4
--- /dev/null
+++ b/business/commands/command.go
@@ -0,0 +1,5 @@
+package commands
+
+const (
+ CommandStock = "/stock"
+)
\ No newline at end of file
diff --git a/business/commands/interface.go b/business/commands/interface.go
new file mode 100644
index 0000000..26e1609
--- /dev/null
+++ b/business/commands/interface.go
@@ -0,0 +1,5 @@
+package commands
+
+type Service interface {
+ ProcessCommand(commandSpec CommandSpec) error
+}
\ No newline at end of file
diff --git a/business/commands/service.go b/business/commands/service.go
new file mode 100644
index 0000000..b64a7ed
--- /dev/null
+++ b/business/commands/service.go
@@ -0,0 +1,45 @@
+package commands
+
+import (
+ "chat-hex/business"
+ "fmt"
+ "strings"
+)
+
+type CommandSpec struct {
+ Content string `validate:"required"`
+ Sender string `validate:"required"`
+ Chatroom string `validate:"required"`
+}
+
+type service struct{}
+
+func NewService() Service {
+ return &service{}
+}
+
+func (s *service) ProcessCommand(commandSpec CommandSpec) error {
+ pieces := strings.Split(commandSpec.Content, "=")
+
+ possibleCommand := strings.ToLower(pieces[0])
+ if possibleCommand == CommandStock {
+ stockCode := strings.ToLower(pieces[1])
+ if len(stockCode) <= 0 {
+ return business.ErrInvalidCommand
+ }
+
+ err := s.AsyncStockCommand(stockCode, commandSpec.Chatroom)
+ if err != nil {
+ return business.ErrInvalidCommand
+ }
+
+ return nil
+ }
+
+ return business.ErrInvalidCommand
+}
+
+func (s *service) AsyncStockCommand(stockCode string, chatroom string) error {
+ fmt.Println("STOCK CODE IS", stockCode, "CHATROOM IS", chatroom)
+ return nil
+}
\ No newline at end of file
diff --git a/business/error.go b/business/error.go
index 4261b18..5c5733e 100644
--- a/business/error.go
+++ b/business/error.go
@@ -4,14 +4,17 @@ import "errors"
var (
//ErrInternalServerError Error caused by system error
- ErrInternalServerError = errors.New("Internal Server Error")
+ ErrInternalServerError = errors.New("internal Server Error")
//ErrHasBeenModified Error when update item that has been modified
- ErrHasBeenModified = errors.New("Data has been modified")
+ ErrHasBeenModified = errors.New("data has been modified")
//ErrNotFound Error when item is not found
- ErrNotFound = errors.New("Data was not found")
+ ErrNotFound = errors.New("data was not found")
//ErrInvalidSpec Error when data given is not valid on update or insert
- ErrInvalidSpec = errors.New("Given spec is not valid")
+ ErrInvalidSpec = errors.New("given spec is not valid")
+
+ //ErrInvalidCommand Error when the message is formatted like a command but it's not a valid one
+ ErrInvalidCommand = errors.New("this is not a valid command")
)
diff --git a/business/messages/interface.go b/business/messages/interface.go
new file mode 100644
index 0000000..aae7db1
--- /dev/null
+++ b/business/messages/interface.go
@@ -0,0 +1,12 @@
+package messages
+
+type Service interface {
+ InsertMessage(insertMessageSpec InsertMessageSpec) error
+ GetMessagesByChatroom(chatroom string) ([]Message, error)
+ MessageHasCommandStructure(insertMessageSpec InsertMessageSpec) bool
+}
+
+type Repository interface {
+ InsertMessage(message Message) error
+ GetMessagesByChatroom(chatroom string) ([]Message, error)
+}
\ No newline at end of file
diff --git a/business/messages/message.go b/business/messages/message.go
new file mode 100644
index 0000000..a0957e5
--- /dev/null
+++ b/business/messages/message.go
@@ -0,0 +1,27 @@
+package messages
+
+import "time"
+
+type Message struct {
+ Id string
+ Content string
+ Sender string
+ Timestamp time.Time
+ ChatRoom string
+}
+
+func NewMessage(
+ id string,
+ content string,
+ sender string,
+ timestamp time.Time,
+ chatroom string) Message {
+
+ return Message{
+ Id: id,
+ Content: content,
+ Sender: sender,
+ Timestamp: timestamp,
+ ChatRoom: chatroom,
+ }
+}
\ No newline at end of file
diff --git a/business/messages/service.go b/business/messages/service.go
new file mode 100644
index 0000000..e1b4ceb
--- /dev/null
+++ b/business/messages/service.go
@@ -0,0 +1,64 @@
+package messages
+
+import (
+ "chat-hex/business"
+ primitiveIDGenerator "chat-hex/util/primitiveIDGenerator"
+ "chat-hex/util/validator"
+ "time"
+)
+
+type InsertMessageSpec struct {
+ Content string `validate:"required"`
+ Sender string `validate:"required"`
+ Chatroom string `validate:"required"`
+}
+
+type service struct {
+ repository Repository
+}
+
+func NewService(repository Repository) Service {
+ return &service{repository}
+}
+
+func (s *service) InsertMessage(insertMessageSpec InsertMessageSpec) error {
+ err := validator.GetValidator().Struct(insertMessageSpec)
+ if err != nil {
+ return business.ErrInvalidSpec
+ }
+
+ id := primitiveIDGenerator.GenerateID()
+ message := NewMessage(
+ id,
+ insertMessageSpec.Content,
+ insertMessageSpec.Sender,
+ time.Now(),
+ insertMessageSpec.Chatroom,
+ )
+
+ err = s.repository.InsertMessage(message)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *service) GetMessagesByChatroom(chatroom string) ([]Message, error) {
+ messages, err := s.repository.GetMessagesByChatroom(chatroom)
+ if err != nil {
+ return []Message{}, err
+ }
+
+ return messages, err
+}
+
+func (s *service) MessageHasCommandStructure(insertMessageSpec InsertMessageSpec) bool {
+ err := validator.GetValidator().Struct(insertMessageSpec)
+ if err != nil {
+ return false
+ }
+
+ firstCharacter:= insertMessageSpec.Content[0:1]
+ return firstCharacter == "/"
+}
\ No newline at end of file
diff --git a/business/user/mocks/Repository.go b/business/user/mocks/Repository.go
index 700f668..c91c08f 100644
--- a/business/user/mocks/Repository.go
+++ b/business/user/mocks/Repository.go
@@ -3,7 +3,7 @@
package mocks
import (
- user "go-hexagonal/business/user"
+ user "chat-hex/business/user"
mock "github.com/stretchr/testify/mock"
)
diff --git a/business/user/mocks/Service.go b/business/user/mocks/Service.go
index a5a656a..2e70a36 100644
--- a/business/user/mocks/Service.go
+++ b/business/user/mocks/Service.go
@@ -3,7 +3,7 @@
package mocks
import (
- user "go-hexagonal/business/user"
+ user "chat-hex/business/user"
mock "github.com/stretchr/testify/mock"
)
diff --git a/business/user/service.go b/business/user/service.go
index 1d58422..a54ca7a 100644
--- a/business/user/service.go
+++ b/business/user/service.go
@@ -1,9 +1,9 @@
package user
import (
- "go-hexagonal/business"
- "go-hexagonal/util/primiviteIDGenerator"
- "go-hexagonal/util/validator"
+ "chat-hex/business"
+ "chat-hex/util/primitiveIDGenerator"
+ "chat-hex/util/validator"
"time"
)
@@ -49,7 +49,7 @@ func (s *service) InsertUser(insertUserSpec InsertUserSpec, createdBy string) er
return business.ErrInvalidSpec
}
- id := primiviteIDGenerator.GenerateID()
+ id := primitiveIDGenerator.GenerateID()
user := NewUser(
id,
insertUserSpec.Name,
diff --git a/business/user/service_test.go b/business/user/service_test.go
index 4b4fdd4..05cd3bc 100644
--- a/business/user/service_test.go
+++ b/business/user/service_test.go
@@ -1,9 +1,9 @@
package user_test
import (
- "go-hexagonal/business"
- "go-hexagonal/business/user"
- userMock "go-hexagonal/business/user/mocks"
+ "chat-hex/business"
+ "chat-hex/business/user"
+ userMock "chat-hex/business/user/mocks"
"os"
"testing"
diff --git a/business/users/interface.go b/business/users/interface.go
new file mode 100644
index 0000000..5650e86
--- /dev/null
+++ b/business/users/interface.go
@@ -0,0 +1,15 @@
+package users
+
+type Service interface {
+ EnterChatroom(enterChatroomSpec EnterChatroomSpec) error
+ LeaveChatroom(leaveChatroomSpec LeaveChatroomSpec) error
+ HashPassword(password string) (*string, error)
+ FindUserByEmail(email string) (*User, error)
+ CheckPassword(hashedPassword string, clearPassword string) error
+}
+
+type Repository interface {
+ FindUserByEmail(email string) (*User, error)
+ EnterChatroom(email string, chatroom string) error
+ LeaveChatroom(email string) error
+}
\ No newline at end of file
diff --git a/business/users/service.go b/business/users/service.go
new file mode 100644
index 0000000..2385355
--- /dev/null
+++ b/business/users/service.go
@@ -0,0 +1,90 @@
+package users
+
+import (
+ "chat-hex/business"
+ "chat-hex/business/chatrooms"
+ "chat-hex/util/validator"
+
+ "golang.org/x/crypto/bcrypt"
+)
+
+type EnterChatroomSpec struct {
+ Email string `validate:"required"`
+ Chatroom string `validate:"required"`
+}
+
+type LeaveChatroomSpec struct {
+ Email string `validate:"required"`
+ Chatroom string `validate:"required"`
+}
+
+type service struct {
+ repository Repository
+ chatroomsService chatrooms.Service
+}
+
+func NewService(repository Repository, chatroomsService chatrooms.Service) Service {
+ return &service{repository, chatroomsService}
+}
+
+func (s *service) EnterChatroom(enterChatroomSpec EnterChatroomSpec) error {
+ err := validator.GetValidator().Struct(enterChatroomSpec)
+ if err != nil {
+ return business.ErrInvalidSpec
+ }
+
+ _, err = s.chatroomsService.FindChatroomByCode(enterChatroomSpec.Chatroom)
+ if err != nil {
+ return business.ErrInvalidSpec
+ }
+
+ err = s.repository.EnterChatroom(enterChatroomSpec.Email, enterChatroomSpec.Chatroom)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *service) LeaveChatroom(leaveChatroomSpec LeaveChatroomSpec) error {
+ err := validator.GetValidator().Struct(leaveChatroomSpec)
+ if err != nil {
+ return business.ErrInvalidSpec
+ }
+
+ err = s.repository.LeaveChatroom(leaveChatroomSpec.Email)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *service) HashPassword(password string) (*string, error) {
+ bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
+ if err != nil {
+ return nil, err
+ }
+
+ preResult := string(bytes)
+ result := &preResult
+ return result, nil
+}
+
+func (s *service) FindUserByEmail(email string) (*User, error){
+ user, err := s.repository.FindUserByEmail(email)
+ if err != nil {
+ return nil, err
+ }
+
+ return user, nil
+}
+
+func (s *service) CheckPassword(passwordToCheck string, clearPassword string) error {
+ err := bcrypt.CompareHashAndPassword([]byte(passwordToCheck), []byte(clearPassword))
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
\ No newline at end of file
diff --git a/business/users/user.go b/business/users/user.go
new file mode 100644
index 0000000..76827fd
--- /dev/null
+++ b/business/users/user.go
@@ -0,0 +1,25 @@
+package users
+
+type User struct {
+ Id string
+ Email string
+ Password string
+ Name string
+ CurrentRoom string
+}
+
+func NewUser(
+ id string,
+ email string,
+ password string,
+ name string,
+ currentRoom string) User {
+
+ return User{
+ Id: id,
+ Email: email,
+ Password: password,
+ Name: name,
+ CurrentRoom: currentRoom,
+ }
+}
\ No newline at end of file
diff --git a/config/.env b/config/.env
index dd9ea3c..b3d7e03 100644
--- a/config/.env
+++ b/config/.env
@@ -1,9 +1,9 @@
-GOHEXAGONAL_APP_PORT=8000
-GOHEXAGONAL_APP_ENVIRONMENT=dev
+APP_PORT=3000
+APP_ENVIRONMENT=dev
-GOHEXAGONAL_DB_DRIVER=mongodb
-GOHEXAGONAL_DB_ADDRESS=localhost
-GOHEXAGONAL_DB_PORT=27017
-GOHEXAGONAL_DB_USERNAME=
-GOHEXAGONAL_DB_PASSWORD=
-GOHEXAGONAL_DB_NAME=transaction
\ No newline at end of file
+DB_DRIVER=mongodb
+DB_ADDRESS=localhost
+DB_PORT=27017
+DB_USERNAME=
+DB_PASSWORD=
+DB_NAME=local
\ No newline at end of file
diff --git a/config/.env_local b/config/.env_local
deleted file mode 100644
index 3525509..0000000
--- a/config/.env_local
+++ /dev/null
@@ -1,9 +0,0 @@
-export GOHEXAGONAL_APP_PORT=8000
-export GOHEXAGONAL_APP_ENVIRONMENT=dev
-
-export GOHEXAGONAL_DB_DRIVER=mongodb
-export GOHEXAGONAL_DB_ADDRESS=localhost
-export GOHEXAGONAL_DB_PORT=27017
-export GOHEXAGONAL_DB_USERNAME=
-export GOHEXAGONAL_DB_PASSWORD=
-export GOHEXAGONAL_DB_NAME=transaction
\ No newline at end of file
diff --git a/config/config.go b/config/config.go
index a8cd69b..85c828b 100644
--- a/config/config.go
+++ b/config/config.go
@@ -2,9 +2,6 @@ package config
import (
"sync"
-
- "github.com/labstack/gommon/log"
- "github.com/spf13/viper"
)
type ConfigIPForwarding struct {
@@ -28,7 +25,7 @@ type AppConfig struct {
var lock = &sync.Mutex{}
var appConfig *AppConfig
-//GetConfig Initiatilize config in singleton way
+//GetConfig Initialize config in singleton way
func GetConfig() *AppConfig {
if appConfig != nil {
return appConfig
@@ -50,32 +47,14 @@ func GetConfig() *AppConfig {
func initConfig() *AppConfig {
var defaultConfig AppConfig
- defaultConfig.AppPort = 8000
+ defaultConfig.AppPort = 3000
defaultConfig.AppEnvironment = ""
defaultConfig.DbDriver = "mongodb"
defaultConfig.DbAddress = "localhost"
defaultConfig.DbPort = 27017
defaultConfig.DbUsername = ""
defaultConfig.DbPassword = ""
- defaultConfig.DbName = "hexagonal"
-
- viper.AutomaticEnv()
- viper.SetEnvPrefix("gohexagonal")
- viper.BindEnv("app_port")
- viper.BindEnv("app_environment")
- viper.BindEnv("db_driver")
- viper.BindEnv("db_address")
- viper.BindEnv("db_port")
- viper.BindEnv("db_username")
- viper.BindEnv("db_password")
- viper.BindEnv("db_name")
-
- var finalConfig AppConfig
- err := viper.Unmarshal(&finalConfig)
- if err != nil {
- log.Info("failed to extract config, will use default value")
- return &defaultConfig
- }
+ defaultConfig.DbName = "local"
- return &finalConfig
+ return &defaultConfig
}
diff --git a/go.mod b/go.mod
index 50331fa..6bd1954 100644
--- a/go.mod
+++ b/go.mod
@@ -1,12 +1,15 @@
-module go-hexagonal
+module chat-hex
go 1.16
require (
- github.com/go-playground/validator/v10 v10.6.1
+ github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
+ github.com/gin-gonic/gin v1.9.1
+ github.com/go-playground/validator/v10 v10.14.0
github.com/labstack/echo/v4 v4.3.0
github.com/labstack/gommon v0.3.0
github.com/spf13/viper v1.8.0
- github.com/stretchr/testify v1.7.0 // indirect
+ github.com/stretchr/testify v1.8.4 // indirect
go.mongodb.org/mongo-driver v1.5.3
+ golang.org/x/crypto v0.9.0 // indirect
)
diff --git a/go.sum b/go.sum
index acc147c..6d93abb 100644
--- a/go.sum
+++ b/go.sum
@@ -47,7 +47,13 @@ github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPI
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
+github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -60,6 +66,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -71,18 +78,31 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
+github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I=
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
+github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
+github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@@ -110,6 +130,8 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -209,6 +231,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@@ -219,6 +243,9 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
+github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@@ -233,6 +260,8 @@ github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
@@ -246,6 +275,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -257,13 +288,19 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
+github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -301,6 +338,9 @@ github.com/spf13/viper v1.8.0/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -308,10 +348,21 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
@@ -330,6 +381,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
@@ -345,6 +397,9 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
+golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -357,6 +412,10 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -392,6 +451,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -429,6 +490,11 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -454,6 +520,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -504,7 +573,19 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -514,9 +595,16 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -573,6 +661,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -680,6 +770,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
+google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -694,6 +786,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -702,5 +796,6 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/middlewares/auth.go b/middlewares/auth.go
new file mode 100644
index 0000000..46fbc4f
--- /dev/null
+++ b/middlewares/auth.go
@@ -0,0 +1,23 @@
+package middlewares
+
+import (
+ "chat-hex/business/auth"
+
+ "github.com/labstack/echo/v4"
+)
+
+func Auth(next, stop echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ tokenString := c.Request().Header.Get("Authorization")
+ if tokenString == "" {
+ return stop(c)
+ }
+
+ err := auth.NewService().ValidateToken(tokenString)
+ if err != nil {
+ return stop(c)
+ }
+
+ return next(c)
+ }
+}
\ No newline at end of file
diff --git a/modules/chatrooms/mongo_repo.go b/modules/chatrooms/mongo_repo.go
new file mode 100644
index 0000000..2fddc24
--- /dev/null
+++ b/modules/chatrooms/mongo_repo.go
@@ -0,0 +1,93 @@
+package mongodb
+
+import (
+ "chat-hex/business"
+ "chat-hex/business/chatrooms"
+ "context"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+)
+
+type MongoDBRepository struct {
+ collection *mongo.Collection
+}
+
+type collection struct {
+ Id string `bson:"id"`
+ Name string `bson:"name"`
+ Desc string `bson:"desc"`
+ Code string `bson:"code"`
+}
+
+func newCollection(chatroom chatrooms.Chatroom) *collection {
+ return &collection{
+ chatroom.Id,
+ chatroom.Name,
+ chatroom.Desc,
+ chatroom.Code,
+ }
+}
+
+func (col *collection) ToChatroom() chatrooms.Chatroom {
+ var chatroom chatrooms.Chatroom
+
+ chatroom.Id = col.Id
+ chatroom.Name = col.Name
+ chatroom.Desc = col.Desc
+ chatroom.Code = col.Code
+
+ return chatroom
+}
+
+func NewMongoDBRepository(db *mongo.Database) *MongoDBRepository {
+ return &MongoDBRepository{
+ db.Collection("chatrooms"),
+ }
+}
+
+func (repo *MongoDBRepository) FindChatroomByCode(code string) (*chatrooms.Chatroom, error) {
+ var col collection
+
+ filter := bson.M{"code": code}
+
+ err := repo.collection.FindOne(context.TODO(), filter).Decode(&col)
+ if err != nil {
+ if err == mongo.ErrNoDocuments {
+ return nil, business.ErrNotFound
+ }
+
+ return nil, err
+ }
+
+ chatroom := col.ToChatroom()
+
+ return &chatroom, nil
+}
+
+func (repo *MongoDBRepository) GetChatrooms() ([]chatrooms.Chatroom, error) {
+ var chatrooms []chatrooms.Chatroom
+
+ filter := bson.M{}
+
+ cursor, err := repo.collection.Find(context.Background(), filter)
+ if err != nil {
+ return chatrooms, err
+ }
+
+ defer cursor.Close(context.Background())
+
+ for cursor.Next(context.TODO()) {
+ var col collection
+
+ err := cursor.Decode(&col)
+ if err != nil {
+ return chatrooms, err
+ }
+
+ chatroom := col.ToChatroom()
+ chatrooms = append(chatrooms, chatroom)
+ }
+
+ return chatrooms, nil
+}
\ No newline at end of file
diff --git a/modules/messages/mongo_repo.go b/modules/messages/mongo_repo.go
new file mode 100644
index 0000000..3cff70e
--- /dev/null
+++ b/modules/messages/mongo_repo.go
@@ -0,0 +1,93 @@
+package mongodb
+
+import (
+ "chat-hex/business/messages"
+ "context"
+ "time"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+)
+
+type MongoDBRepository struct {
+ collection *mongo.Collection
+}
+
+type collection struct {
+ Id string `bson:"_id"`
+ Content string `bson:"content"`
+ Sender string `bson:"sender"`
+ Timestamp time.Time `bson:"timestamp"`
+ ChatRoom string `bson:"chatroom"`
+}
+
+func newCollection(message messages.Message) *collection {
+ return &collection{
+ message.Id,
+ message.Content,
+ message.Sender,
+ message.Timestamp,
+ message.ChatRoom,
+ }
+}
+
+func (col *collection) ToMessage() messages.Message {
+ var message messages.Message
+
+ message.Id = col.Id
+ message.Content = col.Content
+ message.Sender = col.Sender
+ message.Timestamp = col.Timestamp
+ message.ChatRoom = col.ChatRoom
+
+ return message
+}
+
+func NewMongoDBRepository(db *mongo.Database) *MongoDBRepository {
+ return &MongoDBRepository{
+ db.Collection("messages"),
+ }
+}
+
+func (repo *MongoDBRepository) InsertMessage(message messages.Message) error {
+ col := newCollection(message)
+
+ _, err := repo.collection.InsertOne(context.Background(), col)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (repo *MongoDBRepository) GetMessagesByChatroom(chatroom string) ([]messages.Message, error) {
+ var messages []messages.Message
+
+ filter := bson.M{"chatroom": chatroom}
+
+ option := options.Find()
+ option.SetSort(bson.D{{Key: "timestamp", Value: -1}})
+ option.SetLimit(50)
+
+ cursor, err := repo.collection.Find(context.Background(), filter, option)
+ if err != nil {
+ return messages, err
+ }
+
+ defer cursor.Close(context.Background())
+
+ for cursor.Next(context.TODO()) {
+ var col collection
+
+ err := cursor.Decode(&col)
+ if err != nil {
+ return messages, err
+ }
+
+ message := col.ToMessage()
+ messages = append(messages, message)
+ }
+
+ return messages, nil
+}
\ No newline at end of file
diff --git a/modules/user/mongo_repo.go b/modules/user/mongo_repo.go
index 70212ab..9f02888 100644
--- a/modules/user/mongo_repo.go
+++ b/modules/user/mongo_repo.go
@@ -1,9 +1,9 @@
package item
import (
+ "chat-hex/business"
+ "chat-hex/business/user"
"context"
- "go-hexagonal/business"
- "go-hexagonal/business/user"
"time"
"go.mongodb.org/mongo-driver/bson"
@@ -63,7 +63,7 @@ func (col *collection) ToUser() user.User {
//NewMongoDBRepository Generate mongo DB user repository
func NewMongoDBRepository(db *mongo.Database) *MongoDBRepository {
return &MongoDBRepository{
- db.Collection("user"),
+ db.Collection("users"),
}
}
@@ -94,12 +94,12 @@ func (repo *MongoDBRepository) FindAllUserWithPagination(skip int, rowPerPage in
var users []user.User
- rowPageWithAddtion := rowPerPage + 1
+ rowPageWithAddition := rowPerPage + 1
option := options.Find()
option.SetSort(bson.D{{Key: "_id", Value: 1}})
option.SetSkip(int64(skip))
- option.SetLimit(int64(rowPageWithAddtion))
+ option.SetLimit(int64(rowPageWithAddition))
cursor, err := repo.collection.Find(context.Background(), bson.M{}, option)
if err != nil {
diff --git a/modules/users/mongo_repo.go b/modules/users/mongo_repo.go
new file mode 100644
index 0000000..6e25771
--- /dev/null
+++ b/modules/users/mongo_repo.go
@@ -0,0 +1,94 @@
+package mongodb
+
+import (
+ "chat-hex/business"
+ "chat-hex/business/users"
+ "context"
+
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo"
+)
+
+type MongoDBRepository struct {
+ collection *mongo.Collection
+}
+
+type collection struct {
+ Id string `bson:"id"`
+ Email string `bson:"email"`
+ Password string `bson:"password"`
+ Name string `bson:"name"`
+ CurrentRoom string `bson:"currentRoom"`
+}
+
+func newCollection(user users.User) *collection {
+ return &collection{
+ user.Id,
+ user.Email,
+ user.Password,
+ user.Name,
+ user.CurrentRoom,
+ }
+}
+
+func (col *collection) ToUser() users.User {
+ var user users.User
+
+ user.Id = col.Id
+ user.Email = col.Email
+ user.Password = col.Password
+ user.Name = col.Name
+ user.CurrentRoom = col.CurrentRoom
+
+ return user
+}
+
+func NewMongoDBRepository(db *mongo.Database) *MongoDBRepository {
+ return &MongoDBRepository{
+ db.Collection("users"),
+ }
+}
+
+func (repo *MongoDBRepository) FindUserByEmail(email string) (*users.User, error) {
+ var col collection
+
+ filter := bson.M{"email": email}
+
+ if err := repo.collection.FindOne(context.TODO(), filter).Decode(&col); err != nil {
+ if err == mongo.ErrNoDocuments {
+ return nil, business.ErrNotFound
+ }
+
+ return nil, err
+ }
+
+ user := col.ToUser()
+
+ return &user, nil
+}
+
+func (repo *MongoDBRepository) EnterChatroom(email string, chatroom string) error {
+ filter := bson.M{"email": email}
+
+ update := bson.M{"$set": bson.M{"currentRoom": chatroom}}
+
+ _, err := repo.collection.UpdateOne(context.Background(), filter, update)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (repo *MongoDBRepository) LeaveChatroom(email string) error {
+ filter := bson.M{"email": email}
+
+ update := bson.M{"$set": bson.M{"currentRoom": nil}}
+
+ _, err := repo.collection.UpdateOne(context.Background(), filter, update)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
\ No newline at end of file
diff --git a/util/primiviteIDGenerator/primiviteIDGenerator.go b/util/primitiveIDGenerator/primitiveIDGenerator.go
similarity index 53%
rename from util/primiviteIDGenerator/primiviteIDGenerator.go
rename to util/primitiveIDGenerator/primitiveIDGenerator.go
index 7054f0c..c844420 100644
--- a/util/primiviteIDGenerator/primiviteIDGenerator.go
+++ b/util/primitiveIDGenerator/primitiveIDGenerator.go
@@ -1,8 +1,8 @@
-package primiviteIDGenerator
+package primitiveIDGenerator
import "go.mongodb.org/mongo-driver/bson/primitive"
-//GenerateID Generate 12 byte UUID. It will return 24 hexadimal characters
+//GenerateID Generate 12 byte UUID. It will return 24 hexadecimal characters
func GenerateID() string {
return primitive.NewObjectID().Hex()
}