From be319ce59b75f0d3e46d4707191155c5653cc536 Mon Sep 17 00:00:00 2001 From: fernandodev133 <146200770+fernandodev133@users.noreply.github.com> Date: Tue, 17 Oct 2023 16:43:14 -0300 Subject: [PATCH 01/52] =?UTF-8?q?=E2=9C=A8=20Add=20the=20submit=20transact?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/config/config.go | 4 + backend/internal/app/app.go | 4 +- backend/internal/controller/http/v1/router.go | 5 +- .../internal/controller/http/v1/soroban.go | 80 +++++++++++++++++++ backend/internal/controller/http/v1/utils.go | 8 +- .../internal/controller/http/v1/utils_test.go | 2 +- backend/internal/entity/channel.go | 8 +- backend/internal/entity/message.go | 11 +++ backend/internal/entity/transactions.go | 2 + backend/main.go | 12 ++- backend/pkg/kafka/producer.go | 5 +- 11 files changed, 126 insertions(+), 15 deletions(-) create mode 100644 backend/internal/controller/http/v1/soroban.go diff --git a/backend/config/config.go b/backend/config/config.go index 4af6e317..9e3d1175 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -30,6 +30,10 @@ type ( ConsumerTopics []string `env:"KAFKA_HORIZON_CONSUMER_TOPICS"` ProducerTopic string `env:"KAFKA_HORIZON_PRODUCER_TOPIC"` } + SubmitTransactionCfg struct { + ConsumerTopics []string `env:"KAFKA_ENVELOPE_CONSUMER_TOPICS"` + ProducerTopic string `env:"KAFKA_SUBMIT_TRANSACTION_PRODUCER_TOPIC"` + } } PGConfig struct { diff --git a/backend/internal/app/app.go b/backend/internal/app/app.go index 9dd9d26b..f8a300e1 100644 --- a/backend/internal/app/app.go +++ b/backend/internal/app/app.go @@ -20,7 +20,7 @@ import ( ) // Run creates objects via constructors. -func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv entity.ProducerInterface) { +func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv, pSub entity.ProducerInterface) { // Use cases authUc := usecase.NewAuthUseCase( repo.New(pg), cfg.JWT.SecretKey, @@ -58,7 +58,7 @@ func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv entity.Produ // HTTP Server handler := gin.Default() - v1.NewRouter(handler, pKp, pHor, pEnv, *authUc, *userUc, *walletUc, *assetUc, *roleUc, *rolePermissionUc, *vaultCategoryUc, *vaultUc, *contractUc, *logUc, cfg.HTTP) + v1.NewRouter(handler, pKp, pHor, pEnv, pSub, *authUc, *userUc, *walletUc, *assetUc, *roleUc, *rolePermissionUc, *vaultCategoryUc, *vaultUc, *contractUc, *logUc, cfg.HTTP) httpServer := httpserver.New(handler, httpserver.Port(cfg.HTTP.Port), httpserver.ReadTimeout(60*time.Second), diff --git a/backend/internal/controller/http/v1/router.go b/backend/internal/controller/http/v1/router.go index d70458a5..884d07c7 100644 --- a/backend/internal/controller/http/v1/router.go +++ b/backend/internal/controller/http/v1/router.go @@ -35,7 +35,7 @@ func CORSMiddleware(cfg config.HTTP) gin.HandlerFunc { // @BasePath /v1 func NewRouter( handler *gin.Engine, - pKp, pHor, pEnv entity.ProducerInterface, + pKp, pHor, pEnv, pSub entity.ProducerInterface, authUseCase usecase.AuthUseCase, userUseCase usecase.UserUseCase, walletUseCase usecase.WalletUseCase, @@ -49,7 +49,7 @@ func NewRouter( cfg config.HTTP, ) { // Messenger - messengerController := newHTTPControllerMessenger(pKp, pHor, pEnv) + messengerController := newHTTPControllerMessenger(pKp, pHor, pEnv, pSub) // Options Gin handler.Use(gin.Logger()) handler.Use(gin.Recovery()) @@ -71,5 +71,6 @@ func NewRouter( newVaultRoutes(groupV1, messengerController, authUseCase, vaultUc, vaultCategoryUc, walletUseCase, assetUseCase) newContractRoutes(groupV1, messengerController, authUseCase, contractUc, vaultUc, assetUseCase) newLogTransactionsRoutes(groupV1, walletUseCase, assetUseCase, messengerController, logUc, authUseCase) + newSorobanRoutes(groupV1, walletUseCase, messengerController, authUseCase) } } diff --git a/backend/internal/controller/http/v1/soroban.go b/backend/internal/controller/http/v1/soroban.go new file mode 100644 index 00000000..205fc274 --- /dev/null +++ b/backend/internal/controller/http/v1/soroban.go @@ -0,0 +1,80 @@ +package v1 + +import ( + "fmt" + "net/http" + + "github.com/CheesecakeLabs/token-factory-v2/backend/internal/entity" + "github.com/CheesecakeLabs/token-factory-v2/backend/internal/usecase" + "github.com/gin-gonic/gin" +) + +type sorobanRoutes struct { + w usecase.WalletUseCase + m HTTPControllerMessenger + a usecase.AuthUseCase +} + +func newSorobanRoutes(handler *gin.RouterGroup, w usecase.WalletUseCase, m HTTPControllerMessenger, a usecase.AuthUseCase) { + r := &sorobanRoutes{w, m, a} + + h := handler.Group("/soroban-transactions") + h.Use(Auth(r.a.ValidateToken())) + { + h.POST("/sign", r.signTransaction) + h.POST("/submit", r.submitTransaction) + } +} + +type SignedTransactionRequest struct { + Envelope string `json:"envelope" binding:"required" example:"KJDSKD..."` + WalletId int `json:"wallet_id" binding:"required" example:"1"` +} + +type SubmitTransactionRequest struct { + Envelope string `json:"envelope" binding:"required" example:"KJDSKD..."` +} + +// @Summary Signed Transaction +// @Description Signed a XDR transaction +// @Tags Soroban +// @Accept json +// @Produce json +// @Param request body SignedTransactionRequest true "Signed a XDR transaction" +// @Success 200 {object} response +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /soroban-transactions/sign [post] +func (r *sorobanRoutes) signTransaction(c *gin.Context) { + var request SignedTransactionRequest + if err := c.ShouldBindJSON(&request); err != nil { + errorResponse(c, http.StatusBadRequest, "invalid request", err) + return + } +} + +// @Summary Submit Transaction +// @Description Submit a XDR transaction +// @Tags Soroban +// @Accept json +// @Produce json +// @Param request body SubmitTransactionRequest true "Submit a XDR transaction" +// @Success 200 {object} response +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /soroban-transactions/submit [post] +func (r *sorobanRoutes) submitTransaction(c *gin.Context) { + var request SubmitTransactionRequest + if err := c.ShouldBindJSON(&request); err != nil { + errorResponse(c, http.StatusBadRequest, "invalid request", err) + return + } + res, err := r.m.SendMessage(entity.SubmitTransactionChannel, entity.SubmitRequest{Envelope: request.Envelope}) + if err != nil { + fmt.Println(err) + errorResponse(c, http.StatusInternalServerError, "messaging problems", err) + return + } + + c.JSON(http.StatusOK, res) +} diff --git a/backend/internal/controller/http/v1/utils.go b/backend/internal/controller/http/v1/utils.go index 80ae2b17..acc8bbe3 100644 --- a/backend/internal/controller/http/v1/utils.go +++ b/backend/internal/controller/http/v1/utils.go @@ -15,10 +15,11 @@ type HTTPControllerMessenger struct { pKp entity.ProducerInterface pHor entity.ProducerInterface pEnv entity.ProducerInterface + pSub entity.ProducerInterface } -func newHTTPControllerMessenger(pKp, pHor, pEnv entity.ProducerInterface) HTTPControllerMessenger { - return HTTPControllerMessenger{pKp, pHor, pEnv} +func newHTTPControllerMessenger(pKp, pHor, pEnv, pSub entity.ProducerInterface) HTTPControllerMessenger { + return HTTPControllerMessenger{pKp, pHor, pEnv, pSub} } func (m *HTTPControllerMessenger) SendMessage(chanName string, value interface{}) (*entity.NotifyData, error) { @@ -26,7 +27,6 @@ func (m *HTTPControllerMessenger) SendMessage(chanName string, value interface{} if err != nil { return &entity.NotifyData{}, fmt.Errorf("sendMessage - generateHash: %v", err) } - channel := make(chan interface{}) notify.Start(msgKey, channel) @@ -76,6 +76,8 @@ func (m *HTTPControllerMessenger) produce(chanName string, msgKey string, value err = m.pHor.Produce(msgKey, value) case entity.EnvelopeChannel: err = m.pEnv.Produce(msgKey, value) + case entity.SubmitTransactionChannel: + err = m.pSub.Produce(msgKey, value) default: err = fmt.Errorf("invalid channel name") } diff --git a/backend/internal/controller/http/v1/utils_test.go b/backend/internal/controller/http/v1/utils_test.go index b67afe0d..c0d53bf6 100644 --- a/backend/internal/controller/http/v1/utils_test.go +++ b/backend/internal/controller/http/v1/utils_test.go @@ -26,7 +26,7 @@ func (p *mockProducer) Produce(key string, value interface{}) error { func TestSendMessage(t *testing.T) { mockProducer := newMockProducer() - messenger := newHTTPControllerMessenger(mockProducer, mockProducer, mockProducer) + messenger := newHTTPControllerMessenger(mockProducer, mockProducer, mockProducer, mockProducer) reqData := &entity.CreateKeypairRequest{Amount: 1} actualData, err := messenger.SendMessage(entity.EnvelopeChannel, reqData) diff --git a/backend/internal/entity/channel.go b/backend/internal/entity/channel.go index fa5f1df9..5758740e 100644 --- a/backend/internal/entity/channel.go +++ b/backend/internal/entity/channel.go @@ -1,7 +1,9 @@ package entity var ( - EnvelopeChannel = "EnvelopeChannel" - HorizonChannel = "HorizonChannel" - CreateKeypairChannel = "CreateKeypairChannel" + EnvelopeChannel = "EnvelopeChannel" + HorizonChannel = "HorizonChannel" + CreateKeypairChannel = "CreateKeypairChannel" + SignChannel = "SignChannel" + SubmitTransactionChannel = "SubmitTransactionChannel" ) diff --git a/backend/internal/entity/message.go b/backend/internal/entity/message.go index 20eefb52..7df569bf 100644 --- a/backend/internal/entity/message.go +++ b/backend/internal/entity/message.go @@ -75,4 +75,15 @@ type ( Account string Weight uint8 } + + SignTransactionRequest struct { + Id int `json:"id"` + Envelope string `json:"envelope"` + PublicKey string `json:"publicKey"` + } + + SubmitRequest struct { + Id int `json:"id"` + Envelope string `json:"envelope"` + } ) diff --git a/backend/internal/entity/transactions.go b/backend/internal/entity/transactions.go index 0e6b9599..7b728b44 100644 --- a/backend/internal/entity/transactions.go +++ b/backend/internal/entity/transactions.go @@ -10,4 +10,6 @@ const ( SetTrustLineFlagsOp = "setTrustLineFlags" FundWithFriendbotHor = "fundWithFriendbot" ClawbackOp = "clawback" + SubmitTransaction = "submitTransaction" + SignTransaction = "signTransaction" ) diff --git a/backend/main.go b/backend/main.go index 09c8a135..d80b8ff9 100644 --- a/backend/main.go +++ b/backend/main.go @@ -53,5 +53,15 @@ func main() { } go envConn.Run(cfg, entity.EnvelopeChannel) - app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer) + // Kafka submit transaction connection + fmt.Println("Kafka submit transaction connection", cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, cfg.Kafka.SubmitTransactionCfg.ProducerTopic) + submitConn := kafka.New(cfg.Kafka, cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, cfg.Kafka.SubmitTransactionCfg.ProducerTopic) + err = submitConn.AttemptConnect() + if err != nil { + fmt.Printf("Failed to connect to Kafka submit transaction topics %s\n", err) + os.Exit(1) + } + go submitConn.Run(cfg, entity.SubmitTransactionChannel) + + app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer, submitConn.Producer) } diff --git a/backend/pkg/kafka/producer.go b/backend/pkg/kafka/producer.go index 9f47623e..701ac8ab 100644 --- a/backend/pkg/kafka/producer.go +++ b/backend/pkg/kafka/producer.go @@ -15,16 +15,15 @@ type Producer struct { func (p *Producer) Produce(key string, value interface{}) error { valueMarshalled, err := json.Marshal(value) if err != nil { - return fmt.Errorf("Producer - Produce - json.Marshal: %v\n", err) + return fmt.Errorf("Producer - Produce - json.Marshal: %v", err) } - err = p.exec.Produce(&kafka.Message{ Key: []byte(key), TopicPartition: kafka.TopicPartition{Topic: &p.Topic, Partition: kafka.PartitionAny}, Value: valueMarshalled, }, nil) if err != nil { - return fmt.Errorf("Producer - Produce - p.exec.Produce: %v\n", err) + return fmt.Errorf("Producer - Produce - p.exec.Produce: %v", err) } return nil From db00a579eb5bbf5b591c006b6894e598ecba8a86 Mon Sep 17 00:00:00 2001 From: fernandodev133 <146200770+fernandodev133@users.noreply.github.com> Date: Wed, 18 Oct 2023 09:52:02 -0300 Subject: [PATCH 02/52] =?UTF-8?q?=E2=9C=85=20Add=20the=20Submit=20transact?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/config/config.go | 4 ++++ backend/internal/app/app.go | 4 ++-- backend/internal/controller/http/v1/router.go | 4 ++-- backend/internal/controller/http/v1/soroban.go | 13 ++++++++++++- backend/internal/controller/http/v1/utils.go | 7 +++++-- backend/internal/controller/http/v1/utils_test.go | 2 +- backend/main.go | 12 ++++++++++-- 7 files changed, 36 insertions(+), 10 deletions(-) diff --git a/backend/config/config.go b/backend/config/config.go index 9e3d1175..22e67c5c 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -34,6 +34,10 @@ type ( ConsumerTopics []string `env:"KAFKA_ENVELOPE_CONSUMER_TOPICS"` ProducerTopic string `env:"KAFKA_SUBMIT_TRANSACTION_PRODUCER_TOPIC"` } + SignTransactionCfg struct { + ConsumerTopics []string `env:"KAFKA_SIGN_TRANSACTION_CONSUMER_TOPICS"` + ProducerTopic string `env:"KAFKA_SIGN_TRANSACTION_PRODUCER_TOPIC"` + } } PGConfig struct { diff --git a/backend/internal/app/app.go b/backend/internal/app/app.go index f8a300e1..dbac1407 100644 --- a/backend/internal/app/app.go +++ b/backend/internal/app/app.go @@ -20,7 +20,7 @@ import ( ) // Run creates objects via constructors. -func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv, pSub entity.ProducerInterface) { +func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv, pSub, pSig entity.ProducerInterface) { // Use cases authUc := usecase.NewAuthUseCase( repo.New(pg), cfg.JWT.SecretKey, @@ -58,7 +58,7 @@ func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv, pSub entity // HTTP Server handler := gin.Default() - v1.NewRouter(handler, pKp, pHor, pEnv, pSub, *authUc, *userUc, *walletUc, *assetUc, *roleUc, *rolePermissionUc, *vaultCategoryUc, *vaultUc, *contractUc, *logUc, cfg.HTTP) + v1.NewRouter(handler, pKp, pHor, pEnv, pSub, pSig, *authUc, *userUc, *walletUc, *assetUc, *roleUc, *rolePermissionUc, *vaultCategoryUc, *vaultUc, *contractUc, *logUc, cfg.HTTP) httpServer := httpserver.New(handler, httpserver.Port(cfg.HTTP.Port), httpserver.ReadTimeout(60*time.Second), diff --git a/backend/internal/controller/http/v1/router.go b/backend/internal/controller/http/v1/router.go index 884d07c7..f1531d0c 100644 --- a/backend/internal/controller/http/v1/router.go +++ b/backend/internal/controller/http/v1/router.go @@ -35,7 +35,7 @@ func CORSMiddleware(cfg config.HTTP) gin.HandlerFunc { // @BasePath /v1 func NewRouter( handler *gin.Engine, - pKp, pHor, pEnv, pSub entity.ProducerInterface, + pKp, pHor, pEnv, pSub, pSig entity.ProducerInterface, authUseCase usecase.AuthUseCase, userUseCase usecase.UserUseCase, walletUseCase usecase.WalletUseCase, @@ -49,7 +49,7 @@ func NewRouter( cfg config.HTTP, ) { // Messenger - messengerController := newHTTPControllerMessenger(pKp, pHor, pEnv, pSub) + messengerController := newHTTPControllerMessenger(pKp, pHor, pEnv, pSub, pSig) // Options Gin handler.Use(gin.Logger()) handler.Use(gin.Recovery()) diff --git a/backend/internal/controller/http/v1/soroban.go b/backend/internal/controller/http/v1/soroban.go index 205fc274..5558da65 100644 --- a/backend/internal/controller/http/v1/soroban.go +++ b/backend/internal/controller/http/v1/soroban.go @@ -28,7 +28,7 @@ func newSorobanRoutes(handler *gin.RouterGroup, w usecase.WalletUseCase, m HTTPC type SignedTransactionRequest struct { Envelope string `json:"envelope" binding:"required" example:"KJDSKD..."` - WalletId int `json:"wallet_id" binding:"required" example:"1"` + WalletPk string `json:"wallet_pk" binding:"required" example:"GDSKJG..."` } type SubmitTransactionRequest struct { @@ -51,6 +51,17 @@ func (r *sorobanRoutes) signTransaction(c *gin.Context) { errorResponse(c, http.StatusBadRequest, "invalid request", err) return } + + res, err := r.m.SendMessage(entity.SignChannel, entity.SignTransactionRequest{ + PublicKey: request.WalletPk, + Envelope: request.Envelope, + }) + if err != nil { + errorResponse(c, http.StatusInternalServerError, "messaging problems", err) + return + } + + c.JSON(http.StatusOK, res) } // @Summary Submit Transaction diff --git a/backend/internal/controller/http/v1/utils.go b/backend/internal/controller/http/v1/utils.go index acc8bbe3..d734dbf9 100644 --- a/backend/internal/controller/http/v1/utils.go +++ b/backend/internal/controller/http/v1/utils.go @@ -16,10 +16,11 @@ type HTTPControllerMessenger struct { pHor entity.ProducerInterface pEnv entity.ProducerInterface pSub entity.ProducerInterface + pSig entity.ProducerInterface } -func newHTTPControllerMessenger(pKp, pHor, pEnv, pSub entity.ProducerInterface) HTTPControllerMessenger { - return HTTPControllerMessenger{pKp, pHor, pEnv, pSub} +func newHTTPControllerMessenger(pKp, pHor, pEnv, pSub, pSig entity.ProducerInterface) HTTPControllerMessenger { + return HTTPControllerMessenger{pKp, pHor, pEnv, pSub, pSig} } func (m *HTTPControllerMessenger) SendMessage(chanName string, value interface{}) (*entity.NotifyData, error) { @@ -78,6 +79,8 @@ func (m *HTTPControllerMessenger) produce(chanName string, msgKey string, value err = m.pEnv.Produce(msgKey, value) case entity.SubmitTransactionChannel: err = m.pSub.Produce(msgKey, value) + case entity.SignChannel: + err = m.pSig.Produce(msgKey, value) default: err = fmt.Errorf("invalid channel name") } diff --git a/backend/internal/controller/http/v1/utils_test.go b/backend/internal/controller/http/v1/utils_test.go index c0d53bf6..dc7a6323 100644 --- a/backend/internal/controller/http/v1/utils_test.go +++ b/backend/internal/controller/http/v1/utils_test.go @@ -26,7 +26,7 @@ func (p *mockProducer) Produce(key string, value interface{}) error { func TestSendMessage(t *testing.T) { mockProducer := newMockProducer() - messenger := newHTTPControllerMessenger(mockProducer, mockProducer, mockProducer, mockProducer) + messenger := newHTTPControllerMessenger(mockProducer, mockProducer, mockProducer, mockProducer, mockProducer) reqData := &entity.CreateKeypairRequest{Amount: 1} actualData, err := messenger.SendMessage(entity.EnvelopeChannel, reqData) diff --git a/backend/main.go b/backend/main.go index d80b8ff9..1449c99e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -54,7 +54,6 @@ func main() { go envConn.Run(cfg, entity.EnvelopeChannel) // Kafka submit transaction connection - fmt.Println("Kafka submit transaction connection", cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, cfg.Kafka.SubmitTransactionCfg.ProducerTopic) submitConn := kafka.New(cfg.Kafka, cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, cfg.Kafka.SubmitTransactionCfg.ProducerTopic) err = submitConn.AttemptConnect() if err != nil { @@ -63,5 +62,14 @@ func main() { } go submitConn.Run(cfg, entity.SubmitTransactionChannel) - app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer, submitConn.Producer) + // Kafka Sign Transaction connection + signConn := kafka.New(cfg.Kafka, cfg.Kafka.SignTransactionCfg.ConsumerTopics, cfg.Kafka.SignTransactionCfg.ProducerTopic) + err = signConn.AttemptConnect() + if err != nil { + fmt.Printf("Failed to connect to Kafka sign transaction topics %s\n", err) + os.Exit(1) + } + go signConn.Run(cfg, entity.SignChannel) + + app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer, submitConn.Producer, signConn.Producer) } From 7f967bfd482d582c2ba06996d56f9763a7e5051c Mon Sep 17 00:00:00 2001 From: fernandodev133 <146200770+fernandodev133@users.noreply.github.com> Date: Wed, 18 Oct 2023 09:52:45 -0300 Subject: [PATCH 03/52] =?UTF-8?q?=F0=9F=93=9D=20=20add=20the=20new=20=20ro?= =?UTF-8?q?utes=20on=20the=20swagger=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/docs/docs.go | 121 ++++++++++++++++++++++++++++++++++++++ backend/docs/swagger.json | 121 ++++++++++++++++++++++++++++++++++++++ backend/docs/swagger.yaml | 80 +++++++++++++++++++++++++ 3 files changed, 322 insertions(+) diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 4669e6c5..b2d449df 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -1259,6 +1259,98 @@ const docTemplate = `{ } } }, + "/soroban-transactions/sign": { + "post": { + "description": "Signed a XDR transaction", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Soroban" + ], + "summary": "Signed Transaction", + "parameters": [ + { + "description": "Signed a XDR transaction", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.SignedTransactionRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/v1.response" + } + } + } + } + }, + "/soroban-transactions/submit": { + "post": { + "description": "Submit a XDR transaction", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Soroban" + ], + "summary": "Submit Transaction", + "parameters": [ + { + "description": "Submit a XDR transaction", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.SubmitTransactionRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/v1.response" + } + } + } + } + }, "/user/create": { "post": { "description": "Create user", @@ -2581,6 +2673,35 @@ const docTemplate = `{ } } }, + "v1.SignedTransactionRequest": { + "type": "object", + "required": [ + "envelope", + "wallet_pk" + ], + "properties": { + "envelope": { + "type": "string", + "example": "KJDSKD..." + }, + "wallet_pk": { + "type": "string", + "example": "GDSKJG..." + } + } + }, + "v1.SubmitTransactionRequest": { + "type": "object", + "required": [ + "envelope" + ], + "properties": { + "envelope": { + "type": "string", + "example": "KJDSKD..." + } + } + }, "v1.TransferAssetRequest": { "type": "object", "required": [ diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 3b34e944..0f34429b 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -1247,6 +1247,98 @@ } } }, + "/soroban-transactions/sign": { + "post": { + "description": "Signed a XDR transaction", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Soroban" + ], + "summary": "Signed Transaction", + "parameters": [ + { + "description": "Signed a XDR transaction", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.SignedTransactionRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/v1.response" + } + } + } + } + }, + "/soroban-transactions/submit": { + "post": { + "description": "Submit a XDR transaction", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Soroban" + ], + "summary": "Submit Transaction", + "parameters": [ + { + "description": "Submit a XDR transaction", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.SubmitTransactionRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/v1.response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/v1.response" + } + } + } + } + }, "/user/create": { "post": { "description": "Create user", @@ -2569,6 +2661,35 @@ } } }, + "v1.SignedTransactionRequest": { + "type": "object", + "required": [ + "envelope", + "wallet_pk" + ], + "properties": { + "envelope": { + "type": "string", + "example": "KJDSKD..." + }, + "wallet_pk": { + "type": "string", + "example": "GDSKJG..." + } + } + }, + "v1.SubmitTransactionRequest": { + "type": "object", + "required": [ + "envelope" + ], + "properties": { + "envelope": { + "type": "string", + "example": "KJDSKD..." + } + } + }, "v1.TransferAssetRequest": { "type": "object", "required": [ diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 744e118e..0cbb94a5 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -459,6 +459,26 @@ definitions: example: 1 type: integer type: object + v1.SignedTransactionRequest: + properties: + envelope: + example: KJDSKD... + type: string + wallet_pk: + example: GDSKJG... + type: string + required: + - envelope + - wallet_pk + type: object + v1.SubmitTransactionRequest: + properties: + envelope: + example: KJDSKD... + type: string + required: + - envelope + type: object v1.TransferAssetRequest: properties: amount: @@ -1377,6 +1397,66 @@ paths: summary: Update a role tags: - Role + /soroban-transactions/sign: + post: + consumes: + - application/json + description: Signed a XDR transaction + parameters: + - description: Signed a XDR transaction + in: body + name: request + required: true + schema: + $ref: '#/definitions/v1.SignedTransactionRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/v1.response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/v1.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/v1.response' + summary: Signed Transaction + tags: + - Soroban + /soroban-transactions/submit: + post: + consumes: + - application/json + description: Submit a XDR transaction + parameters: + - description: Submit a XDR transaction + in: body + name: request + required: true + schema: + $ref: '#/definitions/v1.SubmitTransactionRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/v1.response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/v1.response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/v1.response' + summary: Submit Transaction + tags: + - Soroban /user/create: post: consumes: From cc327457cf18940b35b453cf42f2895dee1bbde0 Mon Sep 17 00:00:00 2001 From: fernandodev133 <146200770+fernandodev133@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:54:49 -0300 Subject: [PATCH 04/52] =?UTF-8?q?=F0=9F=A7=B1=20add=20the=20new=20topics?= =?UTF-8?q?=20on=20the=20kafka=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/config/config.go | 4 ++-- backend/internal/entity/channel.go | 2 +- dev.docker-compose.yml | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/config/config.go b/backend/config/config.go index 22e67c5c..4f6a376d 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -35,8 +35,8 @@ type ( ProducerTopic string `env:"KAFKA_SUBMIT_TRANSACTION_PRODUCER_TOPIC"` } SignTransactionCfg struct { - ConsumerTopics []string `env:"KAFKA_SIGN_TRANSACTION_CONSUMER_TOPICS"` - ProducerTopic string `env:"KAFKA_SIGN_TRANSACTION_PRODUCER_TOPIC"` + ConsumerTopics []string `env:"KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS"` + ProducerTopic string `env:"KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC"` } } diff --git a/backend/internal/entity/channel.go b/backend/internal/entity/channel.go index 5758740e..3e7a3bb9 100644 --- a/backend/internal/entity/channel.go +++ b/backend/internal/entity/channel.go @@ -4,6 +4,6 @@ var ( EnvelopeChannel = "EnvelopeChannel" HorizonChannel = "HorizonChannel" CreateKeypairChannel = "CreateKeypairChannel" - SignChannel = "SignChannel" SubmitTransactionChannel = "SubmitTransactionChannel" + SignChannel = "SignChannel" ) diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml index 39254746..3f634f51 100644 --- a/dev.docker-compose.yml +++ b/dev.docker-compose.yml @@ -168,6 +168,8 @@ services: KAFKA_ENVELOPE_CONSUMER_TOPICS: ${KAFKA_ENVELOPE_CONSUMER_TOPICS:-submitResponse} KAFKA_HORIZON_PRODUCER_TOPIC: ${KAFKA_HORIZON_PRODUCER_TOPIC:-horizonRequest} KAFKA_HORIZON_CONSUMER_TOPICS: ${KAFKA_HORIZON_CONSUMER_TOPICS:-horizonResponse} + KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS: ${KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS:-signSorobanTransaction} + KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC: ${KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC:-signedSorobanTransaction} depends_on: kafka1: @@ -182,6 +184,8 @@ services: kafka-topics --create --topic $$KAFKA_ENVELOPE_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 kafka-topics --create --topic $$KAFKA_HORIZON_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 kafka-topics --create --topic $$KAFKA_HORIZON_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 kafka1 cub kafka-ready -b kafka1:129092 1 20 " @@ -243,4 +247,4 @@ services: volumes: postgres: - node_modules_tfv2_frontend: \ No newline at end of file + node_modules_tfv2_frontend: From f61e6e047e476fbc6cb5c7b66afcb64bce8e820f Mon Sep 17 00:00:00 2001 From: fernandodev133 <146200770+fernandodev133@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:55:32 -0300 Subject: [PATCH 05/52] =?UTF-8?q?=F0=9F=93=9D=20add=20the=20env=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/.env.example | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/.env.example b/backend/.env.example index 718aeef7..5b4429f0 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -14,8 +14,11 @@ KAFKA_ENVELOPE_PRODUCER_TOPIC= KAFKA_ENVELOPE_CONSUMER_TOPICS= KAFKA_HORIZON_PRODUCER_TOPIC= KAFKA_HORIZON_CONSUMER_TOPICS= -KAFKA_SCHEMA_REGISTRY_URL= +KAFKA_SUBMIT_TRANSACTION_PRODUCER_TOPIC= +KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS= +KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC= +KAFKA_SCHEMA_REGISTRY_URL= # HTTP HTTP_PORT= HTTP_FRONT_ADRESS= From 1a0c258846140e9ecda8963984f9166d1986754e Mon Sep 17 00:00:00 2001 From: wjuniorbh92 Date: Mon, 23 Oct 2023 10:12:46 -0300 Subject: [PATCH 06/52] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20remove=20the=20requi?= =?UTF-8?q?red=20wallet=5Fpk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/docs/docs.go | 3 +-- backend/docs/swagger.json | 3 +-- backend/docs/swagger.yaml | 1 - backend/internal/controller/http/v1/soroban.go | 12 +++++++++++- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/backend/docs/docs.go b/backend/docs/docs.go index b2d449df..1ba198e0 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -2676,8 +2676,7 @@ const docTemplate = `{ "v1.SignedTransactionRequest": { "type": "object", "required": [ - "envelope", - "wallet_pk" + "envelope" ], "properties": { "envelope": { diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 0f34429b..2691937e 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -2664,8 +2664,7 @@ "v1.SignedTransactionRequest": { "type": "object", "required": [ - "envelope", - "wallet_pk" + "envelope" ], "properties": { "envelope": { diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 0cbb94a5..7b3edd74 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -469,7 +469,6 @@ definitions: type: string required: - envelope - - wallet_pk type: object v1.SubmitTransactionRequest: properties: diff --git a/backend/internal/controller/http/v1/soroban.go b/backend/internal/controller/http/v1/soroban.go index 5558da65..aca524ad 100644 --- a/backend/internal/controller/http/v1/soroban.go +++ b/backend/internal/controller/http/v1/soroban.go @@ -28,7 +28,7 @@ func newSorobanRoutes(handler *gin.RouterGroup, w usecase.WalletUseCase, m HTTPC type SignedTransactionRequest struct { Envelope string `json:"envelope" binding:"required" example:"KJDSKD..."` - WalletPk string `json:"wallet_pk" binding:"required" example:"GDSKJG..."` + WalletPk string `json:"wallet_pk" example:"GDSKJG..."` } type SubmitTransactionRequest struct { @@ -52,6 +52,16 @@ func (r *sorobanRoutes) signTransaction(c *gin.Context) { return } + if request.WalletPk == "" { + sponsor, err := r.w.Get(_sponsorId) + if err != nil { + errorResponse(c, http.StatusInternalServerError, "database problems", err) + return + } + + request.WalletPk = sponsor.Key.PublicKey + } + res, err := r.m.SendMessage(entity.SignChannel, entity.SignTransactionRequest{ PublicKey: request.WalletPk, Envelope: request.Envelope, From 21fcc3ef0acde5be556fcbc206acbff2790059de Mon Sep 17 00:00:00 2001 From: wjuniorbh92 Date: Mon, 23 Oct 2023 14:48:21 -0300 Subject: [PATCH 07/52] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20add=20in=20the=20doc?= =?UTF-8?q?ker=20compose=20the=20envs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev.docker-compose.yml | 44 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml index 3f634f51..a408e568 100644 --- a/dev.docker-compose.yml +++ b/dev.docker-compose.yml @@ -76,6 +76,8 @@ services: KAFKA_CREATE_KP_PRODUCER_TOPIC: ${KMS_KAFKA_PRODUCER_TOPIC:-generatedKeypairs} KAFKA_SIGN_CONSUMER_TOPICS: ${KAFKA_SIGN_CONSUMER_TOPICS:-signEnvelope} KAFKA_SIGN_PRODUCER_TOPIC: ${KAFKA_SIGN_PRODUCER_TOPIC:-signedEnvelopes} + KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS: ${KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS:-signSorobanEnvelope} + KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC: ${KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC:-signedSorobanEnvelopes} PG_HOST: ${PG_HOST:-postgres} PG_PORT: ${PG_PORT:-5432} PG_USER: ${PG_USER:-postgres} @@ -133,27 +135,27 @@ services: retries: 20 #Kafka - Schema Registry# - schema_registry: - profiles: ["all", "kafka", "starlabs", "kms"] - image: confluentinc/cp-schema-registry:7.1.2 - container_name: schema_registry - ports: - - "8085:8085" - environment: - SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8085 - SCHEMA_REGISTRY_HOST_NAME: schema_registry - SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: zoo1:2181 - SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_ORIGIN: "*" - SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_METHODS: "GET,POST,PUT,OPTIONS" - SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka1:19092 - healthcheck: - start_period: 10s - interval: 10s - retries: 20 - test: curl --user superUser:superUser --fail --silent --insecure http://schema_registry:8085/subjects --output /dev/null || exit 1 - depends_on: - kafka1: - condition: service_healthy + # schema_registry: + # profiles: ["all", "kafka", "starlabs", "kms"] + # image: confluentinc/cp-schema-registry:7.1.2 + # container_name: schema_registry + # ports: + # - "8085:8085" + # environment: + # SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8085 + # SCHEMA_REGISTRY_HOST_NAME: schema_registry + # SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: zoo1:2181 + # SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_ORIGIN: "*" + # SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_METHODS: "GET,POST,PUT,OPTIONS" + # SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka1:19092 + # healthcheck: + # start_period: 10s + # interval: 10s + # retries: 20 + # test: curl --user superUser:superUser --fail --silent --insecure http://schema_registry:8085/subjects --output /dev/null || exit 1 + # depends_on: + # kafka1: + # condition: service_healthy #Kafka - Init# kafka_init: From c6ff7dd6c5f94cbab51ce1825a51b5a1d7351f56 Mon Sep 17 00:00:00 2001 From: wjuniorbh92 Date: Mon, 23 Oct 2023 15:03:09 -0300 Subject: [PATCH 08/52] =?UTF-8?q?=F0=9F=90=9B=20Fix=20the=20migrations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/migrations/000010_role_permission_juntion.up.sql | 2 +- backend/migrations/000024_refact_permissions.up.sql | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/migrations/000010_role_permission_juntion.up.sql b/backend/migrations/000010_role_permission_juntion.up.sql index dcfcaa28..7b21f014 100644 --- a/backend/migrations/000010_role_permission_juntion.up.sql +++ b/backend/migrations/000010_role_permission_juntion.up.sql @@ -5,7 +5,7 @@ CREATE TABLE RolePermissionJunction ( CONSTRAINT FK_role FOREIGN KEY (role_id) REFERENCES Role (id), CONSTRAINT FK_permission - FOREIGN KEY (permission_id) REFERENCES Permission (id) + FOREIGN KEY (permission_id) REFERENCES Permission (id) ON DELETE CASCADE ); insert into rolepermissionjunction (role_id, permission_id) values (1, 1); diff --git a/backend/migrations/000024_refact_permissions.up.sql b/backend/migrations/000024_refact_permissions.up.sql index 2d3176d7..c1e64d55 100644 --- a/backend/migrations/000024_refact_permissions.up.sql +++ b/backend/migrations/000024_refact_permissions.up.sql @@ -1,5 +1,5 @@ -DELETE FROM permission WHERE ID = 2; -DELETE FROM permission WHERE ID = 6; +DELETE FROM permission WHERE ID = 2 ; +DELETE FROM permission WHERE ID = 6 ; UPDATE permission SET name = 'Token management' WHERE ID = 3; UPDATE permission SET name = 'Transfer internally' WHERE ID = 4; UPDATE permission SET name = 'Transfer externally' WHERE ID = 5; From 018403dde184b34307d108b35fc15e3eb92d3481 Mon Sep 17 00:00:00 2001 From: wjuniorbh92 Date: Mon, 23 Oct 2023 15:21:45 -0300 Subject: [PATCH 09/52] =?UTF-8?q?=F0=9F=90=9B=20add=20in=20the=20deserizal?= =?UTF-8?q?izer=20the=20switch=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/entity/message.go | 5 +++++ backend/pkg/kafka/deserializer.go | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/backend/internal/entity/message.go b/backend/internal/entity/message.go index 7df569bf..a4fb054b 100644 --- a/backend/internal/entity/message.go +++ b/backend/internal/entity/message.go @@ -82,6 +82,11 @@ type ( PublicKey string `json:"publicKey"` } + SorobanTransactionResponse struct { + Id int `json:"id"` + Envelope string `json:"envelope"` + } + SubmitRequest struct { Id int `json:"id"` Envelope string `json:"envelope"` diff --git a/backend/pkg/kafka/deserializer.go b/backend/pkg/kafka/deserializer.go index b2b47cde..c53ef4db 100644 --- a/backend/pkg/kafka/deserializer.go +++ b/backend/pkg/kafka/deserializer.go @@ -23,6 +23,10 @@ func (d *Deserializer) DeserializeMessage(msg *kafka.Message, chanName string) ( return d.deserializeHorizonMessage(msg) case entity.EnvelopeChannel: return d.deserializeEnvelopeMessage(msg) + case entity.SignChannel: + return d.deserializeEnvelopSorobanTransaction(msg) + case entity.SubmitTransactionChannel: + return d.deserializeEnvelopeMessage(msg) default: return nil, fmt.Errorf("invalid channel name: %s", chanName) } @@ -55,6 +59,15 @@ func (d *Deserializer) deserializeEnvelopeMessage(msg *kafka.Message) (entity.En return data, nil } +func (d *Deserializer) deserializeEnvelopSorobanTransaction(msg *kafka.Message) (entity.SignTransactionRequest, error) { + data := entity.SignTransactionRequest{} + err := d.unmarshalMessage(msg, &data) + if err != nil { + return data, fmt.Errorf("failed to deserialize envelope response: %w", err) + } + return data, nil +} + func (d *Deserializer) unmarshalMessage(msg *kafka.Message, v interface{}) error { if d.schemaEnabled { return d.exec.DeserializeInto(*msg.TopicPartition.Topic, msg.Value, v) From a039a23a770814908865d5dfdcb8b39cf4c00245 Mon Sep 17 00:00:00 2001 From: wjuniorbh92 Date: Mon, 23 Oct 2023 15:42:23 -0300 Subject: [PATCH 10/52] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20fix=20typos=20in=20t?= =?UTF-8?q?he=20stellar=20sign?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/controller/http/v1/soroban.go | 5 ++--- backend/internal/entity/message.go | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/internal/controller/http/v1/soroban.go b/backend/internal/controller/http/v1/soroban.go index aca524ad..d73723e0 100644 --- a/backend/internal/controller/http/v1/soroban.go +++ b/backend/internal/controller/http/v1/soroban.go @@ -61,10 +61,9 @@ func (r *sorobanRoutes) signTransaction(c *gin.Context) { request.WalletPk = sponsor.Key.PublicKey } - res, err := r.m.SendMessage(entity.SignChannel, entity.SignTransactionRequest{ - PublicKey: request.WalletPk, - Envelope: request.Envelope, + PublicKeys: []string{request.WalletPk}, + Envelope: request.Envelope, }) if err != nil { errorResponse(c, http.StatusInternalServerError, "messaging problems", err) diff --git a/backend/internal/entity/message.go b/backend/internal/entity/message.go index a4fb054b..eb3d44df 100644 --- a/backend/internal/entity/message.go +++ b/backend/internal/entity/message.go @@ -77,9 +77,9 @@ type ( } SignTransactionRequest struct { - Id int `json:"id"` - Envelope string `json:"envelope"` - PublicKey string `json:"publicKey"` + Id int `json:"id"` + Envelope string `json:"envelope"` + PublicKeys []string `json:"publicKeys"` } SorobanTransactionResponse struct { From 76320800b0ac31e5e1e951ef11dec9e4eea63c70 Mon Sep 17 00:00:00 2001 From: wjuniorbh92 Date: Fri, 27 Oct 2023 10:12:20 -0300 Subject: [PATCH 11/52] =?UTF-8?q?=E2=9C=85=20add=20sponsor=5Fpk=20endpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/docs/docs.go | 29 +++++++++++++++++++ backend/docs/swagger.json | 29 +++++++++++++++++++ backend/docs/swagger.yaml | 19 ++++++++++++ .../internal/controller/http/v1/wallets.go | 19 ++++++++++++ 4 files changed, 96 insertions(+) diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 1ba198e0..76e11bd9 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -2016,6 +2016,35 @@ const docTemplate = `{ } } } + }, + "/wallets/sponsor_pk/": { + "get": { + "description": "Get Sponsor Public Key", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Wallets" + ], + "summary": "Get Sponsor Public Key", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/v1.response" + } + } + } + } } }, "definitions": { diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 2691937e..e68614b6 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -2004,6 +2004,35 @@ } } } + }, + "/wallets/sponsor_pk/": { + "get": { + "description": "Get Sponsor Public Key", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Wallets" + ], + "summary": "Get Sponsor Public Key", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/v1.response" + } + } + } + } } }, "definitions": { diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 7b3edd74..4d14e783 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -1897,4 +1897,23 @@ paths: summary: Fund Wallet tags: - Wallets + /wallets/sponsor_pk/: + get: + consumes: + - application/json + description: Get Sponsor Public Key + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/v1.response' + summary: Get Sponsor Public Key + tags: + - Wallets swagger: "2.0" diff --git a/backend/internal/controller/http/v1/wallets.go b/backend/internal/controller/http/v1/wallets.go index 90fb3843..f67fa4bd 100644 --- a/backend/internal/controller/http/v1/wallets.go +++ b/backend/internal/controller/http/v1/wallets.go @@ -21,6 +21,7 @@ func newWalletsRoutes(handler *gin.RouterGroup, w usecase.WalletUseCase, m HTTPC h.GET("", r.list) h.POST("", r.create) h.POST("fund/", r.fundWallet) + h.GET("sponsor_pk/", r.getSponsorPublicKey) } } @@ -147,3 +148,21 @@ func (r *walletsRoutes) fundWallet(c *gin.Context) { c.JSON(http.StatusOK, wallet) } + +// @Summary Get Sponsor Public Key +// @Description Get Sponsor Public Key +// @Tags Wallets +// @Accept json +// @Produce json +// @Success 200 {object} string +// @Failure 500 {object} response +// @Router /wallets/sponsor_pk/ [get] +func (r *walletsRoutes) getSponsorPublicKey(c *gin.Context) { + sponsor, err := r.w.Get(_sponsorId) + if err != nil { + errorResponse(c, http.StatusInternalServerError, "database problems", err) + return + } + + c.JSON(http.StatusOK, sponsor.Key.PublicKey) +} From 1e878f6bb77b1c2e4b3a7ce9b7fa6741031528dd Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Fri, 3 Nov 2023 17:53:57 -0300 Subject: [PATCH 12/52] list contracts --- .../internal/controller/http/v1/contracts.go | 4 +-- .../usecase/repo/contract_postgres.go | 25 ++++++++++++++++--- .../000029_asset_contract_id.down.sql | 1 + .../000029_asset_contract_id.up.sql | 1 + 4 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 backend/migrations/000029_asset_contract_id.down.sql create mode 100644 backend/migrations/000029_asset_contract_id.up.sql diff --git a/backend/internal/controller/http/v1/contracts.go b/backend/internal/controller/http/v1/contracts.go index 1ef5a5fa..a3a2fbc5 100644 --- a/backend/internal/controller/http/v1/contracts.go +++ b/backend/internal/controller/http/v1/contracts.go @@ -26,7 +26,7 @@ func newContractRoutes(handler *gin.RouterGroup, m HTTPControllerMessenger, a us { h.GET("/:id", r.getContractById) h.POST("", r.createContract) - h.GET("list", r.getAllContracts) + h.GET("/list", r.getAllContracts) } } @@ -108,7 +108,7 @@ func (r *contractRoutes) createContract(c *gin.Context) { // @Failure 500 {object} response // @Router / [get] func (r *contractRoutes) getAllContracts(c *gin.Context) { - contract, err := r.v.GetAll() + contract, err := r.c.GetAll() if err != nil { errorResponse(c, http.StatusInternalServerError, "error getting contract", err) return diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index 119bf80f..7ac0cfbd 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -24,12 +24,22 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { v.id AS vault_id, v.name AS vault_name, vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, - wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight + wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, + d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, + dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, + i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, + ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight FROM contracts c JOIN vault v ON c.vault_id = v.id JOIN vaultcategory vc ON v.vault_category_id = vc.id JOIN wallet w ON v.wallet_id = w.id - JOIN key wk ON w.id = wk.wallet_id; + JOIN key wk ON w.id = wk.wallet_id + JOIN asset a ON a.id = c.asset_id + JOIN wallet d ON a.distributor_id = d.id + JOIN key dk ON d.id = dk.wallet_id + JOIN wallet i ON a.issuer_id = i.id + JOIN key ik ON i.id = ik.wallet_id ` rows, err := r.Db.Query(query) @@ -46,6 +56,8 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { var vault entity.Vault var asset entity.Asset var wallet entity.Wallet + var assetDistributor entity.Wallet + var assetIssuer entity.Wallet err := rows.Scan( &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, &contract.PenaltyRate, @@ -53,6 +65,11 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &assetDistributor.Id, &assetDistributor.Type, &assetDistributor.Funded, + &assetDistributor.Key.Id, &assetDistributor.Key.PublicKey, &assetDistributor.Key.Weight, + &assetIssuer.Id, &assetIssuer.Type, &assetIssuer.Funded, + &assetIssuer.Key.Id, &assetIssuer.Key.PublicKey, &assetIssuer.Key.Weight, ) if err != nil { return nil, fmt.Errorf("ContractRepo - GetContractCategories - row.Scan: %w", err) @@ -60,6 +77,8 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { vault.Wallet = wallet vault.VaultCategory = vaultCategory + asset.Distributor = assetDistributor + asset.Issuer = assetIssuer contract.Asset = asset contract.Vault = vault @@ -118,7 +137,7 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { func (r ContractRepo) CreateContract(data entity.Contract) (entity.Contract, error) { res := data - stmt := `INSERT INTO Contract (name, address, yield_rate, term, min_deposit, penalty_rate, vault_id, asset_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id;` + stmt := `INSERT INTO Contracts (name, address, yield_rate, term, min_deposit, penalty_rate, vault_id, asset_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id;` err := r.Db.QueryRow(stmt, data.Name, data.Address, data.YieldRate, data.Term, data.MinDeposit, data.PenaltyRate, data.Vault.Id, data.Asset.Id).Scan(&res.Id) if err != nil { return entity.Contract{}, fmt.Errorf("ContractRepo - Contract - db.QueryRow: %w", err) diff --git a/backend/migrations/000029_asset_contract_id.down.sql b/backend/migrations/000029_asset_contract_id.down.sql new file mode 100644 index 00000000..e72b665f --- /dev/null +++ b/backend/migrations/000029_asset_contract_id.down.sql @@ -0,0 +1 @@ +ALTER TABLE asset DROP COLUMN contract_id; \ No newline at end of file diff --git a/backend/migrations/000029_asset_contract_id.up.sql b/backend/migrations/000029_asset_contract_id.up.sql new file mode 100644 index 00000000..56c3d750 --- /dev/null +++ b/backend/migrations/000029_asset_contract_id.up.sql @@ -0,0 +1 @@ +ALTER TABLE asset ADD COLUMN contract_id varchar(255); \ No newline at end of file From d6cdab770e2817a1af1c5552de7e82d60178a9f2 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 20 Nov 2023 14:52:36 -0300 Subject: [PATCH 13/52] add contract compound --- .../internal/controller/http/v1/contracts.go | 11 +- backend/internal/entity/contract.go | 1 + .../usecase/repo/contract_postgres.go | 49 +++- .../000030_add_contract_compound.down.sql | 1 + .../000030_add_contract_compound.up.sql | 1 + dev.docker-compose.yml | 252 ------------------ 6 files changed, 44 insertions(+), 271 deletions(-) create mode 100644 backend/migrations/000030_add_contract_compound.down.sql create mode 100644 backend/migrations/000030_add_contract_compound.up.sql delete mode 100644 dev.docker-compose.yml diff --git a/backend/internal/controller/http/v1/contracts.go b/backend/internal/controller/http/v1/contracts.go index a3a2fbc5..a2aa0158 100644 --- a/backend/internal/controller/http/v1/contracts.go +++ b/backend/internal/controller/http/v1/contracts.go @@ -36,9 +36,10 @@ type CreateContractRequest struct { VaultId string `json:"vault_id" binding:"required" example:"1"` Address string `json:"address" binding:"required" example:"GSDSC..."` YieldRate int `json:"yield_rate" binding:"required" example:"1"` - Term int `json:"term" binding:"required" example:"1"` + Term int `json:"term" binding:"required" example:"60"` MinDeposit int `json:"min_deposit" binding:"required" example:"1"` PenaltyRate int `json:"penalty_rate" binding:"required" example:"1"` + Compound int `json:"compound" binding:"required" example:"60"` } // @Summary Create a new contract @@ -88,6 +89,7 @@ func (r *contractRoutes) createContract(c *gin.Context) { Term: request.Term, MinDeposit: request.MinDeposit, PenaltyRate: request.PenaltyRate, + Compound: request.Compound, } contract, err = r.c.Create(contract) @@ -128,12 +130,7 @@ func (r *contractRoutes) getAllContracts(c *gin.Context) { func (r *contractRoutes) getContractById(c *gin.Context) { idStr := c.Param("id") - vaultId, err := strconv.Atoi(idStr) - if err != nil { - errorResponse(c, http.StatusBadRequest, "invalid vault ID", err) - return - } - contract, err := r.v.GetById(vaultId) + contract, err := r.c.GetById(idStr) if err != nil { errorResponse(c, http.StatusInternalServerError, "error getting contract", err) return diff --git a/backend/internal/entity/contract.go b/backend/internal/entity/contract.go index 00e0967d..9ea0115e 100644 --- a/backend/internal/entity/contract.go +++ b/backend/internal/entity/contract.go @@ -11,4 +11,5 @@ type Contract struct { MinDeposit int `json:"min_deposit" db:"min_deposit"` PenaltyRate int `json:"penalty_rate" db:"penalty_rate"` CreatedAt string `json:"created_at" db:"created_at"` + Compound int `json:"compound" db:"compound"` } diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index 7ac0cfbd..0bc68683 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -21,7 +21,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { SELECT c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, c.yield_rate AS contract_yield_rate, c.term AS contract_term, c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, - v.id AS vault_id, v.name AS vault_name, + c.compound AS contract_compound, v.id AS vault_id, v.name AS vault_name, vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, @@ -60,7 +60,8 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { var assetIssuer entity.Wallet err := rows.Scan( - &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, &contract.PenaltyRate, + &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, + &contract.PenaltyRate, &contract.Compound, &vault.Id, &vault.Name, &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, @@ -90,18 +91,28 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { query := ` - SELECT - c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, c.yield_rate AS contract_yield_rate, - c.term AS contract_term, c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, - v.id AS vault_id, v.name AS vault_name, - vc.id AS vault_category_id, vc.name as vault_category_name, - w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, - wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight + SELECT + c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, c.yield_rate AS contract_yield_rate, + c.term AS contract_term, c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, + c.compound AS contract_compound, v.id AS vault_id, v.name AS vault_name, + vc.id AS vault_category_id, vc.name as vault_category_name, + w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, + wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, + d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, + dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, + i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, + ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight FROM contracts c JOIN vault v ON c.vault_id = v.id JOIN vaultcategory vc ON v.vault_category_id = vc.id JOIN wallet w ON v.wallet_id = w.id JOIN key wk ON w.id = wk.wallet_id + JOIN asset a ON a.id = c.asset_id + JOIN wallet d ON a.distributor_id = d.id + JOIN key dk ON d.id = dk.wallet_id + JOIN wallet i ON a.issuer_id = i.id + JOIN key ik ON i.id = ik.wallet_id WHERE c.id = $1; ` @@ -112,13 +123,21 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { var vault entity.Vault var asset entity.Asset var wallet entity.Wallet + var assetDistributor entity.Wallet + var assetIssuer entity.Wallet err := row.Scan( - &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, &contract.PenaltyRate, + &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, + &contract.PenaltyRate, &contract.Compound, &vault.Id, &vault.Name, &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &assetDistributor.Id, &assetDistributor.Type, &assetDistributor.Funded, + &assetDistributor.Key.Id, &assetDistributor.Key.PublicKey, &assetDistributor.Key.Weight, + &assetIssuer.Id, &assetIssuer.Type, &assetIssuer.Funded, + &assetIssuer.Key.Id, &assetIssuer.Key.PublicKey, &assetIssuer.Key.Weight, ) if err != nil { if err == sql.ErrNoRows { @@ -130,6 +149,8 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { vault.Wallet = wallet vault.VaultCategory = vaultCategory contract.Asset = asset + asset.Distributor = assetDistributor + asset.Issuer = assetIssuer contract.Vault = vault return contract, nil @@ -137,8 +158,12 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { func (r ContractRepo) CreateContract(data entity.Contract) (entity.Contract, error) { res := data - stmt := `INSERT INTO Contracts (name, address, yield_rate, term, min_deposit, penalty_rate, vault_id, asset_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id;` - err := r.Db.QueryRow(stmt, data.Name, data.Address, data.YieldRate, data.Term, data.MinDeposit, data.PenaltyRate, data.Vault.Id, data.Asset.Id).Scan(&res.Id) + stmt := `INSERT INTO Contracts (name, address, yield_rate, term, min_deposit, penalty_rate, compound, vault_id, asset_id) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id;` + + err := r.Db.QueryRow(stmt, data.Name, data.Address, data.YieldRate, data.Term, data.MinDeposit, + data.PenaltyRate, data.Compound, data.Vault.Id, data.Asset.Id).Scan(&res.Id) + if err != nil { return entity.Contract{}, fmt.Errorf("ContractRepo - Contract - db.QueryRow: %w", err) } diff --git a/backend/migrations/000030_add_contract_compound.down.sql b/backend/migrations/000030_add_contract_compound.down.sql new file mode 100644 index 00000000..dd7aeaf2 --- /dev/null +++ b/backend/migrations/000030_add_contract_compound.down.sql @@ -0,0 +1 @@ +ALTER TABLE contracts DROP COLUMN compound; \ No newline at end of file diff --git a/backend/migrations/000030_add_contract_compound.up.sql b/backend/migrations/000030_add_contract_compound.up.sql new file mode 100644 index 00000000..c8bfa6c7 --- /dev/null +++ b/backend/migrations/000030_add_contract_compound.up.sql @@ -0,0 +1 @@ +ALTER TABLE contracts ADD COLUMN compound INT DEFAULT 0; \ No newline at end of file diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml deleted file mode 100644 index a408e568..00000000 --- a/dev.docker-compose.yml +++ /dev/null @@ -1,252 +0,0 @@ -version: "3.7" - -services: - postgres: - container_name: postgres - profiles: ["all", "starlabs", "tests", "kafka"] - image: postgres - environment: - POSTGRES_USER: ${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password} - POSTGRES_DB: ${POSTGRES_DB:-postgres} - PGDATA: /data/postgres - volumes: - - postgres:/data/postgres - ports: - - "5432:5432" - restart: unless-stopped - healthcheck: - test: - [ - "CMD-SHELL", - "sh -c 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}'", - ] - interval: 10s - timeout: 3s - retries: 3 - - tfv2_frontend: - profiles: ["all", "frontend"] - container_name: tfv2_frontend - build: - context: ./frontend - target: local - args: - REACT_APP_API_URL: ${FRONTEND_REACT_APP_API_URL:-http://localhost:8080} - REACT_APP_SENTRY_DSN: ${SENTRY_DSN:-https://examplePublicKey@o0.ingest.sentry.io/0} - environment: - REACT_APP_API_URL: ${FRONTEND_REACT_APP_API_URL:-http://localhost:8080} - REACT_APP_SENTRY_DSN: ${SENTRY_DSN:-https://examplePublicKey@o0.ingest.sentry.io/0} - volumes: - - ./frontend/:/app - - node_modules_tfv2_frontend:/app/node_modules - ports: - - 3000:3000 - - backend: - platform: linux/amd64 - profiles: ["all", "tests"] - container_name: token-factory-v2 - build: - context: ./backend - dockerfile: dev.Dockerfile - image: mullberry-backend - ports: - - "8080:8080" - volumes: - - ./:/go/src/CheesecakeLabs/token-factory-v2/backend - depends_on: - postgres: - condition: service_healthy - - stellar-kms: - platform: linux/amd64 - profiles: ["all", "starlabs", "tests"] - container_name: kms - build: - context: ./stellar-kms - dockerfile: dev.Dockerfile - volumes: - - ".:/workspace" - environment: - KAFKA_ENABLED: ${KAFKA_ENABLED:-True} - KAFKA_CLIENT_GROUP_ID: ${KAFKA_CLIENT_GROUP_ID:-starlabs} - KAFKA_CLIENT_BROKERS: ${KAFKA_CLIENT_BROKERS:-kafka1:19092} - KAFKA_CREATE_KP_CONSUMER_TOPICS: ${KMS_KAFKA_CONSUMER_TOPICS:-generateKeypair} - KAFKA_CREATE_KP_PRODUCER_TOPIC: ${KMS_KAFKA_PRODUCER_TOPIC:-generatedKeypairs} - KAFKA_SIGN_CONSUMER_TOPICS: ${KAFKA_SIGN_CONSUMER_TOPICS:-signEnvelope} - KAFKA_SIGN_PRODUCER_TOPIC: ${KAFKA_SIGN_PRODUCER_TOPIC:-signedEnvelopes} - KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS: ${KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS:-signSorobanEnvelope} - KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC: ${KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC:-signedSorobanEnvelopes} - PG_HOST: ${PG_HOST:-postgres} - PG_PORT: ${PG_PORT:-5432} - PG_USER: ${PG_USER:-postgres} - PG_PASSWORD: ${PG_PASSWORD:-password} - PG_DB_NAME: ${PG_DATABASE:-postgres} - MASTER_KEY: ${MASTER_KEY:-da52f130e6fd477256b0c554aba89503} - depends_on: - postgres: - condition: service_healthy - kafka1: - condition: service_healthy - - zoo1: - profiles: ["all", "starlabs", "tests", "kafka"] - image: confluentinc/cp-zookeeper:7.3.2 - hostname: zoo1 - container_name: zoo1 - ports: - - "2181:2181" - environment: - ZOOKEEPER_CLIENT_PORT: 2181 - ZOOKEEPER_SERVER_ID: 1 - ZOOKEEPER_SERVERS: zoo1:2888:3888 - - kafka1: - profiles: ["all", "starlabs", "tests", "kafka"] - image: confluentinc/cp-kafka:7.3.2 - hostname: kafka1 - container_name: kafka1 - ports: - - "9092:9092" - - "29092:29092" - - "9999:9999" - environment: - KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT - KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL - KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181" - KAFKA_BROKER_ID: 1 - KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 - KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 - KAFKA_JMX_PORT: 9999 - KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1} - KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer - KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true" - depends_on: - - zoo1 - healthcheck: - test: nc -z kafka1 19092 || exit -1 - start_period: 30s - interval: 10s - timeout: 10s - retries: 20 - - #Kafka - Schema Registry# - # schema_registry: - # profiles: ["all", "kafka", "starlabs", "kms"] - # image: confluentinc/cp-schema-registry:7.1.2 - # container_name: schema_registry - # ports: - # - "8085:8085" - # environment: - # SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8085 - # SCHEMA_REGISTRY_HOST_NAME: schema_registry - # SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: zoo1:2181 - # SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_ORIGIN: "*" - # SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_METHODS: "GET,POST,PUT,OPTIONS" - # SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka1:19092 - # healthcheck: - # start_period: 10s - # interval: 10s - # retries: 20 - # test: curl --user superUser:superUser --fail --silent --insecure http://schema_registry:8085/subjects --output /dev/null || exit 1 - # depends_on: - # kafka1: - # condition: service_healthy - - #Kafka - Init# - kafka_init: - profiles: ["all", "kafka", "starlabs", "kms"] - image: confluentinc/cp-kafka:7.1.2 - container_name: kafka_init - entrypoint: ["/bin/sh", "-c"] - environment: - KAFKA_CREATE_KP_PRODUCER_TOPIC: ${KAFKA_CREATE_KP_PRODUCER_TOPIC:-generateKeypair} - KAFKA_CREATE_KP_CONSUMER_TOPICS: ${KAFKA_CREATE_KP_CONSUMER_TOPICS:-generatedKeypairs} - KAFKA_ENVELOPE_PRODUCER_TOPIC: ${KAFKA_ENVELOPE_PRODUCER_TOPIC:-createEnvelope} - KAFKA_ENVELOPE_CONSUMER_TOPICS: ${KAFKA_ENVELOPE_CONSUMER_TOPICS:-submitResponse} - KAFKA_HORIZON_PRODUCER_TOPIC: ${KAFKA_HORIZON_PRODUCER_TOPIC:-horizonRequest} - KAFKA_HORIZON_CONSUMER_TOPICS: ${KAFKA_HORIZON_CONSUMER_TOPICS:-horizonResponse} - KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS: ${KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS:-signSorobanTransaction} - KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC: ${KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC:-signedSorobanTransaction} - - depends_on: - kafka1: - condition: service_healthy - command: | - " - # blocks until kafka is reachable - kafka-topics --bootstrap-server kafka1:19092 --list - kafka-topics --create --topic $$KAFKA_CREATE_KP_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka-topics --create --topic $$KAFKA_CREATE_KP_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka-topics --create --topic $$KAFKA_ENVELOPE_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka-topics --create --topic $$KAFKA_ENVELOPE_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka-topics --create --topic $$KAFKA_HORIZON_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka-topics --create --topic $$KAFKA_HORIZON_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka-topics --create --topic $$KAFKA_SIGN_SOROBAN_TRANSACTION_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka-topics --create --topic $$KAFKA_SIGN_SOROBAN_TRANSACTION_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 - kafka1 cub kafka-ready -b kafka1:129092 1 20 - " - - # Kafka - UI# - kafka_ui: - profiles: ["all", "kafka", "starlabs", "kms"] - image: provectuslabs/kafka-ui - container_name: kafka_ui - ports: - - "9093:9093" - environment: - SERVER_PORT: 9093 - KAFKA_CLUSTERS_0_NAME: local - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka1:19092 - KAFKA_CLUSTERS_0_ZOOKEEPER: zoo1:2181 - AUTH_TYPE: "LOGIN_FORM" - SPRING_SECURITY_USER_NAME: admin - SPRING_SECURITY_USER_PASSWORD: admin - depends_on: - kafka1: - condition: service_healthy - - #Starlabs Service# - starlabs: - platform: linux/amd64 - profiles: ["all", "starlabs", "tests"] - container_name: starlabs - build: - context: ./starlabs - dockerfile: dev.Dockerfile - volumes: - - ".:/workspace" - environment: - KAFKA_ENABLED: ${KAFKA_ENABLED:-True} - KAFKA_CLIENT_GROUP_ID: ${KAFKA_CLIENT_GROUP_ID:-starlabs} - KAFKA_CLIENT_BROKERS: ${KAFKA_CLIENT_BROKERS:-kafka1:19092} - KAFKA_HORIZON_CONSUMER_TOPICS: ${KAFKA_CONSUMER_TOPICS:-horizonRequest} - KAFKA_HORIZON_PRODUCER_TOPIC: ${KAFKA_PRODUCER_TOPIC:-horizonResponse} - KAFKA_ENVELOPE_CONSUMER_TOPICS: ${KAFKA_ENVELOPE_CONSUMER_TOPICS:-createEnvelope} - KAFKA_ENVELOPE_PRODUCER_TOPIC: ${KAFKA_ENVELOPE_PRODUCER_TOPIC:-signEnvelope} - KAFKA_SUBMIT_CONSUMER_TOPICS: ${KAFKA_SUBMIT_CONSUMER_TOPICS:-signedEnvelopes} - KAFKA_SUBMIT_PRODUCER_TOPIC: ${KAFKA_SUBMIT_PRODUCER_TOPIC:-submitResponse} - depends_on: - kafka1: - condition: service_healthy - - integration: - profiles: ["tests"] - platform: linux/amd64 - build: - context: ./backend - dockerfile: integration-test/Dockerfile - container_name: integration - image: integration - depends_on: - - backend - - stellar-kms - - starlabs - -volumes: - postgres: - node_modules_tfv2_frontend: From a22138e67a9d37044025d1b54243ff4840b1e112 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 21 Nov 2023 11:03:19 -0300 Subject: [PATCH 14/52] Add forget password endpoint --- backend/go.mod | 26 +++++---- backend/go.sum | 50 +++++++++-------- backend/internal/controller/http/v1/users.go | 13 ++++- .../internal/usecase/users/reset_password.go | 7 +++ backend/pkg/email/aws_ses_service.go | 55 +++++++++++++++++++ 5 files changed, 116 insertions(+), 35 deletions(-) create mode 100644 backend/internal/usecase/users/reset_password.go create mode 100644 backend/pkg/email/aws_ses_service.go diff --git a/backend/go.mod b/backend/go.mod index fc8ea869..07834066 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -5,17 +5,17 @@ go 1.19 require ( github.com/confluentinc/confluent-kafka-go v1.9.2 github.com/dgrijalva/jwt-go v3.2.0+incompatible - github.com/gin-gonic/gin v1.9.0 + github.com/gin-gonic/gin v1.9.1 github.com/golang-migrate/migrate/v4 v4.15.2 github.com/golang/mock v1.6.0 github.com/ilyakaznacheev/cleanenv v1.4.2 github.com/joho/godotenv v1.5.1 github.com/lib/pq v1.10.7 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.1 - golang.org/x/crypto v0.8.0 + golang.org/x/crypto v0.14.0 ) require ( @@ -23,9 +23,10 @@ require ( github.com/Eun/go-doppelgangerreader v0.0.0-20190911075941-30f1527f16b2 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 // indirect - github.com/bytedance/sonic v1.8.7 // indirect + github.com/bytedance/sonic v1.9.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -33,7 +34,7 @@ require ( github.com/go-openapi/swag v0.22.3 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.12.0 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/google/go-cmp v0.5.6 // indirect github.com/gookit/color v1.4.2 // indirect @@ -43,30 +44,30 @@ require ( github.com/invopop/jsonschema v0.4.0 // indirect github.com/itchyny/gojq v0.12.5 // indirect github.com/itchyny/timefmt-go v0.1.3 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/k0kubun/pp v3.0.1+incompatible // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect - github.com/leodido/go-urn v1.2.3 // indirect + github.com/leodido/go-urn v1.2.4 // indirect github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.7 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.0.7 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect go.uber.org/atomic v1.7.0 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/tools v0.8.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/protobuf v1.30.0 // indirect @@ -75,6 +76,7 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/Eun/go-hit v0.5.23 + github.com/aws/aws-sdk-go v1.48.0 github.com/bitly/go-notify v0.0.0-20130217044602-0a148b8111d6 gopkg.in/yaml.v3 v3.0.1 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect diff --git a/backend/go.sum b/backend/go.sum index a8243e5d..38af4724 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -148,6 +148,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.48.0 h1:1SeJ8agckRDQvnSCt1dGZYAwUaoD2Ixj6IaXB4LCv8Q= +github.com/aws/aws-sdk-go v1.48.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU= @@ -198,8 +200,8 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.8.7 h1:d3sry5vGgVq/OpgozRUNP6xBsSo0mtNdwliApw+SAMQ= -github.com/bytedance/sonic v1.8.7/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -443,6 +445,8 @@ github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0 github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +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/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -450,8 +454,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= 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.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= -github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= +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-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= @@ -504,8 +508,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 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.12.0 h1:E4gtWgxWxp8YSxExrQFv5BpCahla0PVF2oTTEYaWQGI= -github.com/go-playground/validator/v10 v10.12.0/go.mod h1:hCAPuzYvKdP33pxWa+2+6AIKXEKqjIUyqsNCtbsSJrA= +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.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -787,7 +791,9 @@ github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/ github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= @@ -854,8 +860,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4= -github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA= -github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +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/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -900,8 +906,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/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -1020,8 +1026,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= -github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +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/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= @@ -1145,7 +1151,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 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 v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -1158,8 +1163,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= @@ -1307,8 +1313,8 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1428,8 +1434,8 @@ golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1587,8 +1593,8 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc 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.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1605,8 +1611,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -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/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= diff --git a/backend/internal/controller/http/v1/users.go b/backend/internal/controller/http/v1/users.go index 689260b7..a7d8ff99 100644 --- a/backend/internal/controller/http/v1/users.go +++ b/backend/internal/controller/http/v1/users.go @@ -25,6 +25,7 @@ func newUserRoutes(handler *gin.RouterGroup, t usecase.UserUseCase, a usecase.Au h.POST("/create", r.createUser) h.POST("/login", r.autentication) h.POST("/logout", r.logout) + h.POST("/forget-password", r.forgetPassword) secured := h.Group("/").Use(Auth(a.ValidateToken())) { @@ -220,7 +221,6 @@ func (r *usersRoutes) editUsersRole(c *gin.Context) { func (r *usersRoutes) getProfile(c *gin.Context) { token := c.GetHeader("Authorization") profile, err := r.t.GetProfile(token) - if err != nil { // r.l.Error(err, "http - v1 - history") // errorResponse(c, http.StatusInternalServerError, "database problems") @@ -230,3 +230,14 @@ func (r *usersRoutes) getProfile(c *gin.Context) { c.JSON(http.StatusOK, profile) } + +// @Summary Forget Password +// @Description Forget Password +// @Schemes +// @Tags user +// @Accept json +// @Produce json +// @Success 200 {object} entity. +// @Router /users [get] +func (r *usersRoutes) forgetPassword(c *gin.Context) { +} diff --git a/backend/internal/usecase/users/reset_password.go b/backend/internal/usecase/users/reset_password.go new file mode 100644 index 00000000..20ba1205 --- /dev/null +++ b/backend/internal/usecase/users/reset_password.go @@ -0,0 +1,7 @@ +package usecase + +func (uc *UserUseCase) Execute(email string) error { + // Generate reset token and save it in the database + // Call the email service to send the reset link + return nil +} diff --git a/backend/pkg/email/aws_ses_service.go b/backend/pkg/email/aws_ses_service.go new file mode 100644 index 00000000..d0ad512c --- /dev/null +++ b/backend/pkg/email/aws_ses_service.go @@ -0,0 +1,55 @@ +package email + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ses" +) + +type AwsSesService struct { + client *ses.SES +} + +func NewAwsSesService() *AwsSesService { + sess := session.Must(session.NewSession(&aws.Config{ + Region: aws.String("YOUR_AWS_REGION"), // TODO: Change this + Credentials: credentials.NewStaticCredentials("YOUR_AWS_ACCESS_KEY_ID", "YOUR_AWS_SECRET_ACCESS_KEY", ""), // TODO: Change this + })) + + return &AwsSesService{ + client: ses.New(sess), + } +} + +func (s *AwsSesService) SendEmail(to, subject, body string) error { + input := &ses.SendEmailInput{ + Destination: &ses.Destination{ + ToAddresses: []*string{ + aws.String(to), + }, + }, + Message: &ses.Message{ + Body: &ses.Body{ + Html: &ses.Content{ + Charset: aws.String("UTF-8"), + Data: aws.String(body), + }, + }, + Subject: &ses.Content{ + Charset: aws.String("UTF-8"), + Data: aws.String(subject), + }, + }, + Source: aws.String("your-email@example.com"), // TODO: Change this + } + + _, err := s.client.SendEmail(input) + if err != nil { + return fmt.Errorf("failed to send email: %v", err) + } + + return nil +} From 166cfbdfb1989e71f3c0df3e22827aefbeb96eb4 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 21 Nov 2023 11:46:46 -0300 Subject: [PATCH 15/52] Add hash field to Message struct --- backend/internal/entity/message.go | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/internal/entity/message.go b/backend/internal/entity/message.go index eb3d44df..d872ea8f 100644 --- a/backend/internal/entity/message.go +++ b/backend/internal/entity/message.go @@ -80,6 +80,7 @@ type ( Id int `json:"id"` Envelope string `json:"envelope"` PublicKeys []string `json:"publicKeys"` + Hash string `json:"hash"` } SorobanTransactionResponse struct { From e09dfcf1e8341688c5121965e4d03e012b83fe29 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 21 Nov 2023 11:52:11 -0300 Subject: [PATCH 16/52] Add new envs --- dev.docker-compose.yml | 254 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 dev.docker-compose.yml diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml new file mode 100644 index 00000000..ccb232ac --- /dev/null +++ b/dev.docker-compose.yml @@ -0,0 +1,254 @@ +version: "3.7" + +services: + postgres: + container_name: postgres + profiles: [ "all", "starlabs", "tests", "kafka" ] + image: postgres + environment: + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password} + POSTGRES_DB: ${POSTGRES_DB:-postgres} + PGDATA: /data/postgres + volumes: + - postgres:/data/postgres + ports: + - "5432:5432" + restart: unless-stopped + healthcheck: + test: + [ + "CMD-SHELL", + "sh -c 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}'" + ] + interval: 10s + timeout: 3s + retries: 3 + + tfv2_frontend: + profiles: [ "all", "frontend" ] + container_name: tfv2_frontend + build: + context: ./frontend + target: local + args: + REACT_APP_API_URL: ${FRONTEND_REACT_APP_API_URL:-http://localhost:8080} + REACT_APP_SENTRY_DSN: ${SENTRY_DSN:-https://examplePublicKey@o0.ingest.sentry.io/0} + environment: + REACT_APP_API_URL: ${FRONTEND_REACT_APP_API_URL:-http://localhost:8080} + REACT_APP_SENTRY_DSN: ${SENTRY_DSN:-https://examplePublicKey@o0.ingest.sentry.io/0} + volumes: + - ./frontend/:/app + - node_modules_tfv2_frontend:/app/node_modules + ports: + - 3000:3000 + + backend: + platform: linux/amd64 + profiles: [ "all", "tests" ] + container_name: token-factory-v2 + build: + context: ./backend + dockerfile: dev.Dockerfile + image: mullberry-backend + ports: + - "8080:8080" + volumes: + - ./:/go/src/CheesecakeLabs/token-factory-v2/backend + depends_on: + postgres: + condition: service_healthy + + stellar-kms: + platform: linux/amd64 + profiles: [ "all", "starlabs", "tests" ] + container_name: kms + build: + context: ./stellar-kms + dockerfile: dev.Dockerfile + volumes: + - ".:/workspace" + environment: + KAFKA_ENABLED: ${KAFKA_ENABLED:-True} + KAFKA_CLIENT_GROUP_ID: ${KAFKA_CLIENT_GROUP_ID:-starlabs} + KAFKA_CLIENT_BROKERS: ${KAFKA_CLIENT_BROKERS:-kafka1:19092} + KAFKA_CREATE_KP_CONSUMER_TOPICS: ${KMS_KAFKA_CONSUMER_TOPICS:-generateKeypair} + KAFKA_CREATE_KP_PRODUCER_TOPIC: ${KMS_KAFKA_PRODUCER_TOPIC:-generatedKeypairs} + KAFKA_SIGN_CONSUMER_TOPICS: ${KAFKA_SIGN_CONSUMER_TOPICS:-signEnvelope} + KAFKA_SIGN_PRODUCER_TOPIC: ${KAFKA_SIGN_PRODUCER_TOPIC:-signedEnvelopes} + KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS: ${KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS:-signSorobanEnvelope} + KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC: ${KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC:-signedSorobanEnvelopes} + PG_HOST: ${PG_HOST:-postgres} + PG_PORT: ${PG_PORT:-5432} + PG_USER: ${PG_USER:-postgres} + PG_PASSWORD: ${PG_PASSWORD:-password} + PG_DB_NAME: ${PG_DATABASE:-postgres} + MASTER_KEY: ${MASTER_KEY:-da52f130e6fd477256b0c554aba89503} + LOG_LEVEL: ${LOG_LEVEL:-debug} + depends_on: + postgres: + condition: service_healthy + kafka1: + condition: service_healthy + + zoo1: + profiles: [ "all", "starlabs", "tests", "kafka" ] + image: confluentinc/cp-zookeeper:7.3.2 + hostname: zoo1 + container_name: zoo1 + ports: + - "2181:2181" + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_SERVER_ID: 1 + ZOOKEEPER_SERVERS: zoo1:2888:3888 + + kafka1: + profiles: [ "all", "starlabs", "tests", "kafka" ] + image: confluentinc/cp-kafka:7.3.2 + hostname: kafka1 + container_name: kafka1 + ports: + - "9092:9092" + - "29092:29092" + - "9999:9999" + environment: + KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL + KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181" + KAFKA_BROKER_ID: 1 + KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 + KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 + KAFKA_JMX_PORT: 9999 + KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1} + KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer + KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true" + depends_on: + - zoo1 + healthcheck: + test: nc -z kafka1 19092 || exit -1 + start_period: 30s + interval: 10s + timeout: 10s + retries: 20 + + #Kafka - Schema Registry# + schema_registry: + profiles: [ "all", "kafka", "starlabs", "kms" ] + image: confluentinc/cp-schema-registry:7.1.2 + container_name: schema_registry + ports: + - "8085:8085" + environment: + SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8085 + SCHEMA_REGISTRY_HOST_NAME: schema_registry + SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: zoo1:2181 + SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_ORIGIN: "*" + SCHEMA_REGISTRY_ACCESS_CONTROL_ALLOW_METHODS: "GET,POST,PUT,OPTIONS" + SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka1:19092 + healthcheck: + start_period: 10s + interval: 10s + retries: 20 + test: curl --user superUser:superUser --fail --silent --insecure http://schema_registry:8085/subjects --output /dev/null || exit 1 + depends_on: + kafka1: + condition: service_healthy + + #Kafka - Init# + kafka_init: + profiles: [ "all", "kafka", "starlabs", "kms" ] + image: confluentinc/cp-kafka:7.1.2 + container_name: kafka_init + entrypoint: [ "/bin/sh", "-c" ] + environment: + KAFKA_CREATE_KP_PRODUCER_TOPIC: ${KAFKA_CREATE_KP_PRODUCER_TOPIC:-generateKeypair} + KAFKA_CREATE_KP_CONSUMER_TOPICS: ${KAFKA_CREATE_KP_CONSUMER_TOPICS:-generatedKeypairs} + KAFKA_ENVELOPE_PRODUCER_TOPIC: ${KAFKA_ENVELOPE_PRODUCER_TOPIC:-createEnvelope} + KAFKA_ENVELOPE_CONSUMER_TOPICS: ${KAFKA_ENVELOPE_CONSUMER_TOPICS:-submitResponse} + KAFKA_HORIZON_PRODUCER_TOPIC: ${KAFKA_HORIZON_PRODUCER_TOPIC:-horizonRequest} + KAFKA_HORIZON_CONSUMER_TOPICS: ${KAFKA_HORIZON_CONSUMER_TOPICS:-horizonResponse} + SIGNED_SOROBAN_PRODUCER_TOPIC: ${KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC:-signSorobanEnvelope} + SIGNED_SOROBAN_CONSUMER_TOPICS: ${KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS:-signedSorobanEnvelopes} + depends_on: + kafka1: + condition: service_healthy + command: | + " + # blocks until kafka is reachable + kafka-topics --bootstrap-server kafka1:19092 --list + kafka-topics --create --topic $$KAFKA_CREATE_KP_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$KAFKA_CREATE_KP_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$KAFKA_ENVELOPE_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$KAFKA_ENVELOPE_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$KAFKA_HORIZON_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$KAFKA_HORIZON_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$SIGNED_SOROBAN_PRODUCER_TOPIC --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka-topics --create --topic $$SIGNED_SOROBAN_CONSUMER_TOPICS --partitions 1 --replication-factor 1 --if-not-exists --bootstrap-server kafka1:19092 + kafka1 cub kafka-ready -b kafka1:129092 1 20 + " + + # Kafka - UI# + kafka_ui: + profiles: [ "all", "kafka", "starlabs", "kms" ] + image: provectuslabs/kafka-ui + container_name: kafka_ui + ports: + - "9093:9093" + environment: + SERVER_PORT: 9093 + KAFKA_CLUSTERS_0_NAME: local + KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka1:19092 + KAFKA_CLUSTERS_0_ZOOKEEPER: zoo1:2181 + AUTH_TYPE: "LOGIN_FORM" + SPRING_SECURITY_USER_NAME: admin + SPRING_SECURITY_USER_PASSWORD: admin + depends_on: + kafka1: + condition: service_healthy + + #Starlabs Service# + starlabs: + platform: linux/amd64 + profiles: [ "all", "starlabs", "tests" ] + container_name: starlabs + build: + context: ./starlabs + dockerfile: dev.Dockerfile + volumes: + - ".:/workspace" + environment: + KAFKA_ENABLED: ${KAFKA_ENABLED:-True} + KAFKA_CLIENT_GROUP_ID: ${KAFKA_CLIENT_GROUP_ID:-starlabs} + KAFKA_CLIENT_BROKERS: ${KAFKA_CLIENT_BROKERS:-kafka1:19092} + KAFKA_HORIZON_CONSUMER_TOPICS: ${KAFKA_CONSUMER_TOPICS:-horizonRequest} + KAFKA_HORIZON_PRODUCER_TOPIC: ${KAFKA_PRODUCER_TOPIC:-horizonResponse} + KAFKA_ENVELOPE_CONSUMER_TOPICS: ${KAFKA_ENVELOPE_CONSUMER_TOPICS:-createEnvelope} + KAFKA_ENVELOPE_PRODUCER_TOPIC: ${KAFKA_ENVELOPE_PRODUCER_TOPIC:-signEnvelope} + KAFKA_SUBMIT_CONSUMER_TOPICS: ${KAFKA_SUBMIT_CONSUMER_TOPICS:-signedEnvelopes} + KAFKA_SUBMIT_PRODUCER_TOPIC: ${KAFKA_SUBMIT_PRODUCER_TOPIC:-submitResponse} + LOG_LEVEL: ${LOG_LEVEL:-debug} + + depends_on: + kafka1: + condition: service_healthy + + integration: + profiles: [ "tests" ] + platform: linux/amd64 + build: + context: ./backend + dockerfile: integration-test/Dockerfile + container_name: integration + image: integration + depends_on: + - backend + - stellar-kms + - starlabs + +volumes: + postgres: + node_modules_tfv2_frontend: From c7013c2cafa2d5f139e535f7863d53acfd9256a6 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 21 Nov 2023 11:52:51 -0300 Subject: [PATCH 17/52] Fix Kafka topic variable names --- dev.docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml index ccb232ac..e07d5704 100644 --- a/dev.docker-compose.yml +++ b/dev.docker-compose.yml @@ -171,8 +171,8 @@ services: KAFKA_ENVELOPE_CONSUMER_TOPICS: ${KAFKA_ENVELOPE_CONSUMER_TOPICS:-submitResponse} KAFKA_HORIZON_PRODUCER_TOPIC: ${KAFKA_HORIZON_PRODUCER_TOPIC:-horizonRequest} KAFKA_HORIZON_CONSUMER_TOPICS: ${KAFKA_HORIZON_CONSUMER_TOPICS:-horizonResponse} - SIGNED_SOROBAN_PRODUCER_TOPIC: ${KAFKA_SIGN_SOROBAN_PRODUCER_TOPIC:-signSorobanEnvelope} - SIGNED_SOROBAN_CONSUMER_TOPICS: ${KAFKA_SIGN_SOROBAN_CONSUMER_TOPICS:-signedSorobanEnvelopes} + SIGNED_SOROBAN_PRODUCER_TOPIC: ${SIGNED_SOROBAN_PRODUCER_TOPIC:-signSorobanEnvelope} + SIGNED_SOROBAN_CONSUMER_TOPICS: ${SIGNED_SOROBAN_CONSUMER_TOPICS:-signedSorobanEnvelopes} depends_on: kafka1: condition: service_healthy From b283cb704d94624e7855abced957c1cfaccc73d9 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 21 Nov 2023 11:54:43 -0300 Subject: [PATCH 18/52] Update dependencies in go.mod and go.sum --- backend/go.mod | 7 +++---- backend/go.sum | 16 ++++++---------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/backend/go.mod b/backend/go.mod index 0ed37181..4ab81fe2 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -16,7 +16,7 @@ require ( github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.1 - golang.org/x/crypto v0.11.0 + golang.org/x/crypto v0.15.0 ) require ( @@ -66,8 +66,8 @@ require ( go.uber.org/atomic v1.11.0 // indirect golang.org/x/arch v0.4.0 // indirect golang.org/x/net v0.12.0 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/protobuf v1.31.0 // indirect @@ -77,7 +77,6 @@ require ( github.com/BurntSushi/toml v1.3.2 // indirect github.com/Eun/go-hit v0.5.23 github.com/bitly/go-notify v0.0.0-20130217044602-0a148b8111d6 - github.com/gin-gonic/contrib v0.0.0-20221130124618-7e01895a63f2 gopkg.in/yaml.v3 v3.0.1 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 23d8611b..d1c50f62 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -19,8 +19,6 @@ github.com/Eun/yaegi-template v1.5.18/go.mod h1:iVHjge496SWL7hLf1euBZIO40Bk0R38g github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/aaw/maybe_tls v0.0.0-20160803104303-89c499bcc6aa h1:6yJyU8MlPBB2enGJdPciPlr8P+PC0nhCFHnSHYMirZI= github.com/aaw/maybe_tls v0.0.0-20160803104303-89c499bcc6aa/go.mod h1:I0wzMZvViQzmJjxK+AtfFAnqDCkQV/+r17PO1CCSYnU= github.com/actgardner/gogen-avro/v10 v10.1.0/go.mod h1:o+ybmVjEa27AAr35FRqU98DJu1fXES56uXniYFv4yDA= @@ -87,8 +85,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= 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/contrib v0.0.0-20221130124618-7e01895a63f2 h1:dyuNlYlG1faymw39NdJddnzJICy6587tiGSVioWhYoE= -github.com/gin-gonic/contrib v0.0.0-20221130124618-7e01895a63f2/go.mod h1:iqneQ2Df3omzIVTkIfn7c1acsVnMGiSLn4XF5Blh3Yg= 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-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -321,8 +317,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -383,8 +379,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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= @@ -395,8 +391,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 2403561e65cf55cc9b5cfa3b931db4483b50b508 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 21 Nov 2023 11:56:45 -0300 Subject: [PATCH 19/52] Add .DS_Store to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e43b0f98 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store From 56e3881239f7da007ff158b795712c0b4f203f51 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 27 Nov 2023 15:52:42 -0300 Subject: [PATCH 20/52] feat: personal vault --- backend/internal/controller/http/v1/assets.go | 32 +++++++++++++++++++ .../internal/controller/http/v1/contracts.go | 2 +- backend/internal/controller/http/v1/router.go | 2 +- backend/internal/controller/http/v1/users.go | 16 ++++++++-- backend/internal/controller/http/v1/vault.go | 28 ++++++++++++---- backend/internal/entity/asset.go | 17 +++++----- backend/internal/entity/users.go | 2 ++ backend/internal/entity/vault.go | 12 ++++--- backend/internal/usecase/assets.go | 8 +++++ backend/internal/usecase/interfaces.go | 1 + .../internal/usecase/repo/asset_postgres.go | 27 ++++++++++++---- .../usecase/repo/contract_postgres.go | 4 +-- .../internal/usecase/repo/user_postgres.go | 5 +-- .../internal/usecase/repo/vault_postgres.go | 32 ++++++++++++------- .../000031_add_vault_owner.down.sql | 1 + .../migrations/000031_add_vault_owner.up.sql | 5 +++ .../000032_vault_catogory_null.up.sql | 2 ++ starlabs | 2 +- stellar-kms | 2 +- 19 files changed, 153 insertions(+), 47 deletions(-) create mode 100644 backend/migrations/000031_add_vault_owner.down.sql create mode 100644 backend/migrations/000031_add_vault_owner.up.sql create mode 100644 backend/migrations/000032_vault_catogory_null.up.sql diff --git a/backend/internal/controller/http/v1/assets.go b/backend/internal/controller/http/v1/assets.go index 652762be..aa4eda4f 100644 --- a/backend/internal/controller/http/v1/assets.go +++ b/backend/internal/controller/http/v1/assets.go @@ -51,6 +51,7 @@ func newAssetsRoutes(handler *gin.RouterGroup, w usecase.WalletUseCase, as useca h.POST("/generate-toml", r.generateTOML) h.PUT("/update-toml", r.updateTOML) h.GET("/toml-data", r.getTomlData) + h.PUT("/:id/update-contract-id", r.updateContractId) } } @@ -114,6 +115,10 @@ type UploadAssetImageRequest struct { Image string `json:"image" example:"iVBORw0KGgoAAAANSUhEUgAACqoAAAMMCAMAAAAWqpRaAAADAFBMVEX///..."` } +type UpdateContractIdRequest struct { + ContractId string `json:"contract_id" example:"iVBORw0KGgoAAAANSUhEUgAACqoAAAMMCAMAAAAWqpRaAAADAFBMVEX///..."` +} + // @Summary Create a new asset // @Description Create and issue a new asset on Stellar // @Tags Assets @@ -953,3 +958,30 @@ func (r *assetsRoutes) getTomlData(c *gin.Context) { c.JSON(http.StatusOK, tomlContent) } + +// @Summary Update a Contract ID +// @Description Update a Contract ID +// @Tags Assets +// @Accept json +// @Produce json +// @Param request body entity.UpdateContractIdRequest true "Contract ID" +// @Success 200 {object} entity.UpdateContractIdRequest +// @Failure 400 {object} response +// @Failure 500 {object} response +// @Router /assets/update-contract-id [put] +func (r *assetsRoutes) updateContractId(c *gin.Context) { + var request UpdateContractIdRequest + if err := c.ShouldBindJSON(&request); err != nil { + errorResponse(c, http.StatusBadRequest, "invalid request body", err) + return + } + + assetId := c.Param("id") + err := r.as.UpdateContractId(assetId, request.ContractId) + if err != nil { + errorResponse(c, http.StatusInternalServerError, "error updating Contract ID", err) + return + } + + c.JSON(http.StatusOK, gin.H{"contract_id": request.ContractId}) +} diff --git a/backend/internal/controller/http/v1/contracts.go b/backend/internal/controller/http/v1/contracts.go index a2aa0158..948901c0 100644 --- a/backend/internal/controller/http/v1/contracts.go +++ b/backend/internal/controller/http/v1/contracts.go @@ -39,7 +39,7 @@ type CreateContractRequest struct { Term int `json:"term" binding:"required" example:"60"` MinDeposit int `json:"min_deposit" binding:"required" example:"1"` PenaltyRate int `json:"penalty_rate" binding:"required" example:"1"` - Compound int `json:"compound" binding:"required" example:"60"` + Compound int `json:"compound" example:"1"` } // @Summary Create a new contract diff --git a/backend/internal/controller/http/v1/router.go b/backend/internal/controller/http/v1/router.go index f378b479..39d6cabe 100644 --- a/backend/internal/controller/http/v1/router.go +++ b/backend/internal/controller/http/v1/router.go @@ -77,7 +77,7 @@ func NewRouter( handler.Use(CORSMiddleware(cfg)) // Alow only frontend origin groupV1 := handler.Group("/v1") { - newUserRoutes(groupV1, userUseCase, authUseCase, rolePermissionUc) + newUserRoutes(groupV1, userUseCase, authUseCase, rolePermissionUc, vaultUc) newWalletsRoutes(groupV1, walletUseCase, messengerController, authUseCase) newAssetsRoutes(groupV1, walletUseCase, assetUseCase, messengerController, authUseCase, logUc) newRoleRoutes(groupV1, roleUseCase, messengerController) diff --git a/backend/internal/controller/http/v1/users.go b/backend/internal/controller/http/v1/users.go index fb4540f8..d7a170ba 100644 --- a/backend/internal/controller/http/v1/users.go +++ b/backend/internal/controller/http/v1/users.go @@ -14,11 +14,13 @@ type usersRoutes struct { t usecase.UserUseCase a usecase.AuthUseCase rP usecase.RolePermissionUseCase + v usecase.VaultUseCase // l logger.Interface } -func newUserRoutes(handler *gin.RouterGroup, t usecase.UserUseCase, a usecase.AuthUseCase, rP usecase.RolePermissionUseCase) { - r := &usersRoutes{t, a, rP} +func newUserRoutes(handler *gin.RouterGroup, t usecase.UserUseCase, a usecase.AuthUseCase, rP usecase.RolePermissionUseCase, + v usecase.VaultUseCase) { + r := &usersRoutes{t, a, rP, v} h := handler.Group("/users") { @@ -228,5 +230,15 @@ func (r *usersRoutes) getProfile(c *gin.Context) { return } + if profile.VaultId != nil { + vault, err := r.v.GetById(*profile.VaultId) + if err != nil { + fmt.Println(err) + return + } + + profile.Vault = &vault + } + c.JSON(http.StatusOK, profile) } diff --git a/backend/internal/controller/http/v1/vault.go b/backend/internal/controller/http/v1/vault.go index 9129f43a..8620616d 100644 --- a/backend/internal/controller/http/v1/vault.go +++ b/backend/internal/controller/http/v1/vault.go @@ -36,8 +36,9 @@ func newVaultRoutes(handler *gin.RouterGroup, m HTTPControllerMessenger, a useca type CreateVaultRequest struct { Name string `json:"name" binding:"required" example:"Treasury"` - VaultCategoryId int `json:"vault_category_id" binding:"required" example:"1"` + VaultCategoryId *int `json:"vault_category_id" example:"1"` AssetsId []int `json:"assets_id" binding:"required"` + OwnerId *int `json:"owner_id"` } type UpdateVaultCategoryRequest struct { @@ -72,10 +73,14 @@ func (r *vaultRoutes) createVault(c *gin.Context) { return } - vaultCategory, err := r.vc.GetById(request.VaultCategoryId) - if err != nil { - errorResponse(c, http.StatusNotFound, "source wallet not found", err) - return + var vaultCategory entity.VaultCategory + + if request.VaultCategoryId != nil { + vaultCategory, err = r.vc.GetById(*request.VaultCategoryId) + if err != nil { + errorResponse(c, http.StatusNotFound, "source wallet not found", err) + return + } } sponsorID := _sponsorId @@ -153,8 +158,9 @@ func (r *vaultRoutes) createVault(c *gin.Context) { vault := entity.Vault{ Name: request.Name, - VaultCategory: vaultCategory, + VaultCategory: &vaultCategory, Wallet: wallet, + OwnerId: request.OwnerId, } vault, err = r.v.Create(vault) @@ -206,6 +212,16 @@ func (r *vaultRoutes) getVaultById(c *gin.Context) { return } + if vault.VaultCategoryId != nil { + vaultCategory, err := r.vc.GetById(*vault.VaultCategoryId) + if err != nil { + errorResponse(c, http.StatusInternalServerError, "error getting vault category", err) + return + } + + vault.VaultCategory = &vaultCategory + } + c.JSON(http.StatusOK, vault) } diff --git a/backend/internal/entity/asset.go b/backend/internal/entity/asset.go index 66eb9568..ee2e947a 100644 --- a/backend/internal/entity/asset.go +++ b/backend/internal/entity/asset.go @@ -1,14 +1,15 @@ package entity type Asset struct { - Id int `json:"id" example:"1"` - Name string `json:"name" example:"USD Coin"` - Code string `json:"code" example:"USDC"` - Distributor Wallet `json:"distributor"` - Issuer Wallet `json:"issuer"` - Amount int `json:"amount" example:"1000000"` - AssetType string `json:"asset_type"` - Image []byte `json:"image,omitempty"` + Id int `json:"id" example:"1"` + Name string `json:"name" example:"USD Coin"` + Code string `json:"code" example:"USDC"` + Distributor Wallet `json:"distributor"` + Issuer Wallet `json:"issuer"` + Amount int `json:"amount" example:"1000000"` + AssetType string `json:"asset_type"` + Image []byte `json:"image,omitempty"` + ContractId *string `json:"contract_id,omitempty"` } const ( diff --git a/backend/internal/entity/users.go b/backend/internal/entity/users.go index 18e181cf..e57ac613 100644 --- a/backend/internal/entity/users.go +++ b/backend/internal/entity/users.go @@ -18,6 +18,8 @@ type ( Role string `json:"role" db:"role"` Email string `json:"email" db:"email"` RoleId int `json:"role_id" db:"role_id"` + VaultId *int `json:"vault_id"` + Vault *Vault `json:"vault,omitempty"` } UserRole struct { diff --git a/backend/internal/entity/vault.go b/backend/internal/entity/vault.go index 35bd374b..8dafb358 100644 --- a/backend/internal/entity/vault.go +++ b/backend/internal/entity/vault.go @@ -1,9 +1,11 @@ package entity type Vault struct { - Id int `json:"id" example:"1"` - Name string `json:"name" example:"Treasury"` - Wallet Wallet `json:"wallet"` - VaultCategory VaultCategory `json:"vault_category"` - Active int `json:"active"` + Id int `json:"id" example:"1"` + Name string `json:"name" example:"Treasury"` + Wallet Wallet `json:"wallet"` + VaultCategoryId *int `json:"vault_category_id"` + VaultCategory *VaultCategory `json:"vault_category"` + Active int `json:"active"` + OwnerId *int `json:"owner_id"` } diff --git a/backend/internal/usecase/assets.go b/backend/internal/usecase/assets.go index 6a19d8fa..d0904ac2 100644 --- a/backend/internal/usecase/assets.go +++ b/backend/internal/usecase/assets.go @@ -159,3 +159,11 @@ func (uc *AssetUseCase) GetTomlData() (entity.TomlData, error) { return tomParsed, err } + +func (uc *AssetUseCase) UpdateContractId(assetId string, contractId string) error { + err := uc.aRepo.UpdateContractId(assetId, contractId) + if err != nil { + return fmt.Errorf("AssetUseCase - UpdateContractId - uc.aRepo.UpdateContractId: %w", err) + } + return nil +} diff --git a/backend/internal/usecase/interfaces.go b/backend/internal/usecase/interfaces.go index a3cf1c86..bceb2a73 100644 --- a/backend/internal/usecase/interfaces.go +++ b/backend/internal/usecase/interfaces.go @@ -49,6 +49,7 @@ type ( GetAssetById(string) (entity.Asset, error) StoreAssetImage(string, []byte) error GetAssetImage(string) ([]byte, error) + UpdateContractId(string, string) error } // Role -. diff --git a/backend/internal/usecase/repo/asset_postgres.go b/backend/internal/usecase/repo/asset_postgres.go index ef96f46a..39deec22 100644 --- a/backend/internal/usecase/repo/asset_postgres.go +++ b/backend/internal/usecase/repo/asset_postgres.go @@ -37,7 +37,7 @@ func (r AssetRepo) GetAsset(id int) (entity.Asset, error) { func (r AssetRepo) GetAssets() ([]entity.Asset, error) { query := ` SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, a.image, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, a.image, a.contract_id, d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, @@ -64,7 +64,7 @@ func (r AssetRepo) GetAssets() ([]entity.Asset, error) { var issuer entity.Wallet err := rows.Scan( - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, &asset.ContractId, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -86,7 +86,7 @@ func (r AssetRepo) GetAssets() ([]entity.Asset, error) { func (r AssetRepo) GetAssetByCode(code string) (entity.Asset, error) { query := ` SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type,a.code as asset_code, a.image, + a.id AS asset_id, a.name AS asset_name, a.asset_type,a.code as asset_code, a.image, a.contract_id, d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, @@ -106,7 +106,7 @@ func (r AssetRepo) GetAssetByCode(code string) (entity.Asset, error) { var issuer entity.Wallet err := row.Scan( - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, &asset.ContractId, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -139,7 +139,7 @@ func (r AssetRepo) CreateAsset(data entity.Asset) (entity.Asset, error) { func (r AssetRepo) GetAssetById(id string) (entity.Asset, error) { query := ` SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, a.contract_id, d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, @@ -159,7 +159,7 @@ func (r AssetRepo) GetAssetById(id string) (entity.Asset, error) { var issuer entity.Wallet err := row.Scan( - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, &asset.ContractId, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -210,3 +210,18 @@ func (r AssetRepo) GetAssetImage(assetId string) ([]byte, error) { return image, nil } + +func (r AssetRepo) UpdateContractId(assetId string, contractId string) error { + stmt := ` + UPDATE asset + SET contract_id = $2 + WHERE id = $1 + ` + + _, err := r.Db.Exec(stmt, assetId, contractId) + if err != nil { + return fmt.Errorf("AssetRepo - UpdateContractId - Db.Exec: %w", err) + } + + return nil +} diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index 0bc68683..9a7a35f8 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -77,7 +77,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { } vault.Wallet = wallet - vault.VaultCategory = vaultCategory + vault.VaultCategory = &vaultCategory asset.Distributor = assetDistributor asset.Issuer = assetIssuer contract.Asset = asset @@ -147,7 +147,7 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { } vault.Wallet = wallet - vault.VaultCategory = vaultCategory + vault.VaultCategory = &vaultCategory contract.Asset = asset asset.Distributor = assetDistributor asset.Issuer = assetIssuer diff --git a/backend/internal/usecase/repo/user_postgres.go b/backend/internal/usecase/repo/user_postgres.go index 45a6887a..cae70530 100644 --- a/backend/internal/usecase/repo/user_postgres.go +++ b/backend/internal/usecase/repo/user_postgres.go @@ -132,13 +132,14 @@ func (r UserRepo) EditUsersRole(id_user string, role_id string) error { } func (r UserRepo) GetProfile(token string) (entity.UserResponse, error) { - stmt := `SELECT u.id, u.name, u.updated_at, u.role_id, r.name as role, u.email + stmt := `SELECT u.id, u.name, u.updated_at, u.role_id, r.name as role, u.email, v.id as vault_id FROM UserAccount u LEFT JOIN Role r ON u.role_id = r.id + LEFT JOIN Vault v ON u.id = v.owner_id WHERE u.token = $1` var user entity.UserResponse - err := r.Db.QueryRow(stmt, token).Scan(&user.ID, &user.Name, &user.UpdatedAt, &user.RoleId, &user.Role, &user.Email) + err := r.Db.QueryRow(stmt, token).Scan(&user.ID, &user.Name, &user.UpdatedAt, &user.RoleId, &user.Role, &user.Email, &user.VaultId) if err != nil { return entity.UserResponse{}, fmt.Errorf("UserRepo - GetProfile - db.Query: %w", err) } diff --git a/backend/internal/usecase/repo/vault_postgres.go b/backend/internal/usecase/repo/vault_postgres.go index 7c8ab4a5..f4669ef3 100644 --- a/backend/internal/usecase/repo/vault_postgres.go +++ b/backend/internal/usecase/repo/vault_postgres.go @@ -24,7 +24,7 @@ func (r VaultRepo) GetVaults() ([]entity.Vault, error) { w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight FROM vault v - JOIN vaultcategory vc ON v.vault_category_id = vc.id + LEFT JOIN vaultcategory vc ON v.vault_category_id = vc.id JOIN wallet w ON v.wallet_id = w.id JOIN key wk ON w.id = wk.wallet_id WHERE v.active = 1; @@ -40,12 +40,14 @@ func (r VaultRepo) GetVaults() ([]entity.Vault, error) { for rows.Next() { var vault entity.Vault - var vaultCategory entity.VaultCategory + var vaultCategoryId sql.NullInt64 + var vaultCategoryName sql.NullString + var vaultCategoryTheme sql.NullString var wallet entity.Wallet err := rows.Scan( &vault.Id, &vault.Name, &vault.Active, - &vaultCategory.Id, &vaultCategory.Name, &vaultCategory.Theme, + &vaultCategoryId, &vaultCategoryName, &vaultCategoryTheme, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, ) @@ -54,7 +56,13 @@ func (r VaultRepo) GetVaults() ([]entity.Vault, error) { } vault.Wallet = wallet - vault.VaultCategory = vaultCategory + if vaultCategoryId.Valid { + vault.VaultCategory = &entity.VaultCategory{ + Id: int(vaultCategoryId.Int64), + Name: vaultCategoryName.String, + Theme: &vaultCategoryTheme.String, + } + } vaults = append(vaults, vault) } @@ -66,11 +74,9 @@ func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { query := ` SELECT v.id AS vault_id, v.name AS vault_name, v.active as vault_active, - vc.id AS vault_category_id, vc.name as vault_category_name, vc.theme as vault_category_theme, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight FROM vault v - JOIN vaultcategory vc ON v.vault_category_id = vc.id JOIN wallet w ON v.wallet_id = w.id JOIN key wk ON w.id = wk.wallet_id WHERE v.id = $1; @@ -79,12 +85,10 @@ func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { row := r.Db.QueryRow(query, id) var vault entity.Vault - var vaultCategory entity.VaultCategory var wallet entity.Wallet err := row.Scan( &vault.Id, &vault.Name, &vault.Active, - &vaultCategory.Id, &vaultCategory.Name, &vaultCategory.Theme, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, ) @@ -96,15 +100,19 @@ func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { } vault.Wallet = wallet - vault.VaultCategory = vaultCategory - return vault, nil } func (r VaultRepo) CreateVault(data entity.Vault) (entity.Vault, error) { res := data - stmt := `INSERT INTO Vault (name, vault_category_id, wallet_id) VALUES ($1, $2, $3) RETURNING id;` - err := r.Db.QueryRow(stmt, data.Name, data.VaultCategory.Id, data.Wallet.Id).Scan(&res.Id) + var vaultCategoryId *int + + if data.VaultCategory.Id != 0 { + vaultCategoryId = &data.VaultCategory.Id + } + + stmt := `INSERT INTO Vault (name, vault_category_id, wallet_id, owner_id) VALUES ($1, $2, $3, $4) RETURNING id;` + err := r.Db.QueryRow(stmt, data.Name, vaultCategoryId, data.Wallet.Id, data.OwnerId).Scan(&res.Id) if err != nil { return entity.Vault{}, fmt.Errorf("VaultRepo - Vault - db.QueryRow: %w", err) } diff --git a/backend/migrations/000031_add_vault_owner.down.sql b/backend/migrations/000031_add_vault_owner.down.sql new file mode 100644 index 00000000..e4128470 --- /dev/null +++ b/backend/migrations/000031_add_vault_owner.down.sql @@ -0,0 +1 @@ +ALTER TABLE vault DROP COLUMN owner_id; \ No newline at end of file diff --git a/backend/migrations/000031_add_vault_owner.up.sql b/backend/migrations/000031_add_vault_owner.up.sql new file mode 100644 index 00000000..fc7d5013 --- /dev/null +++ b/backend/migrations/000031_add_vault_owner.up.sql @@ -0,0 +1,5 @@ +ALTER TABLE vault +ADD COLUMN owner_id INT, +ADD CONSTRAINT fk_vault_owner_id + FOREIGN KEY (owner_id) + REFERENCES useraccount(id); \ No newline at end of file diff --git a/backend/migrations/000032_vault_catogory_null.up.sql b/backend/migrations/000032_vault_catogory_null.up.sql new file mode 100644 index 00000000..b201256f --- /dev/null +++ b/backend/migrations/000032_vault_catogory_null.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE Vault +ALTER COLUMN vault_category_id DROP NOT NULL; \ No newline at end of file diff --git a/starlabs b/starlabs index d283a223..4bc84649 160000 --- a/starlabs +++ b/starlabs @@ -1 +1 @@ -Subproject commit d283a2237762a4ef3acc0d4855f81d5d7fe2c866 +Subproject commit 4bc846493861250718fb9378c87abaa96c47c07e diff --git a/stellar-kms b/stellar-kms index 630eba7d..1427b6e2 160000 --- a/stellar-kms +++ b/stellar-kms @@ -1 +1 @@ -Subproject commit 630eba7d3e7ea4083a0c0824153ed64e20f84828 +Subproject commit 1427b6e2082eafeee0c6a0b3d1477268034ac3d0 From 5f32b6dd02e8aa098413555158a95fb9c8a1a03a Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Wed, 29 Nov 2023 17:25:03 -0300 Subject: [PATCH 21/52] feat: vaults public and private --- .idea/.gitignore | 3 +++ .../internal/controller/http/v1/contracts.go | 8 +----- backend/internal/controller/http/v1/router.go | 2 +- backend/internal/controller/http/v1/users.go | 4 +-- backend/internal/controller/http/v1/vault.go | 5 ++-- backend/internal/usecase/interfaces.go | 2 +- .../usecase/repo/contract_postgres.go | 13 ++++----- .../internal/usecase/repo/vault_postgres.go | 27 ++++++++++++------- backend/internal/usecase/vault.go | 4 +-- backend/internal/usecase/vault_test.go | 10 +++---- .../000033_add_contract_created_at.down.sql | 1 + .../000033_add_contract_created_at.up.sql | 2 ++ 12 files changed, 45 insertions(+), 36 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 backend/migrations/000033_add_contract_created_at.down.sql create mode 100644 backend/migrations/000033_add_contract_created_at.up.sql diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..26d33521 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/backend/internal/controller/http/v1/contracts.go b/backend/internal/controller/http/v1/contracts.go index f10bac67..14fe12ea 100644 --- a/backend/internal/controller/http/v1/contracts.go +++ b/backend/internal/controller/http/v1/contracts.go @@ -173,13 +173,7 @@ func (r *contractRoutes) getContractById(c *gin.Context) { contract, err := r.c.GetById(idStr) if err != nil { r.l.Error(err, "http - v1 - get contract by id - Atoi") - errorResponse(c, http.StatusBadRequest, "invalid vault ID", err) - return - } - contract, err := r.v.GetById(vaultId) - if err != nil { - r.l.Error(err, "http - v1 - get contract by id - GetById") - errorResponse(c, http.StatusInternalServerError, "error getting contract", err) + errorResponse(c, http.StatusBadRequest, "invalid contract ID", err) return } diff --git a/backend/internal/controller/http/v1/router.go b/backend/internal/controller/http/v1/router.go index db68623f..ec6799d0 100644 --- a/backend/internal/controller/http/v1/router.go +++ b/backend/internal/controller/http/v1/router.go @@ -85,7 +85,7 @@ func NewRouter( handler.Use(CORSMiddleware(cfg, logger)) groupV1 := handler.Group("/v1") { - newUserRoutes(groupV1, userUseCase, authUseCase, rolePermissionUc, vaultUc, logger) + newUserRoutes(groupV1, userUseCase, authUseCase, rolePermissionUc, logger, vaultUc) newWalletsRoutes(groupV1, walletUseCase, messengerController, authUseCase, logger) newAssetsRoutes(groupV1, walletUseCase, assetUseCase, messengerController, authUseCase, logUc, logger) newRoleRoutes(groupV1, roleUseCase, messengerController, logger) diff --git a/backend/internal/controller/http/v1/users.go b/backend/internal/controller/http/v1/users.go index 18ec2e16..fb775270 100644 --- a/backend/internal/controller/http/v1/users.go +++ b/backend/internal/controller/http/v1/users.go @@ -17,11 +17,11 @@ type usersRoutes struct { rP usecase.RolePermissionUseCase v usecase.VaultUseCase // l logger.Interface - l logger.Interface + l logger.Interface } func newUserRoutes(handler *gin.RouterGroup, t usecase.UserUseCase, a usecase.AuthUseCase, rP usecase.RolePermissionUseCase, l logger.Interface, v usecase.VaultUseCase) { - r := &usersRoutes{t, a, rP, l} + r := &usersRoutes{t, a, rP, v, l} h := handler.Group("/users") { diff --git a/backend/internal/controller/http/v1/vault.go b/backend/internal/controller/http/v1/vault.go index 98897d46..4d081cb0 100644 --- a/backend/internal/controller/http/v1/vault.go +++ b/backend/internal/controller/http/v1/vault.go @@ -81,7 +81,7 @@ func (r *vaultRoutes) createVault(c *gin.Context) { if request.VaultCategoryId != nil { vaultCategory, err = r.vc.GetById(*request.VaultCategoryId) if err != nil { - r.l.Error(err, "http - v1 - create vault - vault category") + r.l.Error(err, "http - v1 - create vault - vault category") errorResponse(c, http.StatusNotFound, "vault category not found", err) return } @@ -199,6 +199,7 @@ func (r *vaultRoutes) createVault(c *gin.Context) { func (r *vaultRoutes) getAllVaults(c *gin.Context) { pageQuery := c.Query("page") limitQuery := c.Query("limit") + isAll := c.Query("all") == "all" // Check if pagination parameters are provided if pageQuery != "" && limitQuery != "" { @@ -226,7 +227,7 @@ func (r *vaultRoutes) getAllVaults(c *gin.Context) { c.JSON(http.StatusOK, vaults) } else { // Get all vaults without pagination - vaults, err := r.v.GetAll() + vaults, err := r.v.GetAll(isAll) if err != nil { r.l.Error(err, "http - v1 - get all vaults - GetAll") errorResponse(c, http.StatusInternalServerError, "error getting all vaults", err) diff --git a/backend/internal/usecase/interfaces.go b/backend/internal/usecase/interfaces.go index 4d783355..4d2ca13f 100644 --- a/backend/internal/usecase/interfaces.go +++ b/backend/internal/usecase/interfaces.go @@ -90,7 +90,7 @@ type ( } VaultRepoInterface interface { - GetVaults() ([]entity.Vault, error) + GetVaults(isAll bool) ([]entity.Vault, error) CreateVault(entity.Vault) (entity.Vault, error) UpdateVault(entity.Vault) (entity.Vault, error) GetVaultById(id int) (entity.Vault, error) diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index b93deafb..dfa49457 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -21,7 +21,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { SELECT c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, c.yield_rate AS contract_yield_rate, c.term AS contract_term, c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, - c.compound AS contract_compound, v.id AS vault_id, v.name AS vault_name, + c.compound AS contract_compound, c.created_at AS contract_created_at, v.id AS vault_id, v.name AS vault_name, vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, @@ -61,7 +61,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { err := rows.Scan( &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, - &contract.PenaltyRate, &contract.Compound, + &contract.PenaltyRate, &contract.Compound, &contract.CreatedAt, &vault.Id, &vault.Name, &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, @@ -94,7 +94,7 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { SELECT c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, c.yield_rate AS contract_yield_rate, c.term AS contract_term, c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, - c.compound AS contract_compound, v.id AS vault_id, v.name AS vault_name, + c.compound AS contract_compound, c.created_at AS contract_created_at, v.id AS vault_id, v.name AS vault_name, vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, @@ -128,7 +128,7 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { err := row.Scan( &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, - &contract.PenaltyRate, &contract.Compound, + &contract.PenaltyRate, &contract.Compound, &contract.CreatedAt, &vault.Id, &vault.Name, &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, @@ -178,6 +178,7 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, c.yield_rate AS contract_yield_rate, c.term AS contract_term, c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, + c.compound AS contract_compound, c.created_at AS contract_created_at, v.id AS vault_id, v.name AS vault_name, vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, @@ -207,7 +208,7 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, err := rows.Scan( &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, - &contract.Term, &contract.MinDeposit, &contract.PenaltyRate, + &contract.Term, &contract.MinDeposit, &contract.PenaltyRate, &contract.Compound, &contract.CreatedAt, &vault.Id, &vault.Name, &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, @@ -218,7 +219,7 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, } vault.Wallet = wallet - vault.VaultCategory = vaultCategory + vault.VaultCategory = &vaultCategory contract.Vault = vault contracts = append(contracts, contract) diff --git a/backend/internal/usecase/repo/vault_postgres.go b/backend/internal/usecase/repo/vault_postgres.go index 7628d0e9..a16c02f8 100644 --- a/backend/internal/usecase/repo/vault_postgres.go +++ b/backend/internal/usecase/repo/vault_postgres.go @@ -16,10 +16,10 @@ func NewVaultRepo(pg *postgres.Postgres) VaultRepo { return VaultRepo{pg} } -func (r VaultRepo) GetVaults() ([]entity.Vault, error) { - query := ` +func (r VaultRepo) GetVaults(isAll bool) ([]entity.Vault, error) { + baseQuery := ` SELECT - v.id AS vault_id, v.name AS vault_name, v.active AS vault_active, + v.id AS vault_id, v.name AS vault_name, v.active AS vault_active, v.owner_id AS owner_id, vc.id AS vault_category_id, vc.name as vault_category_name, vc.theme as vault_category_theme, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight @@ -27,9 +27,16 @@ func (r VaultRepo) GetVaults() ([]entity.Vault, error) { LEFT JOIN vaultcategory vc ON v.vault_category_id = vc.id JOIN wallet w ON v.wallet_id = w.id JOIN key wk ON w.id = wk.wallet_id - WHERE v.active = 1; ` + whereClause := `WHERE v.active = 1` + + if !isAll { + whereClause = whereClause + ` AND v.owner_id is null` + } + + query := baseQuery + whereClause + rows, err := r.Db.Query(query) if err != nil { return nil, fmt.Errorf("VaultRepo - GetVaultCategories - Query: %w", err) @@ -46,7 +53,7 @@ func (r VaultRepo) GetVaults() ([]entity.Vault, error) { var wallet entity.Wallet err := rows.Scan( - &vault.Id, &vault.Name, &vault.Active, + &vault.Id, &vault.Name, &vault.Active, &vault.OwnerId, &vaultCategoryId, &vaultCategoryName, &vaultCategoryTheme, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, @@ -73,7 +80,7 @@ func (r VaultRepo) GetVaults() ([]entity.Vault, error) { func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { query := ` SELECT - v.id AS vault_id, v.name AS vault_name, v.active as vault_active, + v.id AS vault_id, v.name AS vault_name, v.active as vault_active, v.owner_id AS owner_id, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight FROM vault v @@ -88,7 +95,7 @@ func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { var wallet entity.Wallet err := row.Scan( - &vault.Id, &vault.Name, &vault.Active, + &vault.Id, &vault.Name, &vault.Active, &vault.OwnerId, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, ) @@ -153,7 +160,7 @@ func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { query := ` SELECT - v.id AS vault_id, v.name AS vault_name, v.active AS vault_active, + v.id AS vault_id, v.name AS vault_name, v.active AS vault_active, v.owner_id AS owner_id, vc.id AS vault_category_id, vc.name as vault_category_name, vc.theme as vault_category_theme, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight @@ -180,7 +187,7 @@ func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { var wallet entity.Wallet err := rows.Scan( - &vault.Id, &vault.Name, &vault.Active, + &vault.Id, &vault.Name, &vault.Active, &vault.OwnerId, &vaultCategory.Id, &vaultCategory.Name, &vaultCategory.Theme, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, @@ -190,7 +197,7 @@ func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { } vault.Wallet = wallet - vault.VaultCategory = vaultCategory + vault.VaultCategory = &vaultCategory vaults = append(vaults, vault) } diff --git a/backend/internal/usecase/vault.go b/backend/internal/usecase/vault.go index da68e554..3c3b39c3 100644 --- a/backend/internal/usecase/vault.go +++ b/backend/internal/usecase/vault.go @@ -33,8 +33,8 @@ func (uc *VaultUseCase) Create(data entity.Vault) (entity.Vault, error) { return vault, nil } -func (uc *VaultUseCase) GetAll() ([]entity.Vault, error) { - vault, err := uc.vRepo.GetVaults() +func (uc *VaultUseCase) GetAll(isAll bool) ([]entity.Vault, error) { + vault, err := uc.vRepo.GetVaults(isAll) if err != nil { return nil, fmt.Errorf("VaultUseCase - GetAll - uc.repo.GetVault: %w", err) } diff --git a/backend/internal/usecase/vault_test.go b/backend/internal/usecase/vault_test.go index 6d6644aa..d5ab0a61 100644 --- a/backend/internal/usecase/vault_test.go +++ b/backend/internal/usecase/vault_test.go @@ -45,7 +45,7 @@ func TestVaultUseCaseList(t *testing.T) { Wallet: entity.Wallet{ Type: entity.SponsorType, }, - VaultCategory: entity.VaultCategory{ + VaultCategory: &entity.VaultCategory{ Id: 1, Name: "Some Category", }, @@ -57,7 +57,7 @@ func TestVaultUseCaseList(t *testing.T) { Wallet: entity.Wallet{ Type: entity.IssuerType, }, - VaultCategory: entity.VaultCategory{ + VaultCategory: &entity.VaultCategory{ Id: 2, Name: "Another Category", }, @@ -119,7 +119,7 @@ func TestVaultUseCaseGetById(t *testing.T) { Wallet: entity.Wallet{ Type: entity.SponsorType, }, - VaultCategory: entity.VaultCategory{ + VaultCategory: &entity.VaultCategory{ Id: 1, Name: "Some Category", }, @@ -131,7 +131,7 @@ func TestVaultUseCaseGetById(t *testing.T) { Wallet: entity.Wallet{ Type: entity.IssuerType, }, - VaultCategory: entity.VaultCategory{ + VaultCategory: &entity.VaultCategory{ Id: 2, Name: "Another Category", }, @@ -192,7 +192,7 @@ func TestVaultUseCaseCreate(t *testing.T) { Wallet: entity.Wallet{ Type: entity.SponsorType, }, - VaultCategory: entity.VaultCategory{ + VaultCategory: &entity.VaultCategory{ Id: 1, Name: "Some Category", }, diff --git a/backend/migrations/000033_add_contract_created_at.down.sql b/backend/migrations/000033_add_contract_created_at.down.sql new file mode 100644 index 00000000..eb790762 --- /dev/null +++ b/backend/migrations/000033_add_contract_created_at.down.sql @@ -0,0 +1 @@ +ALTER TABLE contracts DROP COLUMN created_at; \ No newline at end of file diff --git a/backend/migrations/000033_add_contract_created_at.up.sql b/backend/migrations/000033_add_contract_created_at.up.sql new file mode 100644 index 00000000..c48449a5 --- /dev/null +++ b/backend/migrations/000033_add_contract_created_at.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE contracts +ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT NOW() \ No newline at end of file From 1d949c3aa3729401e36f14c577f82c62bb0b6618 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Tue, 5 Dec 2023 21:54:25 -0300 Subject: [PATCH 22/52] feat: contract history --- .../internal/controller/http/v1/contracts.go | 160 +++++++++++++++++- backend/internal/controller/http/v1/router.go | 2 +- backend/internal/controller/http/v1/vault.go | 51 +++--- backend/internal/entity/contract_history.go | 11 ++ backend/internal/usecase/contract.go | 33 +++- backend/internal/usecase/interfaces.go | 3 + .../usecase/repo/contract_postgres.go | 67 +++++++- .../internal/usecase/repo/vault_postgres.go | 23 ++- backend/internal/usecase/vault.go | 6 - .../000034_contract_history.down.sql | 1 + .../migrations/000034_contract_history.up.sql | 11 ++ .../000035_add_contract_permissions.down.sql | 1 + .../000035_add_contract_permissions.up.sql | 27 +++ 13 files changed, 356 insertions(+), 40 deletions(-) create mode 100644 backend/internal/entity/contract_history.go create mode 100644 backend/migrations/000034_contract_history.down.sql create mode 100644 backend/migrations/000034_contract_history.up.sql create mode 100644 backend/migrations/000035_add_contract_permissions.down.sql create mode 100644 backend/migrations/000035_add_contract_permissions.up.sql diff --git a/backend/internal/controller/http/v1/contracts.go b/backend/internal/controller/http/v1/contracts.go index 14fe12ea..73cab8ba 100644 --- a/backend/internal/controller/http/v1/contracts.go +++ b/backend/internal/controller/http/v1/contracts.go @@ -17,18 +17,22 @@ type contractRoutes struct { c usecase.ContractUseCase v usecase.VaultUseCase as usecase.AssetUseCase + u usecase.UserUseCase l *logger.Logger } func newContractRoutes(handler *gin.RouterGroup, m HTTPControllerMessenger, a usecase.AuthUseCase, c usecase.ContractUseCase, v usecase.VaultUseCase, - as usecase.AssetUseCase, l *logger.Logger, + as usecase.AssetUseCase, u usecase.UserUseCase, l *logger.Logger, ) { - r := &contractRoutes{m, a, c, v, as, l} + r := &contractRoutes{m, a, c, v, as, u, l} h := handler.Group("/contract").Use(Auth(r.a.ValidateToken())) { h.GET("/:id", r.getContractById) h.POST("", r.createContract) h.GET("/list", r.getAllContracts) + h.GET("/history/:contractId", r.getContractHistory) + h.POST("/history/", r.addContractHistory) + h.PUT("/history/", r.updateContractHistory) } } @@ -44,6 +48,16 @@ type CreateContractRequest struct { Compound int `json:"compound" example:"1"` } +type AddContractHistoryRequest struct { + DepositAmount float64 `json:"deposit_amount" binding:"required" example:"100"` + ContractId int `json:"contract_id" binding:"required" example:"GSDSC..."` +} + +type UpdateContractHistoryRequest struct { + WithdrawAmount float64 `json:"withdraw_amount" binding:"required" example:"100"` + ContractId int `json:"contract_id" binding:"required" example:"GSDSC..."` +} + // @Summary Create a new contract // @Description Create new contract // @Tags Contract @@ -179,3 +193,145 @@ func (r *contractRoutes) getContractById(c *gin.Context) { c.JSON(http.StatusOK, contract) } + +// @Summary Get contract history +// @Description Retrieve a list of history of contract +// @Tags ContractHistory +// @Accept json +// @Produce json +// @Param page query int false "Page number for pagination" +// @Param limit query int false "Number of items per page for pagination" +// @Success 200 {object} []entity.Contract +// @Failure 400 {object} response "Invalid query parameters" +// @Failure 500 {object} response "Internal server error" +// @Router /contracts [get] +func (r *contractRoutes) getContractHistory(c *gin.Context) { + contractId := c.Param("contractId") + + contract, err := r.c.GetById(contractId) + if err != nil { + errorResponse(c, http.StatusNotFound, "contract not found", err) + } + + token := c.Request.Header.Get("Authorization") + user, err := r.a.GetUserByToken(token) + if err != nil { + errorResponse(c, http.StatusNotFound, "user not found", err) + return + } + + userID, err := strconv.Atoi(user.ID) + contracts, err := r.c.GetHistory(userID, contract.Id) + if err != nil { + r.l.Error(err, "http - v1 - get history - GetHistory") + errorResponse(c, http.StatusInternalServerError, "error getting history", err) + return + } + c.JSON(http.StatusOK, contracts) +} + +// @Summary Add contract history +// @Description Add contract history +// @Tags Contract +// @Accept json +// @Produce json +// @Param request body AddContractHistoryRequest true "History info" +// @Success 200 {object} entity.ContractHistory +// @Failure 400 {object} response +// @Failure 404 {object} response +// @Failure 500 {object} response +// @Router /contract/history [post] +func (r *contractRoutes) addContractHistory(c *gin.Context) { + var request AddContractHistoryRequest + var err error + + if err := c.ShouldBindJSON(&request); err != nil { + r.l.Error(err, "http - v1 - add contract history - ShouldBindJSON") + errorResponse(c, http.StatusBadRequest, fmt.Sprintf("invalid request body: %s", err.Error()), err) + return + } + + contractId := strconv.Itoa(request.ContractId) + contract, err := r.c.GetById(contractId) + if err != nil { + r.l.Error(err, "http - v1 - add contract history - GetById") + errorResponse(c, http.StatusNotFound, "contract not found", err) + return + } + + token := c.Request.Header.Get("Authorization") + user, err := r.u.GetUserByToken(token) + if err != nil { + r.l.Error(err, "http - v1 - create contract - GetById") + errorResponse(c, http.StatusNotFound, "vault not found", err) + return + } + + contractHistory := entity.ContractHistory{ + Contract: contract, + User: user, + DepositAmount: request.DepositAmount, + } + + contractHistory, err = r.c.AddContractHistory(contractHistory) + if err != nil { + r.l.Error(err, "http - v1 - add contract history - Create") + errorResponse(c, http.StatusNotFound, fmt.Sprintf("error: %s", err.Error()), err) + return + } + + c.JSON(http.StatusOK, contractHistory) +} + +// @Summary Update contract history +// @Description Update contract history +// @Tags Contract +// @Accept json +// @Produce json +// @Param request body UpdateContractHistoryRequest true "History info" +// @Success 200 {object} entity.ContractHistory +// @Failure 400 {object} response +// @Failure 404 {object} response +// @Failure 500 {object} response +// @Router /contract/history [put] +func (r *contractRoutes) updateContractHistory(c *gin.Context) { + var request UpdateContractHistoryRequest + var err error + + if err := c.ShouldBindJSON(&request); err != nil { + r.l.Error(err, "http - v1 - add contract history - ShouldBindJSON") + errorResponse(c, http.StatusBadRequest, fmt.Sprintf("invalid request body: %s", err.Error()), err) + return + } + + contractId := strconv.Itoa(request.ContractId) + contract, err := r.c.GetById(contractId) + if err != nil { + r.l.Error(err, "http - v1 - add contract history - GetById") + errorResponse(c, http.StatusNotFound, "contract not found", err) + return + } + + token := c.Request.Header.Get("Authorization") + user, err := r.u.GetUserByToken(token) + if err != nil { + r.l.Error(err, "http - v1 - create contract - GetById") + errorResponse(c, http.StatusNotFound, "vault not found", err) + return + } + + contractHistory := entity.ContractHistory{ + Contract: contract, + User: user, + WithdrawAmount: &request.WithdrawAmount, + } + + contractHistory, err = r.c.UpdateContractHistory(contractHistory) + if err != nil { + r.l.Error(err, "http - v1 - update contract history - Create") + errorResponse(c, http.StatusNotFound, fmt.Sprintf("error: %s", err.Error()), err) + return + } + + c.JSON(http.StatusOK, contractHistory) +} diff --git a/backend/internal/controller/http/v1/router.go b/backend/internal/controller/http/v1/router.go index ec6799d0..c53e1cd9 100644 --- a/backend/internal/controller/http/v1/router.go +++ b/backend/internal/controller/http/v1/router.go @@ -92,7 +92,7 @@ func NewRouter( newRolePermissionsRoutes(groupV1, rolePermissionUc, messengerController, logger) newVaultCategoryRoutes(groupV1, messengerController, authUseCase, vaultCategoryUc, logger) newVaultRoutes(groupV1, messengerController, authUseCase, vaultUc, vaultCategoryUc, walletUseCase, assetUseCase, logger) - newContractRoutes(groupV1, messengerController, authUseCase, contractUc, vaultUc, assetUseCase, logger) + newContractRoutes(groupV1, messengerController, authUseCase, contractUc, vaultUc, assetUseCase, userUseCase, logger) newLogTransactionsRoutes(groupV1, walletUseCase, assetUseCase, messengerController, logUc, authUseCase, logger) newSorobanRoutes(groupV1, walletUseCase, messengerController, authUseCase) newAssetTomlRoutes(groupV1, walletUseCase, assetUseCase, messengerController, authUseCase, logUc, logger) diff --git a/backend/internal/controller/http/v1/vault.go b/backend/internal/controller/http/v1/vault.go index 4d081cb0..d35a38c6 100644 --- a/backend/internal/controller/http/v1/vault.go +++ b/backend/internal/controller/http/v1/vault.go @@ -111,16 +111,34 @@ func (r *vaultRoutes) createVault(c *gin.Context) { } walletPk := kpRes.PublicKeys[0] - ops := []entity.Operation{ - { - Type: entity.CreateAccountOp, - Target: walletPk, - Amount: _startingBalance, - Origin: sponsor.Key.PublicKey, - Sponsor: sponsor.Key.PublicKey, + wallet, err := r.w.Create(entity.Wallet{ + Type: entity.DistributorType, + Key: entity.Key{ + PublicKey: walletPk, + Weight: 1, }, + }) + + fundRes, err := r.m.SendMessage(entity.HorizonChannel, entity.HorizonRequest{ + Id: wallet.Id, + Type: "fundWithFriendbot", + Account: walletPk, + }) + if err != nil { + r.l.Error(err, "http - v1 - fund wallet - SendMessage") + errorResponse(c, http.StatusInternalServerError, "messaging problems", err) + } + + fundResult := fundRes.Message.(entity.HorizonResponse) + + if fundResult.StatusCode != 200 { + r.l.Error(err, "http - v1 - fund wallet - fundRes.StatusCode != 200") + errorResponse(c, http.StatusInternalServerError, "friendbot error", err) + return } + ops := []entity.Operation{} + for _, assetId := range request.AssetsId { asset, err := r.as.GetById(strconv.Itoa(assetId)) if err != nil { @@ -159,15 +177,6 @@ func (r *vaultRoutes) createVault(c *gin.Context) { return } - wallet := entity.Wallet{ - Type: entity.DistributorType, - Funded: true, - Key: entity.Key{ - PublicKey: walletPk, - Weight: 1, - }, - } - vault := entity.Vault{ Name: request.Name, VaultCategory: &vaultCategory, @@ -261,16 +270,6 @@ func (r *vaultRoutes) getVaultById(c *gin.Context) { return } - if vault.VaultCategoryId != nil { - vaultCategory, err := r.vc.GetById(*vault.VaultCategoryId) - if err != nil { - errorResponse(c, http.StatusInternalServerError, "error getting vault category", err) - return - } - - vault.VaultCategory = &vaultCategory - } - c.JSON(http.StatusOK, vault) } diff --git a/backend/internal/entity/contract_history.go b/backend/internal/entity/contract_history.go new file mode 100644 index 00000000..276b3794 --- /dev/null +++ b/backend/internal/entity/contract_history.go @@ -0,0 +1,11 @@ +package entity + +type ContractHistory struct { + Id int `json:"id" example:"1"` + Contract Contract `json:"contract"` + DepositedAt *string `json:"deposited_at"` + DepositAmount float64 `json:"deposit_amount"` + WithdrawnAt *string `json:"withdrawn_at"` + WithdrawAmount *float64 `json:"withdraw_amount"` + User User `json:"user"` +} diff --git a/backend/internal/usecase/contract.go b/backend/internal/usecase/contract.go index 2e779a91..0580cd94 100644 --- a/backend/internal/usecase/contract.go +++ b/backend/internal/usecase/contract.go @@ -35,12 +35,12 @@ func (uc *ContractUseCase) GetAll() ([]entity.Contract, error) { } func (uc *ContractUseCase) GetById(id string) (entity.Contract, error) { - asset, err := uc.cRepo.GetContractById(id) + contract, err := uc.cRepo.GetContractById(id) if err != nil { - return entity.Contract{}, fmt.Errorf("ContractUseCase - Get - uc.repo.GetContractById: %w", err) + return entity.Contract{}, fmt.Errorf("ContractUseCase - GetById - uc.repo.GetContractById: %w", err) } - return asset, nil + return contract, nil } func (uc *ContractUseCase) GetPaginatedContracts(page int, limit int) ([]entity.Contract, error) { @@ -51,3 +51,30 @@ func (uc *ContractUseCase) GetPaginatedContracts(page int, limit int) ([]entity. return contracts, nil } + +func (uc *ContractUseCase) GetHistory(userId int, contractId int) ([]entity.ContractHistory, error) { + contractsHistory, err := uc.cRepo.GetHistory(userId, contractId) + if err != nil { + return nil, fmt.Errorf("ContractUseCase - GetHistory - uc.repo.GetHistory: %w", err) + } + + return contractsHistory, nil +} + +func (uc *ContractUseCase) AddContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) { + contractsHistory, err := uc.cRepo.AddContractHistory(contractHistory) + if err != nil { + return entity.ContractHistory{}, fmt.Errorf("ContractUseCase - AddContractHistory - uc.repo.AddContractHistory: %w", err) + } + + return contractsHistory, nil +} + +func (uc *ContractUseCase) UpdateContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) { + contractHistory, err := uc.cRepo.UpdateContractHistory(contractHistory) + if err != nil { + return entity.ContractHistory{}, fmt.Errorf("ContractUseCase - UpdateContractHistory - uc.repo.UpdateContractHistory: %w", err) + } + + return contractHistory, nil +} diff --git a/backend/internal/usecase/interfaces.go b/backend/internal/usecase/interfaces.go index 4d2ca13f..247311aa 100644 --- a/backend/internal/usecase/interfaces.go +++ b/backend/internal/usecase/interfaces.go @@ -103,6 +103,9 @@ type ( CreateContract(entity.Contract) (entity.Contract, error) GetContractById(id string) (entity.Contract, error) GetPaginatedContracts(int, int) ([]entity.Contract, error) + GetHistory(userId int, contractId int) ([]entity.ContractHistory, error) + AddContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) + UpdateContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) } LogTransactionRepoInterface interface { diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index dfa49457..a46837a3 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -148,9 +148,9 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { vault.Wallet = wallet vault.VaultCategory = &vaultCategory - contract.Asset = asset asset.Distributor = assetDistributor asset.Issuer = assetIssuer + contract.Asset = asset contract.Vault = vault return contract, nil @@ -227,3 +227,68 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, return contracts, nil } + +func (r ContractRepo) GetHistory(userId int, contractId int) ([]entity.ContractHistory, error) { + query := ` + SELECT ch.id, ch.deposited_at, ch.deposit_amount, ch.withdrawn_at, ch.withdraw_amount, ch.deposited_at + FROM contractshistory ch + WHERE ch.user_id = $1 AND ch.contract_id = $2 + ORDER BY ch.deposited_at DESC; + ` + + rows, err := r.Db.Query(query, userId, contractId) + if err != nil { + return nil, fmt.Errorf("ContractRepo - GetHistory - Query: %w", err) + } + defer rows.Close() + + contractsHistory := []entity.ContractHistory{} + + for rows.Next() { + var contractHistory entity.ContractHistory + + err := rows.Scan( + &contractHistory.Id, &contractHistory.DepositedAt, &contractHistory.DepositAmount, &contractHistory.WithdrawnAt, + &contractHistory.WithdrawAmount, &contractHistory.DepositedAt, + ) + if err != nil { + return nil, fmt.Errorf("ContractRepo - GetContractCategories - row.Scan: %w", err) + } + + contractsHistory = append(contractsHistory, contractHistory) + } + + return contractsHistory, nil +} + +func (r ContractRepo) AddContractHistory(data entity.ContractHistory) (entity.ContractHistory, error) { + res := data + stmt := `INSERT INTO contractshistory (deposit_amount, contract_id, user_id) + VALUES ($1, $2, $3) RETURNING id;` + + err := r.Db.QueryRow(stmt, data.DepositAmount, data.Contract.Id, data.User.ID).Scan(&res.Id) + + if err != nil { + return entity.ContractHistory{}, fmt.Errorf("ContractRepo - addContractHistory - db.QueryRow: %w", err) + } + + return res, nil +} + +func (r ContractRepo) UpdateContractHistory(data entity.ContractHistory) (entity.ContractHistory, error) { + res := data + stmt := `UPDATE ContractsHistory SET withdraw_amount = $1, withdrawn_at = now() WHERE id = ( + SELECT id + FROM ContractsHistory + WHERE withdraw_amount IS NULL AND contract_id = $2 AND user_id = $3 + ORDER BY id DESC + LIMIT 1) RETURNING id;` + + err := r.Db.QueryRow(stmt, data.WithdrawAmount, data.Contract.Id, data.User.ID).Scan(&res.Id) + + if err != nil { + return entity.ContractHistory{}, fmt.Errorf("ContractRepo - updateContractHistory - db.QueryRow: %w", err) + } + + return res, nil +} diff --git a/backend/internal/usecase/repo/vault_postgres.go b/backend/internal/usecase/repo/vault_postgres.go index a16c02f8..3ce4ef7b 100644 --- a/backend/internal/usecase/repo/vault_postgres.go +++ b/backend/internal/usecase/repo/vault_postgres.go @@ -81,9 +81,11 @@ func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { query := ` SELECT v.id AS vault_id, v.name AS vault_name, v.active as vault_active, v.owner_id AS owner_id, + vc.id AS vault_category_id, vc.name as vault_category_name, vc.theme as vault_category_theme, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight FROM vault v + LEFT JOIN vaultcategory vc ON v.vault_category_id = vc.id JOIN wallet w ON v.wallet_id = w.id JOIN key wk ON w.id = wk.wallet_id WHERE v.id = $1; @@ -92,10 +94,14 @@ func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { row := r.Db.QueryRow(query, id) var vault entity.Vault + var vaultCategoryId sql.NullInt64 + var vaultCategoryName sql.NullString + var vaultCategoryTheme sql.NullString var wallet entity.Wallet err := row.Scan( &vault.Id, &vault.Name, &vault.Active, &vault.OwnerId, + &vaultCategoryId, &vaultCategoryName, &vaultCategoryTheme, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, ) @@ -107,6 +113,14 @@ func (r VaultRepo) GetVaultById(id int) (entity.Vault, error) { } vault.Wallet = wallet + if vaultCategoryId.Valid { + vault.VaultCategory = &entity.VaultCategory{ + Id: int(vaultCategoryId.Int64), + Name: vaultCategoryName.String, + Theme: &vaultCategoryTheme.String, + } + } + return vault, nil } @@ -118,7 +132,14 @@ func (r VaultRepo) CreateVault(data entity.Vault) (entity.Vault, error) { vaultCategoryId = &data.VaultCategory.Id } - stmt := `INSERT INTO Vault (name, vault_category_id, wallet_id, owner_id) VALUES ($1, $2, $3, $4) RETURNING id;` + var stmt string + if data.OwnerId != nil { + stmt = `INSERT INTO Vault (name, vault_category_id, wallet_id, owner_id) + VALUES (CONCAT(CAST($1 AS TEXT), '#', NEXTVAL('vault_id_seq')), $2, $3, $4) RETURNING id;` + } else { + stmt = `INSERT INTO Vault (name, vault_category_id, wallet_id, owner_id) + VALUES ($1, $2, $3, $4) RETURNING id;` + } err := r.Db.QueryRow(stmt, data.Name, vaultCategoryId, data.Wallet.Id, data.OwnerId).Scan(&res.Id) if err != nil { return entity.Vault{}, fmt.Errorf("VaultRepo - Vault - db.QueryRow: %w", err) diff --git a/backend/internal/usecase/vault.go b/backend/internal/usecase/vault.go index 3c3b39c3..7bac9f03 100644 --- a/backend/internal/usecase/vault.go +++ b/backend/internal/usecase/vault.go @@ -19,12 +19,6 @@ func NewVaultUseCase(vRepo VaultRepoInterface, wRepo WalletRepoInterface) *Vault } func (uc *VaultUseCase) Create(data entity.Vault) (entity.Vault, error) { - wallet, err := uc.wRepo.CreateWalletWithKey(data.Wallet) - if err != nil { - return entity.Vault{}, fmt.Errorf("VaultUseCase - Create - uc.repo.CreateWalletWithKey(dist): %w", err) - } - data.Wallet.Id = wallet.Id - vault, err := uc.vRepo.CreateVault(data) if err != nil { return entity.Vault{}, fmt.Errorf("VaultUseCase - Create - uc.repo.CreateVault: %w", err) diff --git a/backend/migrations/000034_contract_history.down.sql b/backend/migrations/000034_contract_history.down.sql new file mode 100644 index 00000000..a48a469b --- /dev/null +++ b/backend/migrations/000034_contract_history.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS Contracts; \ No newline at end of file diff --git a/backend/migrations/000034_contract_history.up.sql b/backend/migrations/000034_contract_history.up.sql new file mode 100644 index 00000000..17fb4599 --- /dev/null +++ b/backend/migrations/000034_contract_history.up.sql @@ -0,0 +1,11 @@ +CREATE TABLE ContractsHistory ( + id SERIAL PRIMARY KEY, + contract_id INT NOT NULL, + deposited_at TIMESTAMP NOT NULL DEFAULT NOW(), + deposit_amount FLOAT NOT NULL, + withdrawn_at TIMESTAMP, + withdraw_amount FLOAT, + user_id INT NOT NULL, + FOREIGN KEY (contract_id) REFERENCES Contracts(id), + FOREIGN KEY (user_id) REFERENCES UserAccount(id) +); \ No newline at end of file diff --git a/backend/migrations/000035_add_contract_permissions.down.sql b/backend/migrations/000035_add_contract_permissions.down.sql new file mode 100644 index 00000000..a48a469b --- /dev/null +++ b/backend/migrations/000035_add_contract_permissions.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS Contracts; \ No newline at end of file diff --git a/backend/migrations/000035_add_contract_permissions.up.sql b/backend/migrations/000035_add_contract_permissions.up.sql new file mode 100644 index 00000000..8451c014 --- /dev/null +++ b/backend/migrations/000035_add_contract_permissions.up.sql @@ -0,0 +1,27 @@ +DO $$ +DECLARE + permission_id INT; +BEGIN + INSERT INTO Permission (name, description) VALUES ('Create certificates', '') RETURNING id INTO permission_id; + EXECUTE format('INSERT INTO Operation (name, description, permission_id, action) VALUES (%L, %L, %s, %L)', 'Create certificates', '', permission_id, 'create-certificates'); + EXECUTE format('INSERT INTO RolePermissionJunction (role_id, permission_id) VALUES (%s, %s)', 1, permission_id); +END $$; + +DO $$ +DECLARE + permission_id INT; +BEGIN + INSERT INTO Permission (name, description) VALUES ('Create wallet', '') RETURNING id INTO permission_id; + EXECUTE format('INSERT INTO Operation (name, description, permission_id, action) VALUES (%L, %L, %s, %L)', 'Create wallet', '', permission_id, 'create-wallet'); + EXECUTE format('INSERT INTO RolePermissionJunction (role_id, permission_id) VALUES (%s, %s)', 1, permission_id); +END $$; + + +DO $$ +DECLARE + permission_id INT; +BEGIN + INSERT INTO Permission (name, description) VALUES ('Invest in the certificate', '') RETURNING id INTO permission_id; + EXECUTE format('INSERT INTO Operation (name, description, permission_id, action) VALUES (%L, %L, %s, %L)', 'Invest in the certificate', '', permission_id, 'invest-certificate'); + EXECUTE format('INSERT INTO RolePermissionJunction (role_id, permission_id) VALUES (%s, %s)', 1, permission_id); +END $$; From 9f97b83656d402ca7a0b8bd0b4fc5d624cd3ea32 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Tue, 5 Dec 2023 21:57:46 -0300 Subject: [PATCH 23/52] fix tests --- backend/internal/usecase/mocks/mocks.go | 67 +++++++++++++++++++++++-- backend/internal/usecase/vault_test.go | 8 +-- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/backend/internal/usecase/mocks/mocks.go b/backend/internal/usecase/mocks/mocks.go index 58df6b25..1e5b5c03 100644 --- a/backend/internal/usecase/mocks/mocks.go +++ b/backend/internal/usecase/mocks/mocks.go @@ -490,6 +490,20 @@ func (mr *MockAssetRepoInterfaceMockRecorder) StoreAssetImage(arg0, arg1 interfa return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreAssetImage", reflect.TypeOf((*MockAssetRepoInterface)(nil).StoreAssetImage), arg0, arg1) } +// UpdateContractId mocks base method. +func (m *MockAssetRepoInterface) UpdateContractId(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateContractId", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateContractId indicates an expected call of UpdateContractId. +func (mr *MockAssetRepoInterfaceMockRecorder) UpdateContractId(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateContractId", reflect.TypeOf((*MockAssetRepoInterface)(nil).UpdateContractId), arg0, arg1) +} + // MockRoleRepoInterface is a mock of RoleRepoInterface interface. type MockRoleRepoInterface struct { ctrl *gomock.Controller @@ -974,18 +988,18 @@ func (mr *MockVaultRepoInterfaceMockRecorder) GetVaultById(id interface{}) *gomo } // GetVaults mocks base method. -func (m *MockVaultRepoInterface) GetVaults() ([]entity.Vault, error) { +func (m *MockVaultRepoInterface) GetVaults(isAll bool) ([]entity.Vault, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetVaults") + ret := m.ctrl.Call(m, "GetVaults", isAll) ret0, _ := ret[0].([]entity.Vault) ret1, _ := ret[1].(error) return ret0, ret1 } // GetVaults indicates an expected call of GetVaults. -func (mr *MockVaultRepoInterfaceMockRecorder) GetVaults() *gomock.Call { +func (mr *MockVaultRepoInterfaceMockRecorder) GetVaults(isAll interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVaults", reflect.TypeOf((*MockVaultRepoInterface)(nil).GetVaults)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVaults", reflect.TypeOf((*MockVaultRepoInterface)(nil).GetVaults), isAll) } // UpdateVault mocks base method. @@ -1026,6 +1040,21 @@ func (m *MockContractRepoInterface) EXPECT() *MockContractRepoInterfaceMockRecor return m.recorder } +// AddContractHistory mocks base method. +func (m *MockContractRepoInterface) AddContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddContractHistory", contractHistory) + ret0, _ := ret[0].(entity.ContractHistory) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AddContractHistory indicates an expected call of AddContractHistory. +func (mr *MockContractRepoInterfaceMockRecorder) AddContractHistory(contractHistory interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddContractHistory", reflect.TypeOf((*MockContractRepoInterface)(nil).AddContractHistory), contractHistory) +} + // CreateContract mocks base method. func (m *MockContractRepoInterface) CreateContract(arg0 entity.Contract) (entity.Contract, error) { m.ctrl.T.Helper() @@ -1071,6 +1100,21 @@ func (mr *MockContractRepoInterfaceMockRecorder) GetContracts() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContracts", reflect.TypeOf((*MockContractRepoInterface)(nil).GetContracts)) } +// GetHistory mocks base method. +func (m *MockContractRepoInterface) GetHistory(userId, contractId int) ([]entity.ContractHistory, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetHistory", userId, contractId) + ret0, _ := ret[0].([]entity.ContractHistory) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetHistory indicates an expected call of GetHistory. +func (mr *MockContractRepoInterfaceMockRecorder) GetHistory(userId, contractId interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHistory", reflect.TypeOf((*MockContractRepoInterface)(nil).GetHistory), userId, contractId) +} + // GetPaginatedContracts mocks base method. func (m *MockContractRepoInterface) GetPaginatedContracts(arg0, arg1 int) ([]entity.Contract, error) { m.ctrl.T.Helper() @@ -1086,6 +1130,21 @@ func (mr *MockContractRepoInterfaceMockRecorder) GetPaginatedContracts(arg0, arg return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPaginatedContracts", reflect.TypeOf((*MockContractRepoInterface)(nil).GetPaginatedContracts), arg0, arg1) } +// UpdateContractHistory mocks base method. +func (m *MockContractRepoInterface) UpdateContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateContractHistory", contractHistory) + ret0, _ := ret[0].(entity.ContractHistory) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateContractHistory indicates an expected call of UpdateContractHistory. +func (mr *MockContractRepoInterfaceMockRecorder) UpdateContractHistory(contractHistory interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateContractHistory", reflect.TypeOf((*MockContractRepoInterface)(nil).UpdateContractHistory), contractHistory) +} + // MockLogTransactionRepoInterface is a mock of LogTransactionRepoInterface interface. type MockLogTransactionRepoInterface struct { ctrl *gomock.Controller diff --git a/backend/internal/usecase/vault_test.go b/backend/internal/usecase/vault_test.go index d5ab0a61..66709017 100644 --- a/backend/internal/usecase/vault_test.go +++ b/backend/internal/usecase/vault_test.go @@ -68,7 +68,7 @@ func TestVaultUseCaseList(t *testing.T) { name: "list - two vaults", req: nil, mock: func() { - vr.EXPECT().GetVaults().Return([]entity.Vault{vault1, vault2}, nil) + vr.EXPECT().GetVaults(true).Return([]entity.Vault{vault1, vault2}, nil) }, res: []entity.Vault{vault1, vault2}, err: nil, @@ -77,7 +77,7 @@ func TestVaultUseCaseList(t *testing.T) { name: "list - empty", req: nil, mock: func() { - vr.EXPECT().GetVaults().Return([]entity.Vault{}, nil) + vr.EXPECT().GetVaults(true).Return([]entity.Vault{}, nil) }, res: []entity.Vault{}, err: nil, @@ -86,7 +86,7 @@ func TestVaultUseCaseList(t *testing.T) { name: "list - database error", req: nil, mock: func() { - vr.EXPECT().GetVaults().Return(nil, dbError) + vr.EXPECT().GetVaults(true).Return(nil, dbError) }, res: []entity.Vault(nil), err: dbError, @@ -98,7 +98,7 @@ func TestVaultUseCaseList(t *testing.T) { t.Run(tc.name, func(t *testing.T) { tc.mock() - res, err := u.GetAll() + res, err := u.GetAll(true) require.EqualValues(t, tc.res, res) if tc.err == nil { From c5a9007721129b88d747ccffb20b85aa712a556d Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Wed, 6 Dec 2023 10:22:45 -0300 Subject: [PATCH 24/52] fix migration down --- .../000035_add_contract_permissions.down.sql | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/backend/migrations/000035_add_contract_permissions.down.sql b/backend/migrations/000035_add_contract_permissions.down.sql index a48a469b..7cbb9c77 100644 --- a/backend/migrations/000035_add_contract_permissions.down.sql +++ b/backend/migrations/000035_add_contract_permissions.down.sql @@ -1 +1,22 @@ -DROP TABLE IF EXISTS Contracts; \ No newline at end of file +DO $$ +DECLARE + permission_id INT; +BEGIN + -- Revert 'Invest in the certificate' + SELECT id INTO permission_id FROM Permission WHERE name = 'Invest in the certificate'; + DELETE FROM RolePermissionJunction WHERE permission_id = permission_id; + DELETE FROM Operation WHERE permission_id = permission_id; + DELETE FROM Permission WHERE id = permission_id; + + -- Revert 'Create wallet' + SELECT id INTO permission_id FROM Permission WHERE name = 'Create wallet'; + DELETE FROM RolePermissionJunction WHERE permission_id = permission_id; + DELETE FROM Operation WHERE permission_id = permission_id; + DELETE FROM Permission WHERE id = permission_id; + + -- Revert 'Create certificates' + SELECT id INTO permission_id FROM Permission WHERE name = 'Create certificates'; + DELETE FROM RolePermissionJunction WHERE permission_id = permission_id; + DELETE FROM Operation WHERE permission_id = permission_id; + DELETE FROM Permission WHERE id = permission_id; +END $$; From 4512b93d558a1b47c809b0cde433327f20902d81 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Wed, 6 Dec 2023 14:26:44 -0300 Subject: [PATCH 25/52] fix create personal vault --- backend/internal/controller/http/v1/vault.go | 38 +++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/backend/internal/controller/http/v1/vault.go b/backend/internal/controller/http/v1/vault.go index d35a38c6..69807dbf 100644 --- a/backend/internal/controller/http/v1/vault.go +++ b/backend/internal/controller/http/v1/vault.go @@ -158,23 +158,27 @@ func (r *vaultRoutes) createVault(c *gin.Context) { }) } - Id := generateID() - res, err = r.m.SendMessage(entity.EnvelopeChannel, entity.EnvelopeRequest{ - Id: Id, - MainSource: sponsor.Key.PublicKey, - PublicKeys: []string{sponsor.Key.PublicKey, walletPk}, - Operations: ops, - }) - if err != nil { - r.l.Error(err, fmt.Sprintf("http - v1 - create vault - send message %d", Id)) - errorResponse(c, http.StatusInternalServerError, "starlabs messaging problems", err) - return - } - _, ok = res.Message.(entity.EnvelopeResponse) - if !ok { - r.l.Error(err, "http - v1 - create vault - Parse Envelope Response") - errorResponse(c, http.StatusInternalServerError, "unexpected starlabs response", err) - return + if len(ops) > 0 { + Id := generateID() + res, err = r.m.SendMessage(entity.EnvelopeChannel, entity.EnvelopeRequest{ + Id: Id, + MainSource: sponsor.Key.PublicKey, + PublicKeys: []string{sponsor.Key.PublicKey, walletPk}, + Operations: ops, + }) + + if err != nil { + r.l.Error(err, fmt.Sprintf("http - v1 - create vault - send message %d", Id)) + errorResponse(c, http.StatusInternalServerError, "starlabs messaging problems", err) + return + } + + _, ok = res.Message.(entity.EnvelopeResponse) + if !ok { + r.l.Error(err, "http - v1 - create vault - Parse Envelope Response") + errorResponse(c, http.StatusInternalServerError, "unexpected starlabs response", err) + return + } } vault := entity.Vault{ From 4aed09c9b818a0849b54da7e8e4cb626023b8bce Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Thu, 7 Dec 2023 16:45:32 -0300 Subject: [PATCH 26/52] Refactor getAllAssets endpoint to return paginated assets --- backend/internal/controller/http/v1/assets.go | 14 ++++++++--- backend/internal/usecase/assets.go | 8 +++--- backend/internal/usecase/interfaces.go | 2 +- .../internal/usecase/repo/asset_postgres.go | 25 +++++++++++++++---- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/backend/internal/controller/http/v1/assets.go b/backend/internal/controller/http/v1/assets.go index 6ed8a063..8cd2fc7f 100644 --- a/backend/internal/controller/http/v1/assets.go +++ b/backend/internal/controller/http/v1/assets.go @@ -116,6 +116,11 @@ type UploadAssetImageRequest struct { Image string `json:"image" example:"iVBORw0KGgoAAAANSUhEUgAACqoAAAMMCAMAAAAWqpRaAAADAFBMVEX///..."` } +type PaginatedAssetsResponse struct { + Assets []entity.Asset `json:"assets"` + TotalPages int `json:"totalPages"` +} + // @Summary Create a new asset // @Description Create and issue a new asset on Stellar // @Tags Assets @@ -854,7 +859,7 @@ func (r *assetsRoutes) updateAuthFlags(c *gin.Context) { // @Produce json // @Param page query int false "Page number" // @Param limit query int false "Number of items per page" -// @Success 200 {object} []entity.Asset +// @Success 200 {object} PaginatedAssetsResponse // @Failure 500 {object} response // @Router /assets [get] func (r *assetsRoutes) getAllAssets(c *gin.Context) { @@ -877,14 +882,17 @@ func (r *assetsRoutes) getAllAssets(c *gin.Context) { } // Fetch paginated assets - assets, err := r.as.GetPaginatedAssets(page, limit) + assets, totalPages, err := r.as.GetPaginatedAssets(page, limit) if err != nil { r.logger.Error(err, "http - v1 - get all assets - get paginated") errorResponse(c, http.StatusInternalServerError, "error getting paginated assets", err) return } - c.JSON(http.StatusOK, assets) + c.JSON(http.StatusOK, PaginatedAssetsResponse{ + Assets: assets, + TotalPages: totalPages, + }) } else { // Fetch all assets assets, err := r.as.GetAll() diff --git a/backend/internal/usecase/assets.go b/backend/internal/usecase/assets.go index 0a5fb611..1246ee32 100644 --- a/backend/internal/usecase/assets.go +++ b/backend/internal/usecase/assets.go @@ -160,11 +160,11 @@ func (uc *AssetUseCase) GetTomlData() (entity.TomlData, error) { return tomParsed, err } -func (uc *AssetUseCase) GetPaginatedAssets(page int, limit int) ([]entity.Asset, error) { - assets, err := uc.aRepo.GetPaginatedAssets(page, limit) +func (uc *AssetUseCase) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, error) { + assets, totalPages, err := uc.aRepo.GetPaginatedAssets(page, limit) if err != nil { - return nil, fmt.Errorf("AssetUseCase - GetPaginated - uc.repo.GetPaginated: %w", err) + return nil, 0, fmt.Errorf("AssetUseCase - GetPaginated - uc.repo.GetPaginated: %w", err) } - return assets, nil + return assets, totalPages, nil } diff --git a/backend/internal/usecase/interfaces.go b/backend/internal/usecase/interfaces.go index 4497716a..1c8d7aad 100644 --- a/backend/internal/usecase/interfaces.go +++ b/backend/internal/usecase/interfaces.go @@ -49,7 +49,7 @@ type ( GetAssetById(string) (entity.Asset, error) StoreAssetImage(string, []byte) error GetAssetImage(string) ([]byte, error) - GetPaginatedAssets(int, int) ([]entity.Asset, error) + GetPaginatedAssets(int, int) ([]entity.Asset, int, error) } // Role -. diff --git a/backend/internal/usecase/repo/asset_postgres.go b/backend/internal/usecase/repo/asset_postgres.go index c579ceda..172bcec9 100644 --- a/backend/internal/usecase/repo/asset_postgres.go +++ b/backend/internal/usecase/repo/asset_postgres.go @@ -211,10 +211,25 @@ func (r AssetRepo) GetAssetImage(assetId string) ([]byte, error) { return image, nil } -func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, error) { - // Calculate offset +func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, error) { + // Calculate the offset offset := (page - 1) * limit + // Query to count the total number of assets + countQuery := ` + SELECT COUNT(*) + FROM asset; + ` + var totalAssets int + err := r.Db.QueryRow(countQuery).Scan(&totalAssets) + if err != nil { + return nil, 0, fmt.Errorf("AssetRepo - GetPaginated - Count Query: %w", err) + } + + // Calculate total pages + totalPages := (totalAssets + limit - 1) / limit + + // Query to fetch paginated assets query := ` SELECT a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, a.image, @@ -233,7 +248,7 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, erro rows, err := r.Db.Query(query, limit, offset) if err != nil { - return nil, fmt.Errorf("AssetRepo - GetPaginated - Query: %w", err) + return nil, 0, fmt.Errorf("AssetRepo - GetPaginated - Query: %w", err) } defer rows.Close() @@ -251,7 +266,7 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, erro &issuer.Key.Id, &issuer.Key.PublicKey, &issuer.Key.Weight, ) if err != nil { - return nil, fmt.Errorf("AssetRepo - GetPaginated - row.Scan: %w", err) + return nil, 0, fmt.Errorf("AssetRepo - GetPaginated - row.Scan: %w", err) } asset.Distributor = distributor @@ -260,5 +275,5 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, erro assets = append(assets, asset) } - return assets, nil + return assets, totalPages, nil } From 96a26d2ac7797eecb9dad5559447c9a56f7d58b2 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Thu, 7 Dec 2023 16:49:28 -0300 Subject: [PATCH 27/52] Refactor API response schema --- backend/docs/docs.go | 19 +++++++++++++++---- backend/docs/swagger.json | 19 +++++++++++++++---- backend/docs/swagger.yaml | 13 ++++++++++--- go | 0 stellar-kms | 2 +- 5 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 go diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 52dca575..38e3734f 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -142,10 +142,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/entity.Asset" - } + "$ref": "#/definitions/v1.PaginatedAssetsResponse" } }, "500": { @@ -3034,6 +3031,20 @@ const docTemplate = `{ } } }, + "v1.PaginatedAssetsResponse": { + "type": "object", + "properties": { + "assets": { + "type": "array", + "items": { + "$ref": "#/definitions/entity.Asset" + } + }, + "totalPages": { + "type": "integer" + } + } + }, "v1.RolePermissionRequest": { "type": "object", "properties": { diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index e45fb66d..9a3597d4 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -131,10 +131,7 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/entity.Asset" - } + "$ref": "#/definitions/v1.PaginatedAssetsResponse" } }, "500": { @@ -3023,6 +3020,20 @@ } } }, + "v1.PaginatedAssetsResponse": { + "type": "object", + "properties": { + "assets": { + "type": "array", + "items": { + "$ref": "#/definitions/entity.Asset" + } + }, + "totalPages": { + "type": "integer" + } + } + }, "v1.RolePermissionRequest": { "type": "object", "properties": { diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 2096935f..d41d1a98 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -590,6 +590,15 @@ definitions: - code - id type: object + v1.PaginatedAssetsResponse: + properties: + assets: + items: + $ref: '#/definitions/entity.Asset' + type: array + totalPages: + type: integer + type: object v1.RolePermissionRequest: properties: is_add: @@ -790,9 +799,7 @@ paths: "200": description: OK schema: - items: - $ref: '#/definitions/entity.Asset' - type: array + $ref: '#/definitions/v1.PaginatedAssetsResponse' "500": description: Internal Server Error schema: diff --git a/go b/go new file mode 100644 index 00000000..e69de29b diff --git a/stellar-kms b/stellar-kms index 41ad8f01..1427b6e2 160000 --- a/stellar-kms +++ b/stellar-kms @@ -1 +1 @@ -Subproject commit 41ad8f01552a39aa2ea4441c690fd14efb42ca56 +Subproject commit 1427b6e2082eafeee0c6a0b3d1477268034ac3d0 From 2b3b1037b08fd6927d52a4927f16f5ba2c96b99d Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Fri, 8 Dec 2023 11:30:30 -0300 Subject: [PATCH 28/52] log contract submit producer --- backend/pkg/kafka/producer.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/pkg/kafka/producer.go b/backend/pkg/kafka/producer.go index 701ac8ab..7016a5a8 100644 --- a/backend/pkg/kafka/producer.go +++ b/backend/pkg/kafka/producer.go @@ -17,13 +17,21 @@ func (p *Producer) Produce(key string, value interface{}) error { if err != nil { return fmt.Errorf("Producer - Produce - json.Marshal: %v", err) } + err = p.exec.Produce(&kafka.Message{ Key: []byte(key), TopicPartition: kafka.TopicPartition{Topic: &p.Topic, Partition: kafka.PartitionAny}, Value: valueMarshalled, }, nil) + if err != nil { - return fmt.Errorf("Producer - Produce - p.exec.Produce: %v", err) + //return fmt.Errorf("Producer - Produce - p.exec.Produce: %v", err) + str1 := []byte(key) + str2 := key + str3 := value + str4 := valueMarshalled + return fmt.Errorf(fmt.Sprintf("%s%s%s%s", str1, + str2, str3, str4), err) } return nil From df58f3bfa11cf9ce5c02b84f1069285bbc43674f Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Fri, 8 Dec 2023 11:38:51 -0300 Subject: [PATCH 29/52] producer log --- backend/pkg/kafka/producer.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/pkg/kafka/producer.go b/backend/pkg/kafka/producer.go index 7016a5a8..a0440170 100644 --- a/backend/pkg/kafka/producer.go +++ b/backend/pkg/kafka/producer.go @@ -26,12 +26,11 @@ func (p *Producer) Produce(key string, value interface{}) error { if err != nil { //return fmt.Errorf("Producer - Produce - p.exec.Produce: %v", err) - str1 := []byte(key) - str2 := key - str3 := value - str4 := valueMarshalled - return fmt.Errorf(fmt.Sprintf("%s%s%s%s", str1, - str2, str3, str4), err) + str1 := p.Topic + str2 := value + str3 := valueMarshalled + return fmt.Errorf(fmt.Sprintf("%s %s %s", str1, + str2, str3), err) } return nil From b956c35c0c5d94c4c73c33a35b59951abcf2ceda Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Mon, 11 Dec 2023 10:11:36 -0300 Subject: [PATCH 30/52] Fix GetPaginatedAssets function signature --- backend/internal/usecase/assets.go | 9 ++------- backend/internal/usecase/mocks/mocks.go | 7 ++++--- .../000036_add_idx_wallet_table.down.sql | 15 +++++++++++++++ .../migrations/000036_add_idx_wallet_table.up.sql | 13 +++++++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 backend/migrations/000036_add_idx_wallet_table.down.sql create mode 100644 backend/migrations/000036_add_idx_wallet_table.up.sql diff --git a/backend/internal/usecase/assets.go b/backend/internal/usecase/assets.go index 8c150d56..13cfceab 100644 --- a/backend/internal/usecase/assets.go +++ b/backend/internal/usecase/assets.go @@ -160,10 +160,6 @@ func (uc *AssetUseCase) GetTomlData() (entity.TomlData, error) { return tomParsed, err } -<<<<<<< HEAD -func (uc *AssetUseCase) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, error) { - assets, totalPages, err := uc.aRepo.GetPaginatedAssets(page, limit) -======= func (uc *AssetUseCase) UpdateContractId(assetId string, contractId string) error { err := uc.aRepo.UpdateContractId(assetId, contractId) if err != nil { @@ -172,9 +168,8 @@ func (uc *AssetUseCase) UpdateContractId(assetId string, contractId string) erro return nil } -func (uc *AssetUseCase) GetPaginatedAssets(page int, limit int) ([]entity.Asset, error) { - assets, err := uc.aRepo.GetPaginatedAssets(page, limit) ->>>>>>> soroban-transactions +func (uc *AssetUseCase) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, error) { + assets, totalPages, err := uc.aRepo.GetPaginatedAssets(page, limit) if err != nil { return nil, 0, fmt.Errorf("AssetUseCase - GetPaginated - uc.repo.GetPaginated: %w", err) } diff --git a/backend/internal/usecase/mocks/mocks.go b/backend/internal/usecase/mocks/mocks.go index 1e5b5c03..6dc9e674 100644 --- a/backend/internal/usecase/mocks/mocks.go +++ b/backend/internal/usecase/mocks/mocks.go @@ -462,12 +462,13 @@ func (mr *MockAssetRepoInterfaceMockRecorder) GetAssets() *gomock.Call { } // GetPaginatedAssets mocks base method. -func (m *MockAssetRepoInterface) GetPaginatedAssets(arg0, arg1 int) ([]entity.Asset, error) { +func (m *MockAssetRepoInterface) GetPaginatedAssets(arg0, arg1 int) ([]entity.Asset, int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetPaginatedAssets", arg0, arg1) ret0, _ := ret[0].([]entity.Asset) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(int) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // GetPaginatedAssets indicates an expected call of GetPaginatedAssets. diff --git a/backend/migrations/000036_add_idx_wallet_table.down.sql b/backend/migrations/000036_add_idx_wallet_table.down.sql new file mode 100644 index 00000000..3c1e7d3b --- /dev/null +++ b/backend/migrations/000036_add_idx_wallet_table.down.sql @@ -0,0 +1,15 @@ +-- Removing indexes added for optimization + +-- Asset Table +DROP INDEX idx_asset_name; +DROP INDEX idx_asset_asset_type; +DROP INDEX idx_asset_code; +DROP INDEX idx_asset_distributor_id; +DROP INDEX idx_asset_issuer_id; + +-- Wallet Table +DROP INDEX idx_wallet_type; + +-- Key Table +DROP INDEX idx_key_public_key; +DROP INDEX idx_key_wallet_id; diff --git a/backend/migrations/000036_add_idx_wallet_table.up.sql b/backend/migrations/000036_add_idx_wallet_table.up.sql new file mode 100644 index 00000000..3ac06f7d --- /dev/null +++ b/backend/migrations/000036_add_idx_wallet_table.up.sql @@ -0,0 +1,13 @@ +-- Asset Table +CREATE INDEX idx_asset_name ON Asset(name); +CREATE INDEX idx_asset_asset_type ON Asset(asset_type); +CREATE INDEX idx_asset_code ON Asset(code); +CREATE INDEX idx_asset_distributor_id ON Asset(distributor_id); +CREATE INDEX idx_asset_issuer_id ON Asset(issuer_id); + +-- Wallet Table +CREATE INDEX idx_wallet_type ON Wallet(type); + +-- Key Table +CREATE INDEX idx_key_public_key ON Key(public_key); +CREATE INDEX idx_key_wallet_id ON Key(wallet_id); From 4681e832d2a48a31435aa8e9b220be729875f053 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Mon, 11 Dec 2023 10:15:30 -0300 Subject: [PATCH 31/52] Delete file go --- go | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 go diff --git a/go b/go deleted file mode 100644 index e69de29b..00000000 From 53fb2be14a04e99fda219765ff6b6ce6a230c918 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 11 Dec 2023 10:50:25 -0300 Subject: [PATCH 32/52] fix error log --- backend/pkg/kafka/producer.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/pkg/kafka/producer.go b/backend/pkg/kafka/producer.go index a0440170..dcea4570 100644 --- a/backend/pkg/kafka/producer.go +++ b/backend/pkg/kafka/producer.go @@ -25,12 +25,7 @@ func (p *Producer) Produce(key string, value interface{}) error { }, nil) if err != nil { - //return fmt.Errorf("Producer - Produce - p.exec.Produce: %v", err) - str1 := p.Topic - str2 := value - str3 := valueMarshalled - return fmt.Errorf(fmt.Sprintf("%s %s %s", str1, - str2, str3), err) + return fmt.Errorf("Producer - Produce - p.exec.Produce: %v", err) } return nil From 033da995546f61e4eb0742ab03c0c4c34f4c44c5 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 11 Dec 2023 17:14:03 -0300 Subject: [PATCH 33/52] feat: vault order --- backend/internal/usecase/repo/vault_postgres.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/internal/usecase/repo/vault_postgres.go b/backend/internal/usecase/repo/vault_postgres.go index 3ce4ef7b..0def0f7a 100644 --- a/backend/internal/usecase/repo/vault_postgres.go +++ b/backend/internal/usecase/repo/vault_postgres.go @@ -29,13 +29,14 @@ func (r VaultRepo) GetVaults(isAll bool) ([]entity.Vault, error) { JOIN key wk ON w.id = wk.wallet_id ` - whereClause := `WHERE v.active = 1` + whereClause := ` WHERE v.active = 1` + orderClause := ` ORDER BY v.name ASC` if !isAll { whereClause = whereClause + ` AND v.owner_id is null` } - query := baseQuery + whereClause + query := baseQuery + whereClause + orderClause rows, err := r.Db.Query(query) if err != nil { From 315d239c0ab2f1bb25a3e17de875887a9698d87b Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 11 Dec 2023 21:49:43 -0300 Subject: [PATCH 34/52] log envs submit --- backend/main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/main.go b/backend/main.go index b5d14c04..4a1dd644 100644 --- a/backend/main.go +++ b/backend/main.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "os" + "strings" "github.com/CheesecakeLabs/token-factory-v2/backend/config" "github.com/CheesecakeLabs/token-factory-v2/backend/internal/app" @@ -57,6 +58,8 @@ func main() { go envConn.Run(cfg, entity.EnvelopeChannel) // Kafka submit transaction connection + fmt.Printf("cfg.Kafka.SubmitTransactionCfg.ProducerTopic:" + cfg.Kafka.SubmitTransactionCfg.ProducerTopic) + fmt.Printf(strings.Join(cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, "")) submitConn := kafka.New(cfg.Kafka, cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, cfg.Kafka.SubmitTransactionCfg.ProducerTopic) err = submitConn.AttemptConnect() if err != nil { From e3d34a28dffb5541b73575161887a26dbf24c9bd Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Tue, 12 Dec 2023 09:37:30 -0300 Subject: [PATCH 35/52] log envs --- backend/main.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/main.go b/backend/main.go index 4a1dd644..824187a7 100644 --- a/backend/main.go +++ b/backend/main.go @@ -58,8 +58,14 @@ func main() { go envConn.Run(cfg, entity.EnvelopeChannel) // Kafka submit transaction connection - fmt.Printf("cfg.Kafka.SubmitTransactionCfg.ProducerTopic:" + cfg.Kafka.SubmitTransactionCfg.ProducerTopic) - fmt.Printf(strings.Join(cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, "")) + fmt.Println("cfg.Kafka.SubmitTransactionCfg.ProducerTopic: " + cfg.Kafka.SubmitTransactionCfg.ProducerTopic) + fmt.Println("cfg.Kafka.SubmitTransactionCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, "")) + fmt.Println("cfg.Kafka.SignTransactionCfg.ProducerTopic: " + cfg.Kafka.SignTransactionCfg.ProducerTopic) + fmt.Println("cfg.Kafka.SignTransactionCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.SignTransactionCfg.ConsumerTopics, "")) + fmt.Println("cfg.Kafka.EnvelopeCfg.ProducerTopic: " + cfg.Kafka.EnvelopeCfg.ProducerTopic) + fmt.Println("cfg.Kafka.EnvelopeCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.EnvelopeCfg.ConsumerTopics, "")) + fmt.Println("cfg.Kafka.HorizonCfg.ProducerTopic: " + cfg.Kafka.HorizonCfg.ProducerTopic) + fmt.Println("cfg.Kafka.HorizonCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.HorizonCfg.ConsumerTopics, "")) submitConn := kafka.New(cfg.Kafka, cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, cfg.Kafka.SubmitTransactionCfg.ProducerTopic) err = submitConn.AttemptConnect() if err != nil { From b0df03b666342548f82447adf7fe9554c04143a5 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Tue, 12 Dec 2023 09:38:28 -0300 Subject: [PATCH 36/52] log envs --- backend/main.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/main.go b/backend/main.go index 824187a7..45dbde02 100644 --- a/backend/main.go +++ b/backend/main.go @@ -58,14 +58,14 @@ func main() { go envConn.Run(cfg, entity.EnvelopeChannel) // Kafka submit transaction connection - fmt.Println("cfg.Kafka.SubmitTransactionCfg.ProducerTopic: " + cfg.Kafka.SubmitTransactionCfg.ProducerTopic) - fmt.Println("cfg.Kafka.SubmitTransactionCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, "")) - fmt.Println("cfg.Kafka.SignTransactionCfg.ProducerTopic: " + cfg.Kafka.SignTransactionCfg.ProducerTopic) - fmt.Println("cfg.Kafka.SignTransactionCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.SignTransactionCfg.ConsumerTopics, "")) - fmt.Println("cfg.Kafka.EnvelopeCfg.ProducerTopic: " + cfg.Kafka.EnvelopeCfg.ProducerTopic) - fmt.Println("cfg.Kafka.EnvelopeCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.EnvelopeCfg.ConsumerTopics, "")) - fmt.Println("cfg.Kafka.HorizonCfg.ProducerTopic: " + cfg.Kafka.HorizonCfg.ProducerTopic) - fmt.Println("cfg.Kafka.HorizonCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.HorizonCfg.ConsumerTopics, "")) + log.Println("cfg.Kafka.SubmitTransactionCfg.ProducerTopic: " + cfg.Kafka.SubmitTransactionCfg.ProducerTopic) + log.Println("cfg.Kafka.SubmitTransactionCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, "")) + log.Println("cfg.Kafka.SignTransactionCfg.ProducerTopic: " + cfg.Kafka.SignTransactionCfg.ProducerTopic) + log.Println("cfg.Kafka.SignTransactionCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.SignTransactionCfg.ConsumerTopics, "")) + log.Println("cfg.Kafka.EnvelopeCfg.ProducerTopic: " + cfg.Kafka.EnvelopeCfg.ProducerTopic) + log.Println("cfg.Kafka.EnvelopeCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.EnvelopeCfg.ConsumerTopics, "")) + log.Println("cfg.Kafka.HorizonCfg.ProducerTopic: " + cfg.Kafka.HorizonCfg.ProducerTopic) + log.Println("cfg.Kafka.HorizonCfg.ConsumerTopics: " + strings.Join(cfg.Kafka.HorizonCfg.ConsumerTopics, "")) submitConn := kafka.New(cfg.Kafka, cfg.Kafka.SubmitTransactionCfg.ConsumerTopics, cfg.Kafka.SubmitTransactionCfg.ProducerTopic) err = submitConn.AttemptConnect() if err != nil { From c6cdf27742e355f4e8ab156867792648ef19246b Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Tue, 12 Dec 2023 17:37:25 -0300 Subject: [PATCH 37/52] fix logout --- backend/internal/controller/http/v1/users.go | 12 +++++++----- backend/internal/usecase/repo/contract_postgres.go | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/internal/controller/http/v1/users.go b/backend/internal/controller/http/v1/users.go index fb775270..12794705 100644 --- a/backend/internal/controller/http/v1/users.go +++ b/backend/internal/controller/http/v1/users.go @@ -143,13 +143,15 @@ func (r *usersRoutes) autentication(c *gin.Context) { // @Failure 500 {object} response // @Router /user/logout [post] func (r *usersRoutes) logout(c *gin.Context) { - var user entity.User - if err := c.ShouldBindJSON(&user); err != nil { - r.l.Error(err, "http - v1 - logout - ShouldBindJSON") - errorResponse(c, http.StatusBadRequest, "invalid request body", err) + token := c.GetHeader("Authorization") + user, err := r.t.GetUserByToken(token) + if err != nil { + r.l.Error(err, "http - v1 - getUserByToken - GetUserByToken") + errorResponse(c, http.StatusInternalServerError, "database problems", err) return } - err := r.a.UpdateToken(user.Email, "") + + err = r.a.UpdateToken(user.ID, "") if err != nil { r.l.Error(err, "http - v1 - logout - UpdateToken") errorResponse(c, http.StatusInternalServerError, "error updating token", err) diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index a46837a3..140489ff 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -40,6 +40,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { JOIN key dk ON d.id = dk.wallet_id JOIN wallet i ON a.issuer_id = i.id JOIN key ik ON i.id = ik.wallet_id + ORDER BY c.id DESC ` rows, err := r.Db.Query(query) From 2672a4dbd815433e3a4ba14d3e320330d0490045 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Tue, 12 Dec 2023 17:41:04 -0300 Subject: [PATCH 38/52] fix logout new token --- backend/internal/controller/http/v1/users.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/internal/controller/http/v1/users.go b/backend/internal/controller/http/v1/users.go index 12794705..ae8e6077 100644 --- a/backend/internal/controller/http/v1/users.go +++ b/backend/internal/controller/http/v1/users.go @@ -151,7 +151,7 @@ func (r *usersRoutes) logout(c *gin.Context) { return } - err = r.a.UpdateToken(user.ID, "") + err = r.a.UpdateToken(user.ID, user.ID) if err != nil { r.l.Error(err, "http - v1 - logout - UpdateToken") errorResponse(c, http.StatusInternalServerError, "error updating token", err) From 64145b1f863203ff6a8d0d4b8fc9971c7b40bda0 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Wed, 13 Dec 2023 10:44:54 -0300 Subject: [PATCH 39/52] add s3 bucket in the aws service --- backend/config/config.go | 4 ++ backend/pkg/aws/aws_ses_service.go | 38 +++++++++++++++++++ backend/pkg/aws/s3.go | 23 ++++++++++++ backend/pkg/aws/server.go | 27 ++++++++++++++ backend/pkg/email/aws_ses_service.go | 55 ---------------------------- 5 files changed, 92 insertions(+), 55 deletions(-) create mode 100644 backend/pkg/aws/aws_ses_service.go create mode 100644 backend/pkg/aws/s3.go create mode 100644 backend/pkg/aws/server.go delete mode 100644 backend/pkg/email/aws_ses_service.go diff --git a/backend/config/config.go b/backend/config/config.go index ee2c5a98..694a67d9 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -48,6 +48,10 @@ type ( JWT struct { SecretKey string `env-required:"true" env:"JWT_SECRET_KEY"` } + + AWS struct { + BucketName string `env-required:"true" env:"AWS_BUCKET_NAME"` + } ) // NewConfig returns app config. diff --git a/backend/pkg/aws/aws_ses_service.go b/backend/pkg/aws/aws_ses_service.go new file mode 100644 index 00000000..53bb4f53 --- /dev/null +++ b/backend/pkg/aws/aws_ses_service.go @@ -0,0 +1,38 @@ +package aws + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ses" +) + +func (s *AwsConnection) SendEmail(to, subject, body string) error { + input := &ses.SendEmailInput{ + Destination: &ses.Destination{ + ToAddresses: []*string{ + aws.String(to), + }, + }, + Message: &ses.Message{ + Body: &ses.Body{ + Html: &ses.Content{ + Charset: aws.String("UTF-8"), + Data: aws.String(body), + }, + }, + Subject: &ses.Content{ + Charset: aws.String("UTF-8"), + Data: aws.String(subject), + }, + }, + Source: aws.String("your-email@example.com"), // TODO: Change this + } + + _, err := s.emailClient.SendEmail(input) + if err != nil { + return fmt.Errorf("failed to send email: %v", err) + } + + return nil +} diff --git a/backend/pkg/aws/s3.go b/backend/pkg/aws/s3.go new file mode 100644 index 00000000..42e3e78b --- /dev/null +++ b/backend/pkg/aws/s3.go @@ -0,0 +1,23 @@ +package aws + +import ( + "bytes" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/s3/s3manager" +) + +func (s *AwsConnection) uploadToS3(file []byte, filename string) (string, error) { + uploader := s3manager.NewUploader(s.session) + + result, err := uploader.Upload(&s3manager.UploadInput{ + Bucket: aws.String(s.bucketName), + Key: aws.String(filename), + Body: bytes.NewReader(file), + }) + if err != nil { + return "", err + } + + return result.Location, nil +} diff --git a/backend/pkg/aws/server.go b/backend/pkg/aws/server.go new file mode 100644 index 00000000..c3dffd65 --- /dev/null +++ b/backend/pkg/aws/server.go @@ -0,0 +1,27 @@ +package aws + +import ( + "github.com/CheesecakeLabs/token-factory-v2/backend/config" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ses" +) + +type AwsConnection struct { + session *session.Session + emailClient *ses.SES + bucketName string +} + +// Initialize a session with AWS +func NewAwsService(cfg config.AWS) (*AwsConnection, error) { + sess, err := session.NewSession() + if err != nil { + return &AwsConnection{}, err + } + + return &AwsConnection{ + session: sess, + emailClient: ses.New(sess), + bucketName: cfg.BucketName, + }, nil +} diff --git a/backend/pkg/email/aws_ses_service.go b/backend/pkg/email/aws_ses_service.go deleted file mode 100644 index d0ad512c..00000000 --- a/backend/pkg/email/aws_ses_service.go +++ /dev/null @@ -1,55 +0,0 @@ -package email - -import ( - "fmt" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ses" -) - -type AwsSesService struct { - client *ses.SES -} - -func NewAwsSesService() *AwsSesService { - sess := session.Must(session.NewSession(&aws.Config{ - Region: aws.String("YOUR_AWS_REGION"), // TODO: Change this - Credentials: credentials.NewStaticCredentials("YOUR_AWS_ACCESS_KEY_ID", "YOUR_AWS_SECRET_ACCESS_KEY", ""), // TODO: Change this - })) - - return &AwsSesService{ - client: ses.New(sess), - } -} - -func (s *AwsSesService) SendEmail(to, subject, body string) error { - input := &ses.SendEmailInput{ - Destination: &ses.Destination{ - ToAddresses: []*string{ - aws.String(to), - }, - }, - Message: &ses.Message{ - Body: &ses.Body{ - Html: &ses.Content{ - Charset: aws.String("UTF-8"), - Data: aws.String(body), - }, - }, - Subject: &ses.Content{ - Charset: aws.String("UTF-8"), - Data: aws.String(subject), - }, - }, - Source: aws.String("your-email@example.com"), // TODO: Change this - } - - _, err := s.client.SendEmail(input) - if err != nil { - return fmt.Errorf("failed to send email: %v", err) - } - - return nil -} From 4d4841bfc3192111e17bb1c67a693c2ff1e2c0e2 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Wed, 13 Dec 2023 11:26:29 -0300 Subject: [PATCH 40/52] Add the s3 interface --- backend/config/config.go | 1 + backend/internal/app/app.go | 8 ++++- backend/internal/controller/http/v1/assets.go | 6 ++-- backend/internal/entity/asset.go | 2 +- backend/internal/usecase/assets.go | 35 ++++++++++++------- backend/internal/usecase/interfaces.go | 5 +++ .../internal/usecase/service/asset_service.go | 21 +++++++++++ .../internal/usecase/users/reset_password.go | 10 +++--- backend/main.go | 10 +++++- backend/pkg/aws/s3.go | 2 +- backend/pkg/aws/server.go | 2 +- 11 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 backend/internal/usecase/service/asset_service.go diff --git a/backend/config/config.go b/backend/config/config.go index 6770050a..bc8a057e 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -13,6 +13,7 @@ type ( JWT JWT Horizon Horizon Log Log + AWS AWS } Log struct { diff --git a/backend/internal/app/app.go b/backend/internal/app/app.go index 2a728d97..8eb485c2 100644 --- a/backend/internal/app/app.go +++ b/backend/internal/app/app.go @@ -15,6 +15,8 @@ import ( "github.com/CheesecakeLabs/token-factory-v2/backend/internal/entity" "github.com/CheesecakeLabs/token-factory-v2/backend/internal/usecase" "github.com/CheesecakeLabs/token-factory-v2/backend/internal/usecase/repo" + "github.com/CheesecakeLabs/token-factory-v2/backend/internal/usecase/service" + "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/aws" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/httpserver" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/logger" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/postgres" @@ -22,8 +24,9 @@ import ( ) // Run creates objects via constructors. -func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv entity.ProducerInterface, tRepo *toml.DefaultTomlGenerator) { +func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv entity.ProducerInterface, tRepo *toml.DefaultTomlGenerator, pAws *aws.AwsConnection) { l := logger.New(cfg.Log.Level) + // Use cases authUc := usecase.NewAuthUseCase( repo.New(pg), cfg.JWT.SecretKey, @@ -34,13 +37,16 @@ func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv entity.Produ walletUc := usecase.NewWalletUseCase( repo.NewWalletRepo(pg), ) + assetUc := usecase.NewAssetUseCase( repo.NewAssetRepo(pg), repo.NewWalletRepo(pg), tRepo, repo.NewTomlRepo(pg), cfg.Horizon, + service.NewAssetService(pAws), ) + roleUc := usecase.NewRoleUseCase( repo.NewRoleRepo(pg), ) diff --git a/backend/internal/controller/http/v1/assets.go b/backend/internal/controller/http/v1/assets.go index 6ed8a063..0bf900b4 100644 --- a/backend/internal/controller/http/v1/assets.go +++ b/backend/internal/controller/http/v1/assets.go @@ -129,6 +129,8 @@ type UploadAssetImageRequest struct { // @Router /assets [post] func (r *assetsRoutes) createAsset(c *gin.Context) { var request CreateAssetRequest + var imageBytes []byte + if err := c.ShouldBindJSON(&request); err != nil { r.logger.Error(err, "http - v1 - create asset - bind") errorResponse(c, http.StatusBadRequest, fmt.Sprintf("invalid request body: %s", err.Error()), err) @@ -268,7 +270,7 @@ func (r *assetsRoutes) createAsset(c *gin.Context) { } if request.Image != "" { - asset.Image, err = base64.StdEncoding.DecodeString(request.Image) + imageBytes, err = base64.StdEncoding.DecodeString(request.Image) if err != nil { r.logger.Error(err, "http - v1 - create asset - decode image") errorResponse(c, http.StatusBadRequest, "Failed to decode base64 image", err) @@ -276,7 +278,7 @@ func (r *assetsRoutes) createAsset(c *gin.Context) { } } - asset, err = r.as.Create(asset) + asset, err = r.as.Create(asset, imageBytes) if err != nil { r.logger.Error(err, "http - v1 - create asset - create asset") errorResponse(c, http.StatusNotFound, "database problems", err) diff --git a/backend/internal/entity/asset.go b/backend/internal/entity/asset.go index 66eb9568..702fb4ba 100644 --- a/backend/internal/entity/asset.go +++ b/backend/internal/entity/asset.go @@ -8,7 +8,7 @@ type Asset struct { Issuer Wallet `json:"issuer"` Amount int `json:"amount" example:"1000000"` AssetType string `json:"asset_type"` - Image []byte `json:"image,omitempty"` + Image string `json:"image,omitempty"` } const ( diff --git a/backend/internal/usecase/assets.go b/backend/internal/usecase/assets.go index 0a5fb611..db91c57e 100644 --- a/backend/internal/usecase/assets.go +++ b/backend/internal/usecase/assets.go @@ -8,24 +8,26 @@ import ( ) type AssetUseCase struct { - aRepo AssetRepoInterface - wRepo WalletRepoInterface - tInt TomlInterface - tRepo TomlRepoInterface - cfg config.Horizon + aRepo AssetRepoInterface + wRepo WalletRepoInterface + tInt TomlInterface + tRepo TomlRepoInterface + cfg config.Horizon + awsService AssetServiceInterface } -func NewAssetUseCase(aRepo AssetRepoInterface, wRepo WalletRepoInterface, tInt TomlInterface, tRepo TomlRepoInterface, cfg config.Horizon) *AssetUseCase { +func NewAssetUseCase(aRepo AssetRepoInterface, wRepo WalletRepoInterface, tInt TomlInterface, tRepo TomlRepoInterface, cfg config.Horizon, awsService AssetServiceInterface) *AssetUseCase { return &AssetUseCase{ - aRepo: aRepo, - wRepo: wRepo, - tInt: tInt, - tRepo: tRepo, - cfg: cfg, + aRepo: aRepo, + wRepo: wRepo, + tInt: tInt, + tRepo: tRepo, + cfg: cfg, + awsService: awsService, } } -func (uc *AssetUseCase) Create(data entity.Asset) (entity.Asset, error) { +func (uc *AssetUseCase) Create(data entity.Asset, imageBytes []byte) (entity.Asset, error) { issuer, err := uc.wRepo.CreateWalletWithKey(data.Issuer) if err != nil { return entity.Asset{}, fmt.Errorf("AssetUseCase - Create - uc.repo.CreateWalletWithKey(issuer): %w", err) @@ -38,6 +40,15 @@ func (uc *AssetUseCase) Create(data entity.Asset) (entity.Asset, error) { } data.Distributor.Id = dist.Id + // Upload image to S3 if exists + if len(imageBytes) > 0 { + assetImage, err := uc.awsService.UploadAssetImage(data.Code, imageBytes) + if err != nil { + return entity.Asset{}, fmt.Errorf("AssetUseCase - Create - uc.awsService.UploadAssetImage: %w", err) + } + data.Image = assetImage + } + asset, err := uc.aRepo.CreateAsset(data) if err != nil { return entity.Asset{}, fmt.Errorf("AssetUseCase - Create - uc.repo.CreateWallet: %w", err) diff --git a/backend/internal/usecase/interfaces.go b/backend/internal/usecase/interfaces.go index 4497716a..0824986f 100644 --- a/backend/internal/usecase/interfaces.go +++ b/backend/internal/usecase/interfaces.go @@ -116,4 +116,9 @@ type ( SumLogTransactionSupply(timeRange string, timeFrame time.Duration) ([]entity.SumLogTransactionSupply, error) LogTransactionSupplyByAssetID(assetID int, timeRange string, periodInitial string, interval string) (entity.LogTransactionSupply, error) } + + // Asset Service + AssetServiceInterface interface { + UploadAssetImage(string, []byte) (string, error) + } ) diff --git a/backend/internal/usecase/service/asset_service.go b/backend/internal/usecase/service/asset_service.go new file mode 100644 index 00000000..cf4147a0 --- /dev/null +++ b/backend/internal/usecase/service/asset_service.go @@ -0,0 +1,21 @@ +package service + +import ( + "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/aws" +) + +type AssetService struct { + *aws.AwsConnection +} + +func NewAssetService(aws *aws.AwsConnection) *AssetService { + return &AssetService{aws} +} + +func (s *AssetService) UploadAssetImage(filename string, file []byte) (string, error) { + url, err := s.UploadToS3(filename, file) + if err != nil { + return "", err + } + return url, nil +} diff --git a/backend/internal/usecase/users/reset_password.go b/backend/internal/usecase/users/reset_password.go index 20ba1205..f098e35d 100644 --- a/backend/internal/usecase/users/reset_password.go +++ b/backend/internal/usecase/users/reset_password.go @@ -1,7 +1,7 @@ package usecase -func (uc *UserUseCase) Execute(email string) error { - // Generate reset token and save it in the database - // Call the email service to send the reset link - return nil -} +// func (uc *UserUseCase) Execute(email string) error { +// // Generate reset token and save it in the database +// // Call the email service to send the reset link +// return nil +// } diff --git a/backend/main.go b/backend/main.go index da7dcc1d..a4df4cc2 100644 --- a/backend/main.go +++ b/backend/main.go @@ -8,6 +8,7 @@ import ( "github.com/CheesecakeLabs/token-factory-v2/backend/config" "github.com/CheesecakeLabs/token-factory-v2/backend/internal/app" "github.com/CheesecakeLabs/token-factory-v2/backend/internal/entity" + "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/aws" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/kafka" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/postgres" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/toml" @@ -29,6 +30,13 @@ func main() { } defer pg.Close() + // AWS Service + // TODO if is not production, use mock + awsService, err := aws.New(cfg.AWS) + if err != nil { + log.Fatal("app - Run - aws.NewAwsService: %w", err) + } + // Kafka create keypair connection kpConn := kafka.New(cfg.Kafka, cfg.Kafka.CreateKpCfg.ConsumerTopics, cfg.Kafka.CreateKpCfg.ProducerTopic) err = kpConn.AttemptConnect() @@ -56,5 +64,5 @@ func main() { } go envConn.Run(cfg, entity.EnvelopeChannel) - app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer, tRepo) + app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer, tRepo, awsService) } diff --git a/backend/pkg/aws/s3.go b/backend/pkg/aws/s3.go index 42e3e78b..6bf5426c 100644 --- a/backend/pkg/aws/s3.go +++ b/backend/pkg/aws/s3.go @@ -7,7 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/s3/s3manager" ) -func (s *AwsConnection) uploadToS3(file []byte, filename string) (string, error) { +func (s *AwsConnection) UploadToS3(filename string, file []byte) (string, error) { uploader := s3manager.NewUploader(s.session) result, err := uploader.Upload(&s3manager.UploadInput{ diff --git a/backend/pkg/aws/server.go b/backend/pkg/aws/server.go index c3dffd65..b59aad65 100644 --- a/backend/pkg/aws/server.go +++ b/backend/pkg/aws/server.go @@ -13,7 +13,7 @@ type AwsConnection struct { } // Initialize a session with AWS -func NewAwsService(cfg config.AWS) (*AwsConnection, error) { +func New(cfg config.AWS) (*AwsConnection, error) { sess, err := session.NewSession() if err != nil { return &AwsConnection{}, err From 2d16604b6e458010dc12caaae5986b482df2c85b Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Wed, 13 Dec 2023 11:42:21 -0300 Subject: [PATCH 41/52] Change the upload image function --- backend/go.mod | 1 + backend/go.sum | 250 +------------------------------------------------ 2 files changed, 3 insertions(+), 248 deletions(-) diff --git a/backend/go.mod b/backend/go.mod index 168216d5..408d7d28 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -48,6 +48,7 @@ require ( github.com/invopop/jsonschema v0.12.0 // indirect github.com/itchyny/gojq v0.12.13 // indirect github.com/itchyny/timefmt-go v0.1.5 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/k0kubun/pp v3.0.1+incompatible // indirect diff --git a/backend/go.sum b/backend/go.sum index 0fd929fa..bcc4340c 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -28,70 +28,20 @@ github.com/actgardner/gogen-avro/v9 v9.1.0/go.mod h1:nyTj6wPqDJoxM3qdnjcLv+EnMDS github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= -<<<<<<< HEAD -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.48.0 h1:1SeJ8agckRDQvnSCt1dGZYAwUaoD2Ixj6IaXB4LCv8Q= -github.com/aws/aws-sdk-go v1.48.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= -github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= -github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU= -github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= -github.com/aws/aws-sdk-go-v2/credentials v1.3.2/go.mod h1:PACKuTJdt6AlXvEq8rFI4eDmoqDFC5DpVKQbWysaDgM= -github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.0/go.mod h1:Mj/U8OpDbcVcoctrYwA2bak8k/HFPdcLzI/vaiXMwuM= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.4.0/go.mod h1:eHwXu2+uE/T6gpnYWwBwqoeqRf9IXyCcolyOWDRAErQ= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.5.4/go.mod h1:Ex7XQmbFmgFHrjUX6TN3mApKW5Hglyga+F7wZHTtYhA= -github.com/aws/aws-sdk-go-v2/internal/ini v1.2.0/go.mod h1:Q5jATQc+f1MfZp3PDMhn6ry18hGvE0i8yvbXoKbnZaE= -github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.2/go.mod h1:EASdTcM1lGhUe1/p4gkojHwlGJkeoRjjr1sRCzup3Is= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.3.0/go.mod h1:v8ygadNyATSm6elwJ/4gzJwcFhri9RqS8skgHKiwXPU= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.2/go.mod h1:NXmNI41bdEsJMrD0v9rUvbGCB5GwdBEpKvUvIY3vTFg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.2/go.mod h1:QuL2Ym8BkrLmN4lUofXYq6000/i5jPjosCNK//t6gak= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.2/go.mod h1:np7TMuJNT83O0oDOSF8i4dF3dvGqA6hPYYo6YYkzgRA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.12.0/go.mod h1:6J++A5xpo7QDsIeSqPK4UHqMSyPOCopa+zKtqAMhqVQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.16.1/go.mod h1:CQe/KvWV1AqRc65KqeJjrLzr5X2ijnFTTVzJW0VBRCI= -github.com/aws/aws-sdk-go-v2/service/sso v1.3.2/go.mod h1:J21I6kF+d/6XHVk7kp/cx9YVD2TMD2TbLwtRGVcinXo= -github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= -github.com/aws/aws-sdk-go-v2/service/sts v1.6.1/go.mod h1:hLZ/AnkIKHLuPGjEiyghNEdvJ2PP0MgOxcmv9EBJ4xs= -github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= -github.com/aws/smithy-go v1.7.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= -======= github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA= github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= +github.com/aws/aws-sdk-go v1.48.0 h1:1SeJ8agckRDQvnSCt1dGZYAwUaoD2Ixj6IaXB4LCv8Q= +github.com/aws/aws-sdk-go v1.48.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= ->>>>>>> dev github.com/bitly/go-notify v0.0.0-20130217044602-0a148b8111d6 h1:ybynk3s3i+9K288wkO0umbIyMSEE+MktDHFLfLo2yEc= github.com/bitly/go-notify v0.0.0-20130217044602-0a148b8111d6/go.mod h1:zL/tIQvZCBq2zM4ta8HeCRQsjppFaCbpZfd+JNwKNC4= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -<<<<<<< HEAD -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -======= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= ->>>>>>> dev github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= @@ -136,56 +86,14 @@ github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHs github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= -<<<<<<< HEAD -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= -github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= -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/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -======= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= ->>>>>>> dev github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= 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= -<<<<<<< HEAD -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -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-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -======= ->>>>>>> dev github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -206,42 +114,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 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= -<<<<<<< HEAD -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.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -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/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= ->>>>>>> dev 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= @@ -316,23 +190,10 @@ github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+ github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= -<<<<<<< HEAD -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -======= ->>>>>>> dev github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -359,24 +220,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -<<<<<<< HEAD -github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4= -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/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -======= 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/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= ->>>>>>> dev github.com/linkedin/goavro v2.1.0+incompatible/go.mod h1:bBCwI2eGYpUI/4820s67MElg9tdeLbINjLjiM2xZFYM= github.com/linkedin/goavro/v2 v2.10.0/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= github.com/linkedin/goavro/v2 v2.10.1/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= @@ -393,16 +240,10 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -<<<<<<< HEAD -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/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -======= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= ->>>>>>> dev github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= @@ -418,45 +259,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nrwiersma/avro-benchmarks v0.0.0-20210913175520-21aec48c8f76/go.mod h1:iKyFMidsk/sVYONJRE372sJuX/QTRPacU7imPqqsu7g= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -<<<<<<< HEAD -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -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/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -======= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= ->>>>>>> dev github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -491,14 +295,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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= -<<<<<<< HEAD -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -======= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= ->>>>>>> dev github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= @@ -538,18 +336,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -<<<<<<< HEAD -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -<<<<<<< HEAD -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -======= ->>>>>>> dev -======= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= ->>>>>>> soroban-transactions golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -579,10 +367,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -<<<<<<< HEAD -golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -======= ->>>>>>> dev golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -615,20 +399,9 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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= -<<<<<<< HEAD -<<<<<<< HEAD -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -======= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ->>>>>>> dev -======= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= ->>>>>>> soroban-transactions 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= @@ -639,27 +412,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -<<<<<<< HEAD -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -<<<<<<< HEAD -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -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-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -======= ->>>>>>> dev -======= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= ->>>>>>> soroban-transactions 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= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 628182f077e9ce0a5bbdab83d0687dcb564cd91b Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Thu, 14 Dec 2023 17:19:17 -0300 Subject: [PATCH 42/52] Add the local storage method --- .gitignore | 1 + backend/.env.example | 3 ++ backend/.gitignore | 2 +- backend/config/config.go | 5 +++ backend/internal/app/app.go | 6 +-- backend/internal/usecase/assets.go | 30 +++++++------- backend/internal/usecase/interfaces.go | 2 +- backend/internal/usecase/mocks/mocks.go | 40 ++++++++++++++++++- .../internal/usecase/service/asset_service.go | 12 +++--- backend/main.go | 27 ++++++++++--- backend/pkg/aws/s3.go | 7 +++- backend/pkg/aws/server.go | 4 ++ backend/pkg/localstorage/storage.go | 22 ++++++++++ backend/pkg/storage/storage.go | 5 +++ 14 files changed, 132 insertions(+), 34 deletions(-) create mode 100644 backend/pkg/localstorage/storage.go create mode 100644 backend/pkg/storage/storage.go diff --git a/.gitignore b/.gitignore index e43b0f98..9382b808 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +*.png diff --git a/backend/.env.example b/backend/.env.example index eb6f0cfd..978b47cd 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -5,6 +5,9 @@ PG_USER= PG_PASSWORD= PG_DB_NAME= +# Deploy Stage +DEPLOY_STAGE=local + # Kafka KAFKA_CLIENT_GROUP_ID= KAFKA_CLIENT_BROKERS= diff --git a/backend/.gitignore b/backend/.gitignore index 655f0217..a0783c3f 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -25,4 +25,4 @@ starlabs # vendor/ # Go workspace file -go.work \ No newline at end of file +go.work diff --git a/backend/config/config.go b/backend/config/config.go index ccca57bf..a8b673ac 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -14,6 +14,7 @@ type ( Horizon Horizon Log Log AWS AWS + Deploy Deploy } Log struct { @@ -105,6 +106,10 @@ type ( IDPhotoHash string `env:"PRINCIPALS_ID_PHOTO_HASH"` VerificationPhotoHash string `env:"PRINCIPALS_VERIFICATION_PHOTO_HASH"` } + + Deploy struct { + DeployStage string `env:"DEPLOY_STAGE"` + } ) // NewConfig returns app config. diff --git a/backend/internal/app/app.go b/backend/internal/app/app.go index c6525c0e..1a6c3947 100644 --- a/backend/internal/app/app.go +++ b/backend/internal/app/app.go @@ -16,15 +16,15 @@ import ( "github.com/CheesecakeLabs/token-factory-v2/backend/internal/usecase" "github.com/CheesecakeLabs/token-factory-v2/backend/internal/usecase/repo" "github.com/CheesecakeLabs/token-factory-v2/backend/internal/usecase/service" - "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/aws" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/httpserver" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/logger" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/postgres" + "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/storage" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/toml" ) // Run creates objects via constructors. -func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv, pSub, pSig entity.ProducerInterface, tRepo *toml.DefaultTomlGenerator, pAws *aws.AwsConnection) { +func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv, pSub, pSig entity.ProducerInterface, tRepo *toml.DefaultTomlGenerator, storageService storage.StorageService) { l := logger.New(cfg.Log.Level) // Use cases @@ -44,7 +44,7 @@ func Run(cfg *config.Config, pg *postgres.Postgres, pKp, pHor, pEnv, pSub, pSig tRepo, repo.NewTomlRepo(pg), cfg.Horizon, - service.NewAssetService(pAws), + service.NewAssetService(storageService), ) roleUc := usecase.NewRoleUseCase( diff --git a/backend/internal/usecase/assets.go b/backend/internal/usecase/assets.go index 141ee99b..5f8bacf4 100644 --- a/backend/internal/usecase/assets.go +++ b/backend/internal/usecase/assets.go @@ -8,22 +8,22 @@ import ( ) type AssetUseCase struct { - aRepo AssetRepoInterface - wRepo WalletRepoInterface - tInt TomlInterface - tRepo TomlRepoInterface - cfg config.Horizon - awsService AssetServiceInterface + aRepo AssetRepoInterface + wRepo WalletRepoInterface + tInt TomlInterface + tRepo TomlRepoInterface + cfg config.Horizon + storageService AssetServiceInterface } -func NewAssetUseCase(aRepo AssetRepoInterface, wRepo WalletRepoInterface, tInt TomlInterface, tRepo TomlRepoInterface, cfg config.Horizon, awsService AssetServiceInterface) *AssetUseCase { +func NewAssetUseCase(aRepo AssetRepoInterface, wRepo WalletRepoInterface, tInt TomlInterface, tRepo TomlRepoInterface, cfg config.Horizon, storageService AssetServiceInterface) *AssetUseCase { return &AssetUseCase{ - aRepo: aRepo, - wRepo: wRepo, - tInt: tInt, - tRepo: tRepo, - cfg: cfg, - awsService: awsService, + aRepo: aRepo, + wRepo: wRepo, + tInt: tInt, + tRepo: tRepo, + cfg: cfg, + storageService: storageService, } } @@ -42,7 +42,7 @@ func (uc *AssetUseCase) Create(data entity.Asset, imageBytes []byte) (entity.Ass // Upload image to S3 if exists if len(imageBytes) > 0 { - assetImage, err := uc.awsService.UploadAssetImage(fmt.Sprint(data.Id), imageBytes) + assetImage, err := uc.storageService.UploadFile(fmt.Sprint(data.Id), imageBytes) if err != nil { return entity.Asset{}, fmt.Errorf("AssetUseCase - Create - uc.awsService.UploadAssetImage: %w", err) } @@ -85,7 +85,7 @@ func (uc *AssetUseCase) GetAll() ([]entity.Asset, error) { } func (uc *AssetUseCase) UploadImage(assetId string, imageBytes []byte) error { - assetImage, err := uc.awsService.UploadAssetImage(assetId, imageBytes) + assetImage, err := uc.storageService.UploadFile(assetId, imageBytes) if err != nil { return fmt.Errorf("AssetUseCase - Create - uc.awsService.UploadAssetImage: %w", err) } diff --git a/backend/internal/usecase/interfaces.go b/backend/internal/usecase/interfaces.go index 327e990e..bbdc2bbc 100644 --- a/backend/internal/usecase/interfaces.go +++ b/backend/internal/usecase/interfaces.go @@ -123,6 +123,6 @@ type ( // Asset Service AssetServiceInterface interface { - UploadAssetImage(string, []byte) (string, error) + UploadFile(string, []byte) (string, error) } ) diff --git a/backend/internal/usecase/mocks/mocks.go b/backend/internal/usecase/mocks/mocks.go index 6dc9e674..89b56986 100644 --- a/backend/internal/usecase/mocks/mocks.go +++ b/backend/internal/usecase/mocks/mocks.go @@ -478,7 +478,7 @@ func (mr *MockAssetRepoInterfaceMockRecorder) GetPaginatedAssets(arg0, arg1 inte } // StoreAssetImage mocks base method. -func (m *MockAssetRepoInterface) StoreAssetImage(arg0 string, arg1 []byte) error { +func (m *MockAssetRepoInterface) StoreAssetImage(arg0, arg1 string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "StoreAssetImage", arg0, arg1) ret0, _ := ret[0].(error) @@ -1317,3 +1317,41 @@ func (mr *MockLogTransactionRepoInterfaceMockRecorder) SumLogTransactionsByAsset mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SumLogTransactionsByAssetID", reflect.TypeOf((*MockLogTransactionRepoInterface)(nil).SumLogTransactionsByAssetID), assetID, timeRange, timeFrame, transactionType) } + +// MockAssetServiceInterface is a mock of AssetServiceInterface interface. +type MockAssetServiceInterface struct { + ctrl *gomock.Controller + recorder *MockAssetServiceInterfaceMockRecorder +} + +// MockAssetServiceInterfaceMockRecorder is the mock recorder for MockAssetServiceInterface. +type MockAssetServiceInterfaceMockRecorder struct { + mock *MockAssetServiceInterface +} + +// NewMockAssetServiceInterface creates a new mock instance. +func NewMockAssetServiceInterface(ctrl *gomock.Controller) *MockAssetServiceInterface { + mock := &MockAssetServiceInterface{ctrl: ctrl} + mock.recorder = &MockAssetServiceInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAssetServiceInterface) EXPECT() *MockAssetServiceInterfaceMockRecorder { + return m.recorder +} + +// UploadAssetImage mocks base method. +func (m *MockAssetServiceInterface) UploadAssetImage(arg0 string, arg1 []byte) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UploadAssetImage", arg0, arg1) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UploadAssetImage indicates an expected call of UploadAssetImage. +func (mr *MockAssetServiceInterfaceMockRecorder) UploadAssetImage(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UploadAssetImage", reflect.TypeOf((*MockAssetServiceInterface)(nil).UploadAssetImage), arg0, arg1) +} diff --git a/backend/internal/usecase/service/asset_service.go b/backend/internal/usecase/service/asset_service.go index cf4147a0..073ca428 100644 --- a/backend/internal/usecase/service/asset_service.go +++ b/backend/internal/usecase/service/asset_service.go @@ -1,19 +1,19 @@ package service import ( - "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/aws" + "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/storage" ) type AssetService struct { - *aws.AwsConnection + storageService storage.StorageService } -func NewAssetService(aws *aws.AwsConnection) *AssetService { - return &AssetService{aws} +func NewAssetService(storage storage.StorageService) *AssetService { + return &AssetService{storageService: storage} } -func (s *AssetService) UploadAssetImage(filename string, file []byte) (string, error) { - url, err := s.UploadToS3(filename, file) +func (s *AssetService) UploadFile(filename string, file []byte) (string, error) { + url, err := s.storageService.UploadFile(filename, file) if err != nil { return "", err } diff --git a/backend/main.go b/backend/main.go index 4aedac9d..d1f3b4cd 100644 --- a/backend/main.go +++ b/backend/main.go @@ -10,7 +10,9 @@ import ( "github.com/CheesecakeLabs/token-factory-v2/backend/internal/entity" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/aws" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/kafka" + local "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/localstorage" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/postgres" + "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/storage" "github.com/CheesecakeLabs/token-factory-v2/backend/pkg/toml" ) @@ -30,11 +32,24 @@ func main() { } defer pg.Close() - // AWS Service - // TODO if is not production, use mock - awsService, err := aws.New(cfg.AWS) - if err != nil { - log.Fatal("app - Run - aws.NewAwsService: %w", err) + // AWS Service or LocalStorage + var storageService storage.StorageService + if cfg.Deploy.DeployStage != "local" { + awsConn, err := aws.New(cfg.AWS) + if err != nil { + log.Fatalf("Failed to initialize AWS connection: %v", err) + } + storageService = awsConn + } else { + currentDir, err := os.Getwd() + if err != nil { + log.Fatalf("Failed to get current directory: %v", err) + } + + localStorage := &local.LocalStorage{ + BasePath: currentDir, // Use the absolute path + } + storageService = localStorage } // Kafka create keypair connection @@ -82,5 +97,5 @@ func main() { } go signConn.Run(cfg, entity.SignChannel) - app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer, submitConn.Producer, signConn.Producer, tRepo, awsService) + app.Run(cfg, pg, kpConn.Producer, horConn.Producer, envConn.Producer, submitConn.Producer, signConn.Producer, tRepo, storageService) } diff --git a/backend/pkg/aws/s3.go b/backend/pkg/aws/s3.go index 6bf5426c..831fbdf5 100644 --- a/backend/pkg/aws/s3.go +++ b/backend/pkg/aws/s3.go @@ -2,14 +2,19 @@ package aws import ( "bytes" + "path/filepath" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/s3/s3manager" ) -func (s *AwsConnection) UploadToS3(filename string, file []byte) (string, error) { +func (s *AwsConnection) uploadToS3(filename string, file []byte) (string, error) { uploader := s3manager.NewUploader(s.session) + if filepath.Ext(filename) != ".png" { + filename += ".png" + } + result, err := uploader.Upload(&s3manager.UploadInput{ Bucket: aws.String(s.bucketName), Key: aws.String(filename), diff --git a/backend/pkg/aws/server.go b/backend/pkg/aws/server.go index b59aad65..a3ca4433 100644 --- a/backend/pkg/aws/server.go +++ b/backend/pkg/aws/server.go @@ -25,3 +25,7 @@ func New(cfg config.AWS) (*AwsConnection, error) { bucketName: cfg.BucketName, }, nil } + +func (s *AwsConnection) UploadFile(filename string, file []byte) (string, error) { + return s.uploadToS3(filename, file) +} diff --git a/backend/pkg/localstorage/storage.go b/backend/pkg/localstorage/storage.go new file mode 100644 index 00000000..4f16411d --- /dev/null +++ b/backend/pkg/localstorage/storage.go @@ -0,0 +1,22 @@ +package local + +import ( + "os" + "path/filepath" +) + +type LocalStorage struct { + BasePath string +} + +func (l *LocalStorage) UploadFile(filename string, file []byte) (string, error) { + if filepath.Ext(filename) != ".png" { + filename += ".png" + } + fullPath := filepath.Join(l.BasePath, filename) + err := os.WriteFile(fullPath, file, 0o666) + if err != nil { + return "", err + } + return fullPath, nil +} diff --git a/backend/pkg/storage/storage.go b/backend/pkg/storage/storage.go new file mode 100644 index 00000000..5cd75929 --- /dev/null +++ b/backend/pkg/storage/storage.go @@ -0,0 +1,5 @@ +package storage + +type StorageService interface { + UploadFile(filename string, file []byte) (string, error) +} From 57b5695758cefb8aaa40c5fd84d97ec6e60cdfed Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Thu, 14 Dec 2023 20:12:30 -0300 Subject: [PATCH 43/52] Fix the mocks --- backend/internal/usecase/assets_test.go | 5 +++-- backend/internal/usecase/mocks/mocks.go | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/backend/internal/usecase/assets_test.go b/backend/internal/usecase/assets_test.go index 426c2ed3..03514199 100644 --- a/backend/internal/usecase/assets_test.go +++ b/backend/internal/usecase/assets_test.go @@ -36,7 +36,8 @@ func asset(t *testing.T) (*usecase.AssetUseCase, *mocks.MockAssetRepoInterface, ra := mocks.NewMockAssetRepoInterface(mockCtl) tg := mocks.NewMockTomlInterface(mockCtl) tr := mocks.NewMockTomlRepoInterface(mockCtl) - u := usecase.NewAssetUseCase(ra, rw, tg, tr, config.Horizon{}) + st := mocks.NewMockAssetServiceInterface(mockCtl) + u := usecase.NewAssetUseCase(ra, rw, tg, tr, config.Horizon{}, st) return u, ra, rw, tg } @@ -156,7 +157,7 @@ func TestAssetUseCaseCreate(t *testing.T) { t.Run(tc.name, func(t *testing.T) { tc.mock() - res, err := u.Create(tc.req.(entity.Asset)) + res, err := u.Create(tc.req.(entity.Asset), []byte{}) require.EqualValues(t, tc.res, res) if tc.err == nil { diff --git a/backend/internal/usecase/mocks/mocks.go b/backend/internal/usecase/mocks/mocks.go index 89b56986..ac45c35d 100644 --- a/backend/internal/usecase/mocks/mocks.go +++ b/backend/internal/usecase/mocks/mocks.go @@ -1341,17 +1341,17 @@ func (m *MockAssetServiceInterface) EXPECT() *MockAssetServiceInterfaceMockRecor return m.recorder } -// UploadAssetImage mocks base method. -func (m *MockAssetServiceInterface) UploadAssetImage(arg0 string, arg1 []byte) (string, error) { +// UploadFile mocks base method. +func (m *MockAssetServiceInterface) UploadFile(arg0 string, arg1 []byte) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UploadAssetImage", arg0, arg1) + ret := m.ctrl.Call(m, "UploadFile", arg0, arg1) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } -// UploadAssetImage indicates an expected call of UploadAssetImage. -func (mr *MockAssetServiceInterfaceMockRecorder) UploadAssetImage(arg0, arg1 interface{}) *gomock.Call { +// UploadFile indicates an expected call of UploadFile. +func (mr *MockAssetServiceInterfaceMockRecorder) UploadFile(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UploadAssetImage", reflect.TypeOf((*MockAssetServiceInterface)(nil).UploadAssetImage), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UploadFile", reflect.TypeOf((*MockAssetServiceInterface)(nil).UploadFile), arg0, arg1) } From 727e754593fb1b7b706dab2f322b2bd25f65c43d Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Fri, 15 Dec 2023 10:18:01 -0300 Subject: [PATCH 44/52] feat: vaults and contracts pagination --- .../internal/controller/http/v1/contracts.go | 12 +++- backend/internal/controller/http/v1/vault.go | 12 +++- backend/internal/usecase/contract.go | 8 +-- backend/internal/usecase/interfaces.go | 4 +- .../usecase/repo/contract_postgres.go | 58 ++++++++++++++----- .../internal/usecase/repo/vault_postgres.go | 23 ++++++-- backend/internal/usecase/vault.go | 8 +-- 7 files changed, 93 insertions(+), 32 deletions(-) diff --git a/backend/internal/controller/http/v1/contracts.go b/backend/internal/controller/http/v1/contracts.go index 73cab8ba..8b94e5de 100644 --- a/backend/internal/controller/http/v1/contracts.go +++ b/backend/internal/controller/http/v1/contracts.go @@ -58,6 +58,11 @@ type UpdateContractHistoryRequest struct { ContractId int `json:"contract_id" binding:"required" example:"GSDSC..."` } +type PaginatedContractsResponse struct { + Contracts []entity.Contract `json:"contracts"` + TotalPages int `json:"totalPages"` +} + // @Summary Create a new contract // @Description Create new contract // @Tags Contract @@ -154,13 +159,16 @@ func (r *contractRoutes) getAllContracts(c *gin.Context) { } // Get paginated contracts - contracts, err := r.c.GetPaginatedContracts(page, limit) + contracts, totalPages, err := r.c.GetPaginatedContracts(page, limit) if err != nil { r.l.Error(err, "http - v1 - get all contracts - GetPaginatedContracts") errorResponse(c, http.StatusInternalServerError, "error getting paginated contracts", err) return } - c.JSON(http.StatusOK, contracts) + c.JSON(http.StatusOK, PaginatedContractsResponse{ + Contracts: contracts, + TotalPages: totalPages, + }) } else { // Get all contracts without pagination contracts, err := r.c.GetAll() diff --git a/backend/internal/controller/http/v1/vault.go b/backend/internal/controller/http/v1/vault.go index 69807dbf..8f59a713 100644 --- a/backend/internal/controller/http/v1/vault.go +++ b/backend/internal/controller/http/v1/vault.go @@ -55,6 +55,11 @@ type UpdateVaultAssetRequest struct { IsRemove bool `json:"is_remove" example:"false"` } +type PaginatedVaultsResponse struct { + Vaults []entity.Vault `json:"vaults"` + TotalPages int `json:"totalPages"` +} + // @Summary Create a new vault // @Description Create and issue a new asset on Stellar // @Tags Vault @@ -231,13 +236,16 @@ func (r *vaultRoutes) getAllVaults(c *gin.Context) { } // Get paginated vaults - vaults, err := r.v.GetPaginatedVaults(page, limit) + vaults, totalPages, err := r.v.GetPaginatedVaults(page, limit) if err != nil { r.l.Error(err, "http - v1 - get all vaults - GetPaginatedVaults") errorResponse(c, http.StatusInternalServerError, "error getting paginated vaults", err) return } - c.JSON(http.StatusOK, vaults) + c.JSON(http.StatusOK, PaginatedVaultsResponse{ + Vaults: vaults, + TotalPages: totalPages, + }) } else { // Get all vaults without pagination vaults, err := r.v.GetAll(isAll) diff --git a/backend/internal/usecase/contract.go b/backend/internal/usecase/contract.go index 0580cd94..01397485 100644 --- a/backend/internal/usecase/contract.go +++ b/backend/internal/usecase/contract.go @@ -43,13 +43,13 @@ func (uc *ContractUseCase) GetById(id string) (entity.Contract, error) { return contract, nil } -func (uc *ContractUseCase) GetPaginatedContracts(page int, limit int) ([]entity.Contract, error) { - contracts, err := uc.cRepo.GetPaginatedContracts(page, limit) +func (uc *ContractUseCase) GetPaginatedContracts(page int, limit int) ([]entity.Contract, int, error) { + contracts, totalPages, err := uc.cRepo.GetPaginatedContracts(page, limit) if err != nil { - return nil, fmt.Errorf("ContractUseCase - GetPaginatedContracts - uc.repo.GetPaginatedContracts: %w", err) + return nil, 0, fmt.Errorf("ContractUseCase - GetPaginatedContracts - uc.repo.GetPaginatedContracts: %w", err) } - return contracts, nil + return contracts, totalPages, nil } func (uc *ContractUseCase) GetHistory(userId int, contractId int) ([]entity.ContractHistory, error) { diff --git a/backend/internal/usecase/interfaces.go b/backend/internal/usecase/interfaces.go index 66e4e662..301070d0 100644 --- a/backend/internal/usecase/interfaces.go +++ b/backend/internal/usecase/interfaces.go @@ -95,14 +95,14 @@ type ( UpdateVault(entity.Vault) (entity.Vault, error) GetVaultById(id int) (entity.Vault, error) DeleteVault(entity.Vault) (entity.Vault, error) - GetPaginatedVaults(int, int) ([]entity.Vault, error) + GetPaginatedVaults(int, int) ([]entity.Vault, int, error) } ContractRepoInterface interface { GetContracts() ([]entity.Contract, error) CreateContract(entity.Contract) (entity.Contract, error) GetContractById(id string) (entity.Contract, error) - GetPaginatedContracts(int, int) ([]entity.Contract, error) + GetPaginatedContracts(int, int) ([]entity.Contract, int, error) GetHistory(userId int, contractId int) ([]entity.ContractHistory, error) AddContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) UpdateContractHistory(contractHistory entity.ContractHistory) (entity.ContractHistory, error) diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index 140489ff..66f06751 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -172,30 +172,51 @@ func (r ContractRepo) CreateContract(data entity.Contract) (entity.Contract, err return res, nil } -func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, error) { +func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, int, error) { offset := (page - 1) * limit + + // Query to count the total number of vaults + countQuery := `SELECT COUNT(*) FROM contracts;` + + var totalVaults int + err := r.Db.QueryRow(countQuery).Scan(&totalVaults) + if err != nil { + return nil, 0, fmt.Errorf("ContractRepo - GetPaginatedContracts - Count Query: %w", err) + } + + // Calculate total pages + totalPages := (totalVaults + limit - 1) / limit + query := ` - SELECT - c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, - c.yield_rate AS contract_yield_rate, c.term AS contract_term, - c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, - c.compound AS contract_compound, c.created_at AS contract_created_at, - v.id AS vault_id, v.name AS vault_name, + SELECT + c.id AS contract_id, c.name AS contract_name, c.address AS contract_address, c.yield_rate AS contract_yield_rate, + c.term AS contract_term, c.min_deposit AS contract_min_deposit, c.penalty_rate AS contract_penalty_rate, + c.compound AS contract_compound, c.created_at AS contract_created_at, v.id AS vault_id, v.name AS vault_name, vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, - wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight + wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, + d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, + dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, + i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, + ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight FROM contracts c JOIN vault v ON c.vault_id = v.id JOIN vaultcategory vc ON v.vault_category_id = vc.id JOIN wallet w ON v.wallet_id = w.id JOIN key wk ON w.id = wk.wallet_id + JOIN asset a ON a.id = c.asset_id + JOIN wallet d ON a.distributor_id = d.id + JOIN key dk ON d.id = dk.wallet_id + JOIN wallet i ON a.issuer_id = i.id + JOIN key ik ON i.id = ik.wallet_id ORDER BY c.id DESC LIMIT $1 OFFSET $2; ` rows, err := r.Db.Query(query, limit, offset) if err != nil { - return nil, fmt.Errorf("ContractRepo - GetPaginatedContracts - Query: %w", err) + return nil, 0, fmt.Errorf("ContractRepo - GetPaginatedContracts - Query: %w", err) } defer rows.Close() @@ -205,28 +226,39 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, var contract entity.Contract var vaultCategory entity.VaultCategory var vault entity.Vault + var asset entity.Asset var wallet entity.Wallet + var assetDistributor entity.Wallet + var assetIssuer entity.Wallet err := rows.Scan( - &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, - &contract.Term, &contract.MinDeposit, &contract.PenaltyRate, &contract.Compound, &contract.CreatedAt, + &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, + &contract.PenaltyRate, &contract.Compound, &contract.CreatedAt, &vault.Id, &vault.Name, &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &assetDistributor.Id, &assetDistributor.Type, &assetDistributor.Funded, + &assetDistributor.Key.Id, &assetDistributor.Key.PublicKey, &assetDistributor.Key.Weight, + &assetIssuer.Id, &assetIssuer.Type, &assetIssuer.Funded, + &assetIssuer.Key.Id, &assetIssuer.Key.PublicKey, &assetIssuer.Key.Weight, ) if err != nil { - return nil, fmt.Errorf("ContractRepo - GetPaginatedContracts - row.Scan: %w", err) + return nil, 0, fmt.Errorf("ContractRepo - GetPaginatedContracts - row.Scan: %w", err) } vault.Wallet = wallet vault.VaultCategory = &vaultCategory + asset.Distributor = assetDistributor + asset.Issuer = assetIssuer + contract.Asset = asset contract.Vault = vault contracts = append(contracts, contract) } - return contracts, nil + return contracts, totalPages, nil } func (r ContractRepo) GetHistory(userId int, contractId int) ([]entity.ContractHistory, error) { diff --git a/backend/internal/usecase/repo/vault_postgres.go b/backend/internal/usecase/repo/vault_postgres.go index 0def0f7a..127e40c9 100644 --- a/backend/internal/usecase/repo/vault_postgres.go +++ b/backend/internal/usecase/repo/vault_postgres.go @@ -176,10 +176,23 @@ func (r VaultRepo) DeleteVault(data entity.Vault) (entity.Vault, error) { } // GetPaginatedVaults -. -func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { +func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, int, error) { // Calculate offset based on page number and limit offset := (page - 1) * limit + // Query to count the total number of vaults + countQuery := `SELECT COUNT(*) FROM vault v WHERE v.active = 1 AND v.owner_id is null;` + + var totalVaults int + err := r.Db.QueryRow(countQuery).Scan(&totalVaults) + if err != nil { + return nil, 0, fmt.Errorf("VaultRepo - GetPaginatedVaults - Count Query: %w", err) + } + + // Calculate total pages + totalPages := (totalVaults + limit - 1) / limit + + // Query to fetch paginated assets query := ` SELECT v.id AS vault_id, v.name AS vault_name, v.active AS vault_active, v.owner_id AS owner_id, @@ -191,13 +204,13 @@ func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { JOIN wallet w ON v.wallet_id = w.id JOIN key wk ON w.id = wk.wallet_id WHERE v.active = 1 - ORDER BY v.id DESC + ORDER BY v.name ASC OFFSET $1 LIMIT $2; ` rows, err := r.Db.Query(query, offset, limit) if err != nil { - return nil, fmt.Errorf("VaultRepo - GetPaginatedVaults - Query: %w", err) + return nil, 0, fmt.Errorf("VaultRepo - GetPaginatedVaults - Query: %w", err) } defer rows.Close() @@ -215,7 +228,7 @@ func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, ) if err != nil { - return nil, fmt.Errorf("VaultRepo - GetPaginatedVaults - row.Scan: %w", err) + return nil, 0, fmt.Errorf("VaultRepo - GetPaginatedVaults - row.Scan: %w", err) } vault.Wallet = wallet @@ -224,5 +237,5 @@ func (r VaultRepo) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { vaults = append(vaults, vault) } - return vaults, nil + return vaults, totalPages, nil } diff --git a/backend/internal/usecase/vault.go b/backend/internal/usecase/vault.go index 7bac9f03..f6f514dc 100644 --- a/backend/internal/usecase/vault.go +++ b/backend/internal/usecase/vault.go @@ -63,11 +63,11 @@ func (uc *VaultUseCase) DeleteVault(data entity.Vault) (entity.Vault, error) { return vault, nil } -func (uc *VaultUseCase) GetPaginatedVaults(page, limit int) ([]entity.Vault, error) { - vault, err := uc.vRepo.GetPaginatedVaults(page, limit) +func (uc *VaultUseCase) GetPaginatedVaults(page, limit int) ([]entity.Vault, int, error) { + vault, totalPages, err := uc.vRepo.GetPaginatedVaults(page, limit) if err != nil { - return nil, fmt.Errorf("VaultUseCase - GetPaginatedVaults - uc.repo.GetPaginatedVaults: %w", err) + return nil, 0, fmt.Errorf("VaultUseCase - GetPaginatedVaults - uc.repo.GetPaginatedVaults: %w", err) } - return vault, nil + return vault, totalPages, nil } From 6b12dd8d12633206654e8ba636527519c9a5ce32 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Fri, 15 Dec 2023 10:29:38 -0300 Subject: [PATCH 45/52] update mocks --- backend/internal/usecase/mocks/mocks.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/backend/internal/usecase/mocks/mocks.go b/backend/internal/usecase/mocks/mocks.go index ac45c35d..5033d321 100644 --- a/backend/internal/usecase/mocks/mocks.go +++ b/backend/internal/usecase/mocks/mocks.go @@ -959,12 +959,13 @@ func (mr *MockVaultRepoInterfaceMockRecorder) DeleteVault(arg0 interface{}) *gom } // GetPaginatedVaults mocks base method. -func (m *MockVaultRepoInterface) GetPaginatedVaults(arg0, arg1 int) ([]entity.Vault, error) { +func (m *MockVaultRepoInterface) GetPaginatedVaults(arg0, arg1 int) ([]entity.Vault, int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetPaginatedVaults", arg0, arg1) ret0, _ := ret[0].([]entity.Vault) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(int) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // GetPaginatedVaults indicates an expected call of GetPaginatedVaults. @@ -1117,12 +1118,13 @@ func (mr *MockContractRepoInterfaceMockRecorder) GetHistory(userId, contractId i } // GetPaginatedContracts mocks base method. -func (m *MockContractRepoInterface) GetPaginatedContracts(arg0, arg1 int) ([]entity.Contract, error) { +func (m *MockContractRepoInterface) GetPaginatedContracts(arg0, arg1 int) ([]entity.Contract, int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetPaginatedContracts", arg0, arg1) ret0, _ := ret[0].([]entity.Contract) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(int) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // GetPaginatedContracts indicates an expected call of GetPaginatedContracts. From 16d4efda4598621a95377df4774dfe9660352801 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Mon, 18 Dec 2023 10:12:38 -0300 Subject: [PATCH 46/52] Add the edge case, if image is null --- .../internal/usecase/repo/asset_postgres.go | 244 ++++++++++-------- 1 file changed, 138 insertions(+), 106 deletions(-) diff --git a/backend/internal/usecase/repo/asset_postgres.go b/backend/internal/usecase/repo/asset_postgres.go index 9ca4488a..a66dcd57 100644 --- a/backend/internal/usecase/repo/asset_postgres.go +++ b/backend/internal/usecase/repo/asset_postgres.go @@ -36,23 +36,24 @@ func (r AssetRepo) GetAsset(id int) (entity.Asset, error) { func (r AssetRepo) GetAssets() ([]entity.Asset, error) { query := ` - SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, a.image, a.contract_id, - d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, - dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, - i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, - ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight - FROM asset a - JOIN wallet d ON a.distributor_id = d.id - JOIN key dk ON d.id = dk.wallet_id - JOIN wallet i ON a.issuer_id = i.id - JOIN key ik ON i.id = ik.wallet_id - ORDER BY a.name; - ` + SELECT + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, + COALESCE(a.image, '') AS image, a.contract_id, + d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, + dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, + i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, + ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight + FROM asset a + JOIN wallet d ON a.distributor_id = d.id + JOIN key dk ON d.id = dk.wallet_id + JOIN wallet i ON a.issuer_id = i.id + JOIN key ik ON i.id = ik.wallet_id + ORDER BY a.name; + ` rows, err := r.Db.Query(query) if err != nil { - return nil, fmt.Errorf("AssetRepo - GetAllAssets - Query: %w", err) + return nil, fmt.Errorf("AssetRepo - GetAssets - Query: %w", err) } defer rows.Close() @@ -62,16 +63,23 @@ func (r AssetRepo) GetAssets() ([]entity.Asset, error) { var asset entity.Asset var distributor entity.Wallet var issuer entity.Wallet + var image sql.NullString err := rows.Scan( - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, &asset.ContractId, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, &issuer.Key.Id, &issuer.Key.PublicKey, &issuer.Key.Weight, ) if err != nil { - return nil, fmt.Errorf("AssetRepo - GetAllAssets - row.Scan: %w", err) + return nil, fmt.Errorf("AssetRepo - GetAssets - row.Scan: %w", err) + } + + if image.Valid { + asset.Image = image.String + } else { + asset.Image = "" } asset.Distributor = distributor @@ -85,28 +93,30 @@ func (r AssetRepo) GetAssets() ([]entity.Asset, error) { func (r AssetRepo) GetAssetByCode(code string) (entity.Asset, error) { query := ` - SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type,a.code as asset_code, a.image, a.contract_id, - d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, - dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, - i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, - ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight - FROM asset a - JOIN wallet d ON a.distributor_id = d.id - JOIN key dk ON d.id = dk.wallet_id - JOIN wallet i ON a.issuer_id = i.id - JOIN key ik ON i.id = ik.wallet_id - WHERE a.code = $1; - ` + SELECT + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, + COALESCE(a.image, '') AS image, a.contract_id, + d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, + dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, + i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, + ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight + FROM asset a + JOIN wallet d ON a.distributor_id = d.id + JOIN key dk ON d.id = dk.wallet_id + JOIN wallet i ON a.issuer_id = i.id + JOIN key ik ON i.id = ik.wallet_id + WHERE a.code = $1; + ` row := r.Db.QueryRow(query, code) var asset entity.Asset var distributor entity.Wallet var issuer entity.Wallet + var image sql.NullString err := row.Scan( - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, &asset.ContractId, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -119,47 +129,44 @@ func (r AssetRepo) GetAssetByCode(code string) (entity.Asset, error) { return entity.Asset{}, fmt.Errorf("AssetRepo - GetAssetByCode - row.Scan: %w", err) } + if image.Valid { + asset.Image = image.String + } else { + asset.Image = "" + } + asset.Distributor = distributor asset.Issuer = issuer return asset, nil } -func (r AssetRepo) CreateAsset(data entity.Asset) (entity.Asset, error) { - res := data - stmt := `INSERT INTO Asset (code, issuer_id, distributor_id, name, asset_type, image ) VALUES ($1, $2, $3,$4, $5, $6) RETURNING id;` - err := r.Db.QueryRow(stmt, data.Code, data.Issuer.Id, data.Distributor.Id, data.Name, data.AssetType, data.Image).Scan(&res.Id) - if err != nil { - return entity.Asset{}, fmt.Errorf("AssetRepo - CreateAsset - db.QueryRow: %w", err) - } - - return res, nil -} - func (r AssetRepo) GetAssetById(id string) (entity.Asset, error) { query := ` - SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, a.contract_id, - d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, - dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, - i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, - ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight - FROM asset a - JOIN wallet d ON a.distributor_id = d.id - JOIN key dk ON d.id = dk.wallet_id - JOIN wallet i ON a.issuer_id = i.id - JOIN key ik ON i.id = ik.wallet_id - WHERE a.id = $1; - ` + SELECT + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, + COALESCE(a.image, '') AS image, a.contract_id, + d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, + dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, + i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, + ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight + FROM asset a + JOIN wallet d ON a.distributor_id = d.id + JOIN key dk ON d.id = dk.wallet_id + JOIN wallet i ON a.issuer_id = i.id + JOIN key ik ON i.id = ik.wallet_id + WHERE a.id = $1; + ` row := r.Db.QueryRow(query, id) var asset entity.Asset var distributor entity.Wallet var issuer entity.Wallet + var image sql.NullString err := row.Scan( - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, &asset.ContractId, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -172,62 +179,20 @@ func (r AssetRepo) GetAssetById(id string) (entity.Asset, error) { return entity.Asset{}, fmt.Errorf("AssetRepo - GetAssetById - row.Scan: %w", err) } + if image.Valid { + asset.Image = image.String + } else { + asset.Image = "" + } + asset.Distributor = distributor asset.Issuer = issuer return asset, nil } -func (r AssetRepo) StoreAssetImage(assetId string, image string) error { - stmt := ` - UPDATE asset - SET image = $2 - WHERE id = $1 - ` - - _, err := r.Db.Exec(stmt, assetId, image) - if err != nil { - return fmt.Errorf("AssetRepo - StoreAssetImage - Db.Exec: %w", err) - } - - return nil -} - -func (r AssetRepo) GetAssetImage(assetId string) ([]byte, error) { - stmt := ` - SELECT image - FROM asset - WHERE id = $1 - ` - - row := r.Db.QueryRow(stmt, assetId) - - var image []byte - err := row.Scan(&image) - if err != nil { - return nil, fmt.Errorf("AssetRepo - GetAssetImage - row.Scan: %w", err) - } - - return image, nil -} - -func (r AssetRepo) UpdateContractId(assetId string, contractId string) error { - stmt := ` - UPDATE asset - SET contract_id = $2 - WHERE id = $1 - ` - - _, err := r.Db.Exec(stmt, assetId, contractId) - if err != nil { - return fmt.Errorf("AssetRepo - UpdateContractId - Db.Exec: %w", err) - } - - return nil -} - func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, error) { - // Calculate the offset // Calculate offset + // Calculate the offset offset := (page - 1) * limit // Query to count the total number of assets @@ -247,7 +212,8 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, // Query to fetch paginated assets query := ` SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, a.image, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, + COALESCE(a.image, '') AS image, a.contract_id, d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, @@ -272,9 +238,10 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, var asset entity.Asset var distributor entity.Wallet var issuer entity.Wallet + var image sql.NullString err := rows.Scan( - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -284,6 +251,12 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, return nil, 0, fmt.Errorf("AssetRepo - GetPaginated - row.Scan: %w", err) } + if image.Valid { + asset.Image = image.String + } else { + asset.Image = "" + } + asset.Distributor = distributor asset.Issuer = issuer @@ -292,3 +265,62 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, return assets, totalPages, nil } + +func (r AssetRepo) StoreAssetImage(assetId string, image string) error { + stmt := ` + UPDATE asset + SET image = $2 + WHERE id = $1 + ` + + _, err := r.Db.Exec(stmt, assetId, image) + if err != nil { + return fmt.Errorf("AssetRepo - StoreAssetImage - Db.Exec: %w", err) + } + + return nil +} + +func (r AssetRepo) GetAssetImage(assetId string) ([]byte, error) { + stmt := ` + SELECT image + FROM asset + WHERE id = $1 + ` + + row := r.Db.QueryRow(stmt, assetId) + + var image []byte + err := row.Scan(&image) + if err != nil { + return nil, fmt.Errorf("AssetRepo - GetAssetImage - row.Scan: %w", err) + } + + return image, nil +} + +func (r AssetRepo) UpdateContractId(assetId string, contractId string) error { + stmt := ` + UPDATE asset + SET contract_id = $2 + WHERE id = $1 + ` + + _, err := r.Db.Exec(stmt, assetId, contractId) + if err != nil { + return fmt.Errorf("AssetRepo - UpdateContractId - Db.Exec: %w", err) + } + + return nil +} + +func (r AssetRepo) CreateAsset(data entity.Asset) (entity.Asset, error) { + res := data + stmt := `INSERT INTO Asset (code, issuer_id, distributor_id, name, asset_type, image ) VALUES ($1, $2, $3,$4, $5, $6) RETURNING id;` + err := r.Db.QueryRow(stmt, data.Code, data.Issuer.Id, data.Distributor.Id, data.Name, data.AssetType, data.Image).Scan(&res.Id) + if err != nil { + return entity.Asset{}, fmt.Errorf("AssetRepo - CreateAsset - db.QueryRow: %w", err) + } + + return res, nil +} From 847427fc975ba20b1d8b49a39a9c2ff0620e9c20 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 18 Dec 2023 10:13:02 -0300 Subject: [PATCH 47/52] feat: set images null --- backend/migrations/000038_update_asset_images.up.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 backend/migrations/000038_update_asset_images.up.sql diff --git a/backend/migrations/000038_update_asset_images.up.sql b/backend/migrations/000038_update_asset_images.up.sql new file mode 100644 index 00000000..2032101f --- /dev/null +++ b/backend/migrations/000038_update_asset_images.up.sql @@ -0,0 +1 @@ +UPDATE asset SET image = null \ No newline at end of file From 1a42c9f25f2405bb9c510c4d54930cb2695f5bc7 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Mon, 18 Dec 2023 10:34:57 -0300 Subject: [PATCH 48/52] Add ContractId to asset retrieval queries --- .../internal/usecase/repo/asset_postgres.go | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/backend/internal/usecase/repo/asset_postgres.go b/backend/internal/usecase/repo/asset_postgres.go index a66dcd57..0268b469 100644 --- a/backend/internal/usecase/repo/asset_postgres.go +++ b/backend/internal/usecase/repo/asset_postgres.go @@ -67,6 +67,7 @@ func (r AssetRepo) GetAssets() ([]entity.Asset, error) { err := rows.Scan( &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, + &asset.ContractId, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -167,6 +168,7 @@ func (r AssetRepo) GetAssetById(id string) (entity.Asset, error) { err := row.Scan( &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, + &asset.ContractId, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -211,20 +213,21 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, // Query to fetch paginated assets query := ` - SELECT - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, - COALESCE(a.image, '') AS image, a.contract_id, - d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, - dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, - i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, - ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight - FROM asset a - JOIN wallet d ON a.distributor_id = d.id - JOIN key dk ON d.id = dk.wallet_id - JOIN wallet i ON a.issuer_id = i.id - JOIN key ik ON i.id = ik.wallet_id - ORDER BY a.name - LIMIT $1 OFFSET $2; + SELECT + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code AS code, + COALESCE(a.image, '') AS image, a.contract_id, + d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, + dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, + i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, + ik.id AS issuer_key_id, ik.public_key AS issuer_key_public_key, ik.weight AS issuer_key_weight + FROM asset a + JOIN wallet d ON a.distributor_id = d.id + JOIN key dk ON d.id = dk.wallet_id + JOIN wallet i ON a.issuer_id = i.id + JOIN key ik ON i.id = ik.wallet_id + ORDER BY a.name + LIMIT $1 OFFSET $2; + ` rows, err := r.Db.Query(query, limit, offset) @@ -242,6 +245,7 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, err := rows.Scan( &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, + &asset.ContractId, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, @@ -251,18 +255,16 @@ func (r AssetRepo) GetPaginatedAssets(page int, limit int) ([]entity.Asset, int, return nil, 0, fmt.Errorf("AssetRepo - GetPaginated - row.Scan: %w", err) } - if image.Valid { - asset.Image = image.String - } else { + if !image.Valid { asset.Image = "" + } else { + asset.Image = image.String } - asset.Distributor = distributor asset.Issuer = issuer assets = append(assets, asset) } - return assets, totalPages, nil } @@ -283,20 +285,27 @@ func (r AssetRepo) StoreAssetImage(assetId string, image string) error { func (r AssetRepo) GetAssetImage(assetId string) ([]byte, error) { stmt := ` - SELECT image - FROM asset - WHERE id = $1 - ` + SELECT image + FROM asset + WHERE id = $1 + ` row := r.Db.QueryRow(stmt, assetId) - var image []byte + var image sql.NullString err := row.Scan(&image) if err != nil { + if err == sql.ErrNoRows { + return nil, fmt.Errorf("AssetRepo - GetAssetImage - asset not found: %w", err) + } return nil, fmt.Errorf("AssetRepo - GetAssetImage - row.Scan: %w", err) } - return image, nil + if image.Valid { + return []byte(image.String), nil + } + + return nil, nil // No image found, return nil without error } func (r AssetRepo) UpdateContractId(assetId string, contractId string) error { From 4aa820d3231fc19b6f59de08e16e016dc6be35e6 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 18 Dec 2023 11:26:13 -0300 Subject: [PATCH 49/52] fix: asset image contracts --- .../usecase/repo/contract_postgres.go | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/backend/internal/usecase/repo/contract_postgres.go b/backend/internal/usecase/repo/contract_postgres.go index 66f06751..24371c0a 100644 --- a/backend/internal/usecase/repo/contract_postgres.go +++ b/backend/internal/usecase/repo/contract_postgres.go @@ -25,7 +25,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, COALESCE(a.image, '') AS image, d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, @@ -59,6 +59,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { var wallet entity.Wallet var assetDistributor entity.Wallet var assetIssuer entity.Wallet + var image sql.NullString err := rows.Scan( &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, @@ -67,7 +68,7 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, &assetDistributor.Id, &assetDistributor.Type, &assetDistributor.Funded, &assetDistributor.Key.Id, &assetDistributor.Key.PublicKey, &assetDistributor.Key.Weight, &assetIssuer.Id, &assetIssuer.Type, &assetIssuer.Funded, @@ -81,6 +82,11 @@ func (r ContractRepo) GetContracts() ([]entity.Contract, error) { vault.VaultCategory = &vaultCategory asset.Distributor = assetDistributor asset.Issuer = assetIssuer + if !image.Valid { + asset.Image = "" + } else { + asset.Image = image.String + } contract.Asset = asset contract.Vault = vault @@ -99,7 +105,7 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, COALESCE(a.image, '') AS image, d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, @@ -126,6 +132,7 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { var wallet entity.Wallet var assetDistributor entity.Wallet var assetIssuer entity.Wallet + var image sql.NullString err := row.Scan( &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, @@ -134,7 +141,7 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, &assetDistributor.Id, &assetDistributor.Type, &assetDistributor.Funded, &assetDistributor.Key.Id, &assetDistributor.Key.PublicKey, &assetDistributor.Key.Weight, &assetIssuer.Id, &assetIssuer.Type, &assetIssuer.Funded, @@ -151,6 +158,11 @@ func (r ContractRepo) GetContractById(id string) (entity.Contract, error) { vault.VaultCategory = &vaultCategory asset.Distributor = assetDistributor asset.Issuer = assetIssuer + if !image.Valid { + asset.Image = "" + } else { + asset.Image = image.String + } contract.Asset = asset contract.Vault = vault @@ -195,7 +207,7 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, vc.id AS vault_category_id, vc.name as vault_category_name, w.id AS wallet_id, w.type AS wallet_type, w.funded AS wallet_funded, wk.id AS wallet_key_id, wk.public_key AS wallet_key_public_key, wk.weight AS wallet_key_weight, - a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, a.image, + a.id AS asset_id, a.name AS asset_name, a.asset_type, a.code as asset_code, COALESCE(a.image, '') AS image, d.id AS distributor_id, d.type AS distributor_type, d.funded AS distributor_funded, dk.id AS distributor_key_id, dk.public_key AS distributor_key_public_key, dk.weight AS distributor_key_weight, i.id AS issuer_id, i.type AS issuer_type, i.funded AS issuer_funded, @@ -230,6 +242,7 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, var wallet entity.Wallet var assetDistributor entity.Wallet var assetIssuer entity.Wallet + var image sql.NullString err := rows.Scan( &contract.Id, &contract.Name, &contract.Address, &contract.YieldRate, &contract.Term, &contract.MinDeposit, @@ -238,7 +251,7 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, &vaultCategory.Id, &vaultCategory.Name, &wallet.Id, &wallet.Type, &wallet.Funded, &wallet.Key.Id, &wallet.Key.PublicKey, &wallet.Key.Weight, - &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &asset.Image, + &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, &assetDistributor.Id, &assetDistributor.Type, &assetDistributor.Funded, &assetDistributor.Key.Id, &assetDistributor.Key.PublicKey, &assetDistributor.Key.Weight, &assetIssuer.Id, &assetIssuer.Type, &assetIssuer.Funded, @@ -252,6 +265,11 @@ func (r ContractRepo) GetPaginatedContracts(page, limit int) ([]entity.Contract, vault.VaultCategory = &vaultCategory asset.Distributor = assetDistributor asset.Issuer = assetIssuer + if !image.Valid { + asset.Image = "" + } else { + asset.Image = image.String + } contract.Asset = asset contract.Vault = vault From 6440777eab57ffcc43f688e13e7456aa991b28ac Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 18 Dec 2023 15:45:38 -0300 Subject: [PATCH 50/52] feat: testnet reset --- backend/migrations/000039_testnet_reset.up.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 backend/migrations/000039_testnet_reset.up.sql diff --git a/backend/migrations/000039_testnet_reset.up.sql b/backend/migrations/000039_testnet_reset.up.sql new file mode 100644 index 00000000..4652b0b9 --- /dev/null +++ b/backend/migrations/000039_testnet_reset.up.sql @@ -0,0 +1,14 @@ +TRUNCATE TABLE logtransactions CASCADE; +TRUNCATE TABLE contractshistory CASCADE; +TRUNCATE TABLE contracts CASCADE; +TRUNCATE TABLE vault CASCADE; +TRUNCATE TABLE vaultcategory CASCADE; +TRUNCATE TABLE asset CASCADE; +TRUNCATE TABLE key CASCADE; +TRUNCATE TABLE wallet CASCADE; +TRUNCATE TABLE useraccount CASCADE; +TRUNCATE TABLE toml CASCADE; + +ALTER SEQUENCE public.key_id_seq RESTART 1; +ALTER SEQUENCE public.wallet_id_seq RESTART 1; + From 5757c187f6d500aff85a91907f2bc6bb7134ac73 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 19 Dec 2023 10:02:03 -0300 Subject: [PATCH 51/52] Add asset.ContractId to GetAssetByCode function --- backend/internal/usecase/repo/asset_postgres.go | 1 + backend/migrations/000039_testnet_reset.up.sql | 1 + 2 files changed, 2 insertions(+) diff --git a/backend/internal/usecase/repo/asset_postgres.go b/backend/internal/usecase/repo/asset_postgres.go index 0268b469..c1172eee 100644 --- a/backend/internal/usecase/repo/asset_postgres.go +++ b/backend/internal/usecase/repo/asset_postgres.go @@ -118,6 +118,7 @@ func (r AssetRepo) GetAssetByCode(code string) (entity.Asset, error) { err := row.Scan( &asset.Id, &asset.Name, &asset.AssetType, &asset.Code, &image, + &asset.ContractId, &distributor.Id, &distributor.Type, &distributor.Funded, &distributor.Key.Id, &distributor.Key.PublicKey, &distributor.Key.Weight, &issuer.Id, &issuer.Type, &issuer.Funded, diff --git a/backend/migrations/000039_testnet_reset.up.sql b/backend/migrations/000039_testnet_reset.up.sql index 4652b0b9..66b9fc60 100644 --- a/backend/migrations/000039_testnet_reset.up.sql +++ b/backend/migrations/000039_testnet_reset.up.sql @@ -11,4 +11,5 @@ TRUNCATE TABLE toml CASCADE; ALTER SEQUENCE public.key_id_seq RESTART 1; ALTER SEQUENCE public.wallet_id_seq RESTART 1; +ALTER SEQUENCE public.asset_id_seq RESTART 1; From 8391065fcb2575ad87b1a5525e82d8d80cc1ba51 Mon Sep 17 00:00:00 2001 From: Wellington Junior Date: Tue, 19 Dec 2023 12:11:36 -0300 Subject: [PATCH 52/52] Add AWS_REGION environment variable --- backend/.env.example | 1 + backend/config/config.go | 1 + backend/pkg/aws/server.go | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/backend/.env.example b/backend/.env.example index 978b47cd..183b569b 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -37,6 +37,7 @@ JWT_SECRET_KEY=secret GIN_MODE=developer #release AWS_BUCKET_NAME= +AWS_REGION= ## Horizon Config HORIZON_PUBLIC_API_SERVER=https://horizon-testnet.stellar.org diff --git a/backend/config/config.go b/backend/config/config.go index a8b673ac..5c8b8bad 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -66,6 +66,7 @@ type ( AWS struct { BucketName string `env-required:"true" env:"AWS_BUCKET_NAME"` + AwsRegion string `env:"AWS_REGION"` } Horizon struct { diff --git a/backend/pkg/aws/server.go b/backend/pkg/aws/server.go index a3ca4433..c2619bea 100644 --- a/backend/pkg/aws/server.go +++ b/backend/pkg/aws/server.go @@ -2,6 +2,7 @@ package aws import ( "github.com/CheesecakeLabs/token-factory-v2/backend/config" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ses" ) @@ -14,7 +15,11 @@ type AwsConnection struct { // Initialize a session with AWS func New(cfg config.AWS) (*AwsConnection, error) { - sess, err := session.NewSession() + sess, err := session.NewSession( + &aws.Config{ + Region: aws.String(cfg.AwsRegion), + }, + ) if err != nil { return &AwsConnection{}, err }