From 1e9322f8257672d95d850739609af87c673d7b56 Mon Sep 17 00:00:00 2001 From: Andre Russowsky Date: Tue, 15 Oct 2024 11:29:46 -0300 Subject: [PATCH 01/62] feature: implement get operation by portfolio :sparkles: --- .../database/postgres/operation.postgresql.go | 52 +++++++++++++++ .../app/query/get-id-operation-portifolio.go | 36 +++++++++++ .../app/query/get-id-operaton-account_test.go | 64 ------------------- .../domain/operation/operation_repository.go | 1 + .../gen/mock/operation/operation_mock.go | 15 +++++ .../internal/ports/http/operation.go | 22 +++++++ .../transaction/internal/ports/http/routes.go | 5 +- 7 files changed, 129 insertions(+), 66 deletions(-) create mode 100644 components/transaction/internal/app/query/get-id-operation-portifolio.go delete mode 100644 components/transaction/internal/app/query/get-id-operaton-account_test.go diff --git a/components/transaction/internal/adapters/database/postgres/operation.postgresql.go b/components/transaction/internal/adapters/database/postgres/operation.postgresql.go index 63c0a514..4de667f3 100644 --- a/components/transaction/internal/adapters/database/postgres/operation.postgresql.go +++ b/components/transaction/internal/adapters/database/postgres/operation.postgresql.go @@ -328,6 +328,58 @@ func (r *OperationPostgreSQLRepository) FindByAccount(ctx context.Context, organ return operation.ToEntity(), nil } +// FindByPortfolio retrieves a Operation entity from the database using the provided portfolio ID. +func (r *OperationPostgreSQLRepository) FindByPortfolio(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID) (*o.Operation, error) { + db, err := r.connection.GetDB() + if err != nil { + return nil, err + } + + operation := &o.OperationPostgreSQLModel{} + + row := db.QueryRowContext(ctx, "SELECT * FROM operation WHERE organization_id = $1 AND ledger_id = $2 AND portfolio_id = $3 AND id = $4 AND deleted_at IS NULL", + organizationID, ledgerID, portfolioID, id) + if err := row.Scan( + &operation.ID, + &operation.TransactionID, + &operation.Description, + &operation.Type, + &operation.AssetCode, + &operation.Amount, + &operation.AmountScale, + &operation.AvailableBalance, + &operation.BalanceScale, + &operation.OnHoldBalance, + &operation.AvailableBalanceAfter, + &operation.OnHoldBalanceAfter, + &operation.BalanceScaleAfter, + &operation.Status, + &operation.StatusDescription, + &operation.AccountID, + &operation.AccountAlias, + &operation.PortfolioID, + &operation.ChartOfAccounts, + &operation.OrganizationID, + &operation.LedgerID, + &operation.CreatedAt, + &operation.UpdatedAt, + &operation.DeletedAt, + ); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, common.EntityNotFoundError{ + EntityType: reflect.TypeOf(o.Operation{}).Name(), + Title: "Entity not found.", + Code: "0007", + Message: "No entity was found matching the provided ID. Ensure the correct ID is being used for the entity you are attempting to manage.", + } + } + + return nil, err + } + + return operation.ToEntity(), nil +} + // Update a Operation entity into Postgresql and returns the Operation updated. func (r *OperationPostgreSQLRepository) Update(ctx context.Context, organizationID, ledgerID, id uuid.UUID, operation *o.Operation) (*o.Operation, error) { db, err := r.connection.GetDB() diff --git a/components/transaction/internal/app/query/get-id-operation-portifolio.go b/components/transaction/internal/app/query/get-id-operation-portifolio.go new file mode 100644 index 00000000..38117c30 --- /dev/null +++ b/components/transaction/internal/app/query/get-id-operation-portifolio.go @@ -0,0 +1,36 @@ +package query + +import ( + "context" + "errors" + "reflect" + + "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common/mlog" + "github.com/LerianStudio/midaz/components/transaction/internal/app" + o "github.com/LerianStudio/midaz/components/transaction/internal/domain/operation" + "github.com/google/uuid" +) + +func (uc *UseCase) GetOperationByPortfolio(ctx context.Context, organizationID, ledgerID, portfolioID, operationID string) (*o.Operation, error) { + logger := mlog.NewLoggerFromContext(ctx) + logger.Infof("Retrieving operation by account") + + op, err := uc.OperationRepo.FindByPortfolio(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), uuid.MustParse(operationID)) + if err != nil { + logger.Errorf("Error getting operation on repo: %v", err) + + if errors.Is(err, app.ErrDatabaseItemNotFound) { + return nil, common.EntityNotFoundError{ + EntityType: reflect.TypeOf(o.Operation{}).Name(), + Message: "Operation was not found", + Code: "OPERATION_NOT_FOUND", + Err: err, + } + } + + return nil, err + } + + return op, nil +} diff --git a/components/transaction/internal/app/query/get-id-operaton-account_test.go b/components/transaction/internal/app/query/get-id-operaton-account_test.go deleted file mode 100644 index 697345c4..00000000 --- a/components/transaction/internal/app/query/get-id-operaton-account_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package query - -import ( - "context" - "errors" - "testing" - - o "github.com/LerianStudio/midaz/components/transaction/internal/domain/operation" - mock "github.com/LerianStudio/midaz/components/transaction/internal/gen/mock/operation" - "github.com/google/uuid" - "github.com/stretchr/testify/assert" - "go.uber.org/mock/gomock" -) - -func TestGetOperationByAccount(t *testing.T) { - ID := uuid.New() - organizationID := uuid.New() - ledgerID := uuid.New() - accountID := uuid.New() - - operation := &o.Operation{ - ID: ID.String(), - OrganizationID: organizationID.String(), - LedgerID: ledgerID.String(), - AccountID: accountID.String(), - } - - uc := UseCase{ - OperationRepo: mock.NewMockRepository(gomock.NewController(t)), - } - - uc.OperationRepo.(*mock.MockRepository). - EXPECT(). - FindByAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(operation, nil). - Times(1) - res, err := uc.OperationRepo.FindByAccount(context.TODO(), organizationID, ledgerID, accountID, ID) - - assert.Equal(t, operation, res) - assert.Nil(t, err) -} - -func TestGetOperationByAccountError(t *testing.T) { - errMSG := "err to create account on database" - ID := uuid.New() - organizationID := uuid.New() - ledgerID := uuid.New() - accountID := uuid.New() - - uc := UseCase{ - OperationRepo: mock.NewMockRepository(gomock.NewController(t)), - } - - uc.OperationRepo.(*mock.MockRepository). - EXPECT(). - FindByAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(nil, errors.New(errMSG)). - Times(1) - res, err := uc.OperationRepo.FindByAccount(context.TODO(), organizationID, ledgerID, accountID, ID) - - assert.NotEmpty(t, err) - assert.Equal(t, err.Error(), errMSG) - assert.Nil(t, res) -} diff --git a/components/transaction/internal/domain/operation/operation_repository.go b/components/transaction/internal/domain/operation/operation_repository.go index 5bc80402..820425c7 100644 --- a/components/transaction/internal/domain/operation/operation_repository.go +++ b/components/transaction/internal/domain/operation/operation_repository.go @@ -16,6 +16,7 @@ type Repository interface { FindAllByPortfolio(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, limit, page int) ([]*Operation, error) Find(ctx context.Context, organizationID, ledgerID, id uuid.UUID) (*Operation, error) FindByAccount(ctx context.Context, organizationID, ledgerID, accountID, id uuid.UUID) (*Operation, error) + FindByPortfolio(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID) (*Operation, error) ListByIDs(ctx context.Context, organizationID, ledgerID uuid.UUID, ids []uuid.UUID) ([]*Operation, error) Update(ctx context.Context, organizationID, ledgerID, id uuid.UUID, operation *Operation) (*Operation, error) Delete(ctx context.Context, organizationID, ledgerID, id uuid.UUID) error diff --git a/components/transaction/internal/gen/mock/operation/operation_mock.go b/components/transaction/internal/gen/mock/operation/operation_mock.go index e1698e8e..97fe6317 100644 --- a/components/transaction/internal/gen/mock/operation/operation_mock.go +++ b/components/transaction/internal/gen/mock/operation/operation_mock.go @@ -145,6 +145,21 @@ func (mr *MockRepositoryMockRecorder) FindByAccount(arg0, arg1, arg2, arg3, arg4 return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByAccount", reflect.TypeOf((*MockRepository)(nil).FindByAccount), arg0, arg1, arg2, arg3, arg4) } +// FindByPortfolio mocks base method. +func (m *MockRepository) FindByPortfolio(arg0 context.Context, arg1, arg2, arg3, arg4 uuid.UUID) (*operation.Operation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByPortfolio", arg0, arg1, arg2, arg3, arg4) + ret0, _ := ret[0].(*operation.Operation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindByPortfolio indicates an expected call of FindByPortfolio. +func (mr *MockRepositoryMockRecorder) FindByPortfolio(arg0, arg1, arg2, arg3, arg4 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByPortfolio", reflect.TypeOf((*MockRepository)(nil).FindByPortfolio), arg0, arg1, arg2, arg3, arg4) +} + // ListByIDs mocks base method. func (m *MockRepository) ListByIDs(arg0 context.Context, arg1, arg2 uuid.UUID, arg3 []uuid.UUID) ([]*operation.Operation, error) { m.ctrl.T.Helper() diff --git a/components/transaction/internal/ports/http/operation.go b/components/transaction/internal/ports/http/operation.go index b9a500ee..8f33a818 100644 --- a/components/transaction/internal/ports/http/operation.go +++ b/components/transaction/internal/ports/http/operation.go @@ -102,3 +102,25 @@ func (handler *OperationHandler) GetAllOperationsByPortfolio(c *fiber.Ctx) error return commonHTTP.OK(c, pagination) } + +func (handler *OperationHandler) GetOperationByPortfolio(c *fiber.Ctx) error { + ctx := c.UserContext() + logger := mlog.NewLoggerFromContext(c.UserContext()) + + organizationID := c.Params("organization_id") + ledgerID := c.Params("ledger_id") + portfolioID := c.Params("portfolio_id") + operationID := c.Params("operation_id") + + logger.Infof("Initiating retrieval of Operation by portfolio") + + operation, err := handler.Query.GetOperationByPortfolio(ctx, organizationID, ledgerID, portfolioID, operationID) + if err != nil { + logger.Errorf("Failed to retrieve Operation by portfolio, Error: %s", err.Error()) + return commonHTTP.WithError(c, err) + } + + logger.Infof("Successfully retrieved Operation by portfolio") + + return commonHTTP.OK(c, operation) +} diff --git a/components/transaction/internal/ports/http/routes.go b/components/transaction/internal/ports/http/routes.go index fadbaa5c..0191a0cf 100644 --- a/components/transaction/internal/ports/http/routes.go +++ b/components/transaction/internal/ports/http/routes.go @@ -32,10 +32,11 @@ func NewRouter(cc *mcasdoor.CasdoorConnection, th *TransactionHandler, oh *Opera // Operations f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:account_id/operations", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("operations"), oh.GetAllOperationsByAccount) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/operations", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("operations"), oh.GetAllOperationsByPortfolio) f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/accounts/:account_id/operations/:operation_id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("operations"), oh.GetOperationByAccount) - // f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/operations/:operation_id", nil) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/operations", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("operations"), oh.GetAllOperationsByPortfolio) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/operations/:operation_id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("operations"), oh.GetOperationByPortfolio) + // f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/transactions/:transaction_id/operations/:operation_id", nil) // Health From 8bdd21666c32a7a37ef0ee498908d654e4c161d3 Mon Sep 17 00:00:00 2001 From: Andre Russowsky Date: Tue, 15 Oct 2024 11:30:13 -0300 Subject: [PATCH 02/62] chore: unit test :wrench: --- .../query/get-id-operation-account_test.go | 64 +++++++++++++++++++ .../query/get-id-operation-portifolio_test.go | 64 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 components/transaction/internal/app/query/get-id-operation-account_test.go create mode 100644 components/transaction/internal/app/query/get-id-operation-portifolio_test.go diff --git a/components/transaction/internal/app/query/get-id-operation-account_test.go b/components/transaction/internal/app/query/get-id-operation-account_test.go new file mode 100644 index 00000000..5a17e8e4 --- /dev/null +++ b/components/transaction/internal/app/query/get-id-operation-account_test.go @@ -0,0 +1,64 @@ +package query + +import ( + "context" + "errors" + "testing" + + o "github.com/LerianStudio/midaz/components/transaction/internal/domain/operation" + mock "github.com/LerianStudio/midaz/components/transaction/internal/gen/mock/operation" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" +) + +func TestGetOperationByAccount(t *testing.T) { + ID := uuid.New() + organizationID := uuid.New() + ledgerID := uuid.New() + accountID := uuid.New() + + operation := &o.Operation{ + ID: ID.String(), + OrganizationID: organizationID.String(), + LedgerID: ledgerID.String(), + AccountID: accountID.String(), + } + + uc := UseCase{ + OperationRepo: mock.NewMockRepository(gomock.NewController(t)), + } + + uc.OperationRepo.(*mock.MockRepository). + EXPECT(). + FindByAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(operation, nil). + Times(1) + res, err := uc.OperationRepo.FindByAccount(context.TODO(), organizationID, ledgerID, accountID, ID) + + assert.Equal(t, operation, res) + assert.Nil(t, err) +} + +func TestGetOperationByAccountError(t *testing.T) { + errMSG := "err to get operation on database" + ID := uuid.New() + organizationID := uuid.New() + ledgerID := uuid.New() + accountID := uuid.New() + + uc := UseCase{ + OperationRepo: mock.NewMockRepository(gomock.NewController(t)), + } + + uc.OperationRepo.(*mock.MockRepository). + EXPECT(). + FindByAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(nil, errors.New(errMSG)). + Times(1) + res, err := uc.OperationRepo.FindByAccount(context.TODO(), organizationID, ledgerID, accountID, ID) + + assert.NotEmpty(t, err) + assert.Equal(t, err.Error(), errMSG) + assert.Nil(t, res) +} diff --git a/components/transaction/internal/app/query/get-id-operation-portifolio_test.go b/components/transaction/internal/app/query/get-id-operation-portifolio_test.go new file mode 100644 index 00000000..70852c6a --- /dev/null +++ b/components/transaction/internal/app/query/get-id-operation-portifolio_test.go @@ -0,0 +1,64 @@ +package query + +import ( + "context" + "errors" + "testing" + + o "github.com/LerianStudio/midaz/components/transaction/internal/domain/operation" + mock "github.com/LerianStudio/midaz/components/transaction/internal/gen/mock/operation" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" +) + +func TestGetOperationByPortfolio(t *testing.T) { + ID := uuid.New() + organizationID := uuid.New() + ledgerID := uuid.New() + portfolioID := uuid.New() + + operation := &o.Operation{ + ID: ID.String(), + OrganizationID: organizationID.String(), + LedgerID: ledgerID.String(), + PortfolioID: portfolioID.String(), + } + + uc := UseCase{ + OperationRepo: mock.NewMockRepository(gomock.NewController(t)), + } + + uc.OperationRepo.(*mock.MockRepository). + EXPECT(). + FindByPortfolio(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(operation, nil). + Times(1) + res, err := uc.OperationRepo.FindByPortfolio(context.TODO(), organizationID, ledgerID, portfolioID, ID) + + assert.Equal(t, operation, res) + assert.Nil(t, err) +} + +func TestGetOperationByPortfolioError(t *testing.T) { + errMSG := "err to get operation on database" + ID := uuid.New() + organizationID := uuid.New() + ledgerID := uuid.New() + portfolioID := uuid.New() + + uc := UseCase{ + OperationRepo: mock.NewMockRepository(gomock.NewController(t)), + } + + uc.OperationRepo.(*mock.MockRepository). + EXPECT(). + FindByPortfolio(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(nil, errors.New(errMSG)). + Times(1) + res, err := uc.OperationRepo.FindByPortfolio(context.TODO(), organizationID, ledgerID, portfolioID, ID) + + assert.NotEmpty(t, err) + assert.Equal(t, err.Error(), errMSG) + assert.Nil(t, res) +} From c97138d0239d71df0e91e79d566ebdaaab8235b1 Mon Sep 17 00:00:00 2001 From: Andre Russowsky Date: Tue, 15 Oct 2024 15:37:56 -0300 Subject: [PATCH 03/62] chore: postman update :wrench: --- postman/MIDAZ.postman_collection.json | 54 ++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/postman/MIDAZ.postman_collection.json b/postman/MIDAZ.postman_collection.json index 1b315688..6f8bdef5 100644 --- a/postman/MIDAZ.postman_collection.json +++ b/postman/MIDAZ.postman_collection.json @@ -1,10 +1,10 @@ { "info": { - "_postman_id": "8e5e00be-8120-4cc4-a7e3-fd52c0f4a06f", + "_postman_id": "11d6371b-14bf-4e75-9a8c-93f0a53d7355", "name": "MIDAZ", "description": "# 🚀 Get started here\n\nThis template guides you through CRUD operations (GET, POST, PUT, DELETE), variables, and tests.\n\n## 🔖 **How to use this template**\n\n#### **Step 1: Send requests**\n\nRESTful APIs allow you to perform CRUD operations using the POST, GET, PUT, and DELETE HTTP methods.\n\nThis collection contains each of these [request](https://learning.postman.com/docs/sending-requests/requests/) types. Open each request and click \"Send\" to see what happens.\n\n#### **Step 2: View responses**\n\nObserve the response tab for status code (200 OK), response time, and size.\n\n#### **Step 3: Send new Body data**\n\nUpdate or add new data in \"Body\" in the POST request. Typically, Body data is also used in PUT request.\n\n```\n{\n \"name\": \"Add your name in the body\"\n}\n\n ```\n\n#### **Step 4: Update the variable**\n\nVariables enable you to store and reuse values in Postman. We have created a [variable](https://learning.postman.com/docs/sending-requests/variables/) called `base_url` with the sample request [https://postman-api-learner.glitch.me](https://postman-api-learner.glitch.me). Replace it with your API endpoint to customize this collection.\n\n#### **Step 5: Add tests in the \"Tests\" tab**\n\nTests help you confirm that your API is working as expected. You can write test scripts in JavaScript and view the output in the \"Test Results\" tab.\n\n\n\n## 💪 Pro tips\n\n- Use folders to group related requests and organize the collection.\n- Add more [scripts](https://learning.postman.com/docs/writing-scripts/intro-to-scripts/) in \"Tests\" to verify if the API works as expected and execute workflows.\n \n\n## 💡Related templates\n\n[API testing basics](https://go.postman.co/redirect/workspace?type=personal&collectionTemplateId=e9a37a28-055b-49cd-8c7e-97494a21eb54&sourceTemplateId=ddb19591-3097-41cf-82af-c84273e56719) \n[API documentation](https://go.postman.co/redirect/workspace?type=personal&collectionTemplateId=e9c28f47-1253-44af-a2f3-20dce4da1f18&sourceTemplateId=ddb19591-3097-41cf-82af-c84273e56719) \n[Authorization methods](https://go.postman.co/redirect/workspace?type=personal&collectionTemplateId=31a9a6ed-4cdf-4ced-984c-d12c9aec1c27&sourceTemplateId=ddb19591-3097-41cf-82af-c84273e56719)", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "32592108" + "_exporter_id": "38753084" }, "item": [ { @@ -2215,6 +2215,31 @@ }, "response": [] }, + { + "name": "Operation by account", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/accounts/{{account_id}}/operations/{{operation_id}}", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "accounts", + "{{account_id}}", + "operations", + "{{operation_id}}" + ] + } + }, + "response": [] + }, { "name": "Operations by portfolio", "request": { @@ -2238,6 +2263,31 @@ } }, "response": [] + }, + { + "name": "Operation by portfolio", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/portfolios/{{portfolio_id}}/operations/{{operation_id}}", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "portfolios", + "{{portfolio_id}}", + "operations", + "{{operation_id}}" + ] + } + }, + "response": [] } ] } From bc4b697c2e50cd1ec3cd41e0f96cb933a17b6a79 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Wed, 16 Oct 2024 13:28:35 -0300 Subject: [PATCH 04/62] fix: resolve conflicts :bug: --- postman/MIDAZ.postman_collection.json | 379 +++++++++++++++++--------- 1 file changed, 257 insertions(+), 122 deletions(-) diff --git a/postman/MIDAZ.postman_collection.json b/postman/MIDAZ.postman_collection.json index 6f8bdef5..2373cf9b 100644 --- a/postman/MIDAZ.postman_collection.json +++ b/postman/MIDAZ.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "11d6371b-14bf-4e75-9a8c-93f0a53d7355", + "_postman_id": "85863248-3216-47d3-a390-d3c07d1e5c2b", "name": "MIDAZ", "description": "# 🚀 Get started here\n\nThis template guides you through CRUD operations (GET, POST, PUT, DELETE), variables, and tests.\n\n## 🔖 **How to use this template**\n\n#### **Step 1: Send requests**\n\nRESTful APIs allow you to perform CRUD operations using the POST, GET, PUT, and DELETE HTTP methods.\n\nThis collection contains each of these [request](https://learning.postman.com/docs/sending-requests/requests/) types. Open each request and click \"Send\" to see what happens.\n\n#### **Step 2: View responses**\n\nObserve the response tab for status code (200 OK), response time, and size.\n\n#### **Step 3: Send new Body data**\n\nUpdate or add new data in \"Body\" in the POST request. Typically, Body data is also used in PUT request.\n\n```\n{\n \"name\": \"Add your name in the body\"\n}\n\n ```\n\n#### **Step 4: Update the variable**\n\nVariables enable you to store and reuse values in Postman. We have created a [variable](https://learning.postman.com/docs/sending-requests/variables/) called `base_url` with the sample request [https://postman-api-learner.glitch.me](https://postman-api-learner.glitch.me). Replace it with your API endpoint to customize this collection.\n\n#### **Step 5: Add tests in the \"Tests\" tab**\n\nTests help you confirm that your API is working as expected. You can write test scripts in JavaScript and view the output in the \"Test Results\" tab.\n\n\n\n## 💪 Pro tips\n\n- Use folders to group related requests and organize the collection.\n- Add more [scripts](https://learning.postman.com/docs/writing-scripts/intro-to-scripts/) in \"Tests\" to verify if the API works as expected and execute workflows.\n \n\n## 💡Related templates\n\n[API testing basics](https://go.postman.co/redirect/workspace?type=personal&collectionTemplateId=e9a37a28-055b-49cd-8c7e-97494a21eb54&sourceTemplateId=ddb19591-3097-41cf-82af-c84273e56719) \n[API documentation](https://go.postman.co/redirect/workspace?type=personal&collectionTemplateId=e9c28f47-1253-44af-a2f3-20dce4da1f18&sourceTemplateId=ddb19591-3097-41cf-82af-c84273e56719) \n[Authorization methods](https://go.postman.co/redirect/workspace?type=personal&collectionTemplateId=31a9a6ed-4cdf-4ced-984c-d12c9aec1c27&sourceTemplateId=ddb19591-3097-41cf-82af-c84273e56719)", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", @@ -23,7 +23,7 @@ "listen": "test", "script": { "exec": [ - "postman.setEnvironmentVariable(\"access_token\", pm.request.auth.oauth2.get(\"accessToken\"));" + "" ], "type": "text/javascript", "packages": {} @@ -700,6 +700,38 @@ }, "response": [] } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } ] }, { @@ -909,6 +941,38 @@ }, "response": [] } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } ] }, { @@ -1075,33 +1139,38 @@ } }, "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } }, { - "name": "Assets", - "request": { - "method": "DELETE", - "header": [], - "body": { - "mode": "formdata", - "formdata": [] - }, - "url": { - "raw": "{{url}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/assets/{{asset_id}}", - "host": [ - "{{url}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "assets", - "{{asset_id}}" - ] - } - }, - "response": [] + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } } ] }, @@ -1297,6 +1366,38 @@ }, "response": [] } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } ] }, { @@ -1498,6 +1599,38 @@ }, "response": [] } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } ] }, { @@ -1523,21 +1656,11 @@ } ], "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\n \"assetCode\": \"BRL\",\n \"name\": \"{{$randomBankAccountName}}\",\n \"alias\": \"@wallet_{{$randomBankAccount}}\",\n \"type\": \"deposit\",\n //\"parentAccountId\": \"{{account_id}}\",\n //\"entityId\": \"{{$randomUUID}}\", //optional\n \"productId\": \"{{product_id}}\",\n \"status\": {\n \"code\": \"CREDIT\",\n \"description\": \"Teste Account\",\n \"allowSending\": true,\n \"allowReceiving\": true\n },\n \"metadata\": {\n \"chave\": \"metadata_chave\",\n \"bitcoinn\": \"{{$randomBitcoin}}\",\n \"boolean\": {{$randomBoolean}},\n \"double\": 10.5,\n \"int\": 1\n }\n}", + "raw": "{\n \"assetCode\": \"BRL\",\n \"name\": \"{{$randomBankAccountName}}\",\n \"alias\": \"@wallet_{{$randomBankAccount}}\",\n \"type\": \"DEBIT\",\n //\"parentAccountId\": \"{{account_id}}\",\n //\"entityId\": \"{{$randomUUID}}\", //optional\n \"productId\": \"{{product_id}}\",\n \"status\": {\n \"code\": \"CREDIT\",\n \"description\": \"Teste Account\",\n \"allowSending\": true,\n \"allowReceiving\": true\n },\n \"metadata\": {\n \"chave\": \"metadata_chave\",\n \"bitcoinn\": \"{{$randomBitcoin}}\",\n \"boolean\": {{$randomBoolean}},\n \"double\": 10.5,\n \"int\": 1\n }\n}", "options": { "raw": { "language": "json" @@ -1711,6 +1834,65 @@ } }, "response": [] + }, + { + "name": "Accounts by by asset id", + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "formdata", + "formdata": [] + }, + "url": { + "raw": "{{url}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/assets/{{asset_id}}", + "host": [ + "{{url}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "assets", + "{{asset_id}}" + ] + } + }, + "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } } ] }, @@ -1738,19 +1920,7 @@ ], "request": { "method": "POST", - "header": [ - { - "key": "idempotencyKey", - "value": "{{$randomUUID}}", - "type": "text" - }, - { - "key": "tolerance", - "value": "300", - "description": "seconds", - "type": "text" - } - ], + "header": [], "body": { "mode": "formdata", "formdata": [ @@ -2072,36 +2242,10 @@ "response": [] }, { - "name": "transactions", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "const jsonData = JSON.parse(responseBody);", - "if (jsonData.hasOwnProperty('id')) {", - " console.log(\"transaction_id before: \" + postman.getEnvironmentVariable(\"transaction_id\"));", - " postman.setEnvironmentVariable(\"transaction_id\", jsonData.id);", - " console.log(\"transaction_id after: \" + postman.getEnvironmentVariable(\"transaction_id\"));", - "}" - ], - "type": "text/javascript", - "packages": {} - } - } - ], + "name": "Transaction by id", "request": { - "method": "PATCH", + "method": "GET", "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"description\": \"description for the transaction mcgregor to jeff value of 100 reais\",\n \"metadata\": {\n \"mensagem\": \"pagamento\",\n \"valor\": \"100\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, "url": { "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/{{transaction_id}}", "host": [ @@ -2116,18 +2260,17 @@ "transactions", "{{transaction_id}}" ] - }, - "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." + } }, "response": [] }, { - "name": "Operation by account", + "name": "Transactions", "request": { "method": "GET", "header": [], "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/accounts/{{account_id}}/operations/{{operation_id}}", + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions", "host": [ "{{url_transaction}}" ], @@ -2137,20 +2280,43 @@ "{{organization_id}}", "ledgers", "{{ledger_id}}", - "accounts", - "{{account_id}}", - "operations", - "{{operation_id}}" + "transactions" ] } }, "response": [] }, { - "name": "Transaction by id", + "name": "transactions", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const jsonData = JSON.parse(responseBody);", + "if (jsonData.hasOwnProperty('id')) {", + " console.log(\"transaction_id before: \" + postman.getEnvironmentVariable(\"transaction_id\"));", + " postman.setEnvironmentVariable(\"transaction_id\", jsonData.id);", + " console.log(\"transaction_id after: \" + postman.getEnvironmentVariable(\"transaction_id\"));", + "}" + ], + "type": "text/javascript", + "packages": {} + } + } + ], "request": { - "method": "GET", + "method": "PATCH", "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"description\": \"description for the transaction mcgregor to jeff value of 100 reais\",\n \"metadata\": {\n \"mensagem\": \"pagamento\",\n \"valor\": \"100\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, "url": { "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/{{transaction_id}}", "host": [ @@ -2165,29 +2331,8 @@ "transactions", "{{transaction_id}}" ] - } - }, - "response": [] - }, - { - "name": "Transactions", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "transactions" - ] - } + }, + "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." }, "response": [] }, @@ -2292,16 +2437,6 @@ ] } ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, "event": [ { "listen": "prerequest", From 3bf9fa9982165dd73597828f7d266b2fc2405c95 Mon Sep 17 00:00:00 2001 From: Andre Russowsky Date: Tue, 15 Oct 2024 15:40:54 -0300 Subject: [PATCH 05/62] chore: postman update :wrench: --- postman/MIDAZ.postman_collection.json | 349 +++++--------------------- 1 file changed, 60 insertions(+), 289 deletions(-) diff --git a/postman/MIDAZ.postman_collection.json b/postman/MIDAZ.postman_collection.json index 2373cf9b..973baf48 100644 --- a/postman/MIDAZ.postman_collection.json +++ b/postman/MIDAZ.postman_collection.json @@ -23,7 +23,7 @@ "listen": "test", "script": { "exec": [ - "" + "postman.setEnvironmentVariable(\"access_token\", pm.request.auth.oauth2.get(\"accessToken\"));" ], "type": "text/javascript", "packages": {} @@ -700,38 +700,6 @@ }, "response": [] } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } ] }, { @@ -941,38 +909,6 @@ }, "response": [] } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } ] }, { @@ -1139,38 +1075,33 @@ } }, "response": [] - } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } }, { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } + "name": "Assets", + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "formdata", + "formdata": [] + }, + "url": { + "raw": "{{url}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/assets/{{asset_id}}", + "host": [ + "{{url}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "assets", + "{{asset_id}}" + ] + } + }, + "response": [] } ] }, @@ -1366,38 +1297,6 @@ }, "response": [] } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } ] }, { @@ -1599,38 +1498,6 @@ }, "response": [] } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } ] }, { @@ -1656,11 +1523,21 @@ } ], "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\n \"assetCode\": \"BRL\",\n \"name\": \"{{$randomBankAccountName}}\",\n \"alias\": \"@wallet_{{$randomBankAccount}}\",\n \"type\": \"DEBIT\",\n //\"parentAccountId\": \"{{account_id}}\",\n //\"entityId\": \"{{$randomUUID}}\", //optional\n \"productId\": \"{{product_id}}\",\n \"status\": {\n \"code\": \"CREDIT\",\n \"description\": \"Teste Account\",\n \"allowSending\": true,\n \"allowReceiving\": true\n },\n \"metadata\": {\n \"chave\": \"metadata_chave\",\n \"bitcoinn\": \"{{$randomBitcoin}}\",\n \"boolean\": {{$randomBoolean}},\n \"double\": 10.5,\n \"int\": 1\n }\n}", + "raw": "{\n \"assetCode\": \"BRL\",\n \"name\": \"{{$randomBankAccountName}}\",\n \"alias\": \"@wallet_{{$randomBankAccount}}\",\n \"type\": \"deposit\",\n //\"parentAccountId\": \"{{account_id}}\",\n //\"entityId\": \"{{$randomUUID}}\", //optional\n \"productId\": \"{{product_id}}\",\n \"status\": {\n \"code\": \"CREDIT\",\n \"description\": \"Teste Account\",\n \"allowSending\": true,\n \"allowReceiving\": true\n },\n \"metadata\": {\n \"chave\": \"metadata_chave\",\n \"bitcoinn\": \"{{$randomBitcoin}}\",\n \"boolean\": {{$randomBoolean}},\n \"double\": 10.5,\n \"int\": 1\n }\n}", "options": { "raw": { "language": "json" @@ -1834,65 +1711,6 @@ } }, "response": [] - }, - { - "name": "Accounts by by asset id", - "request": { - "method": "DELETE", - "header": [], - "body": { - "mode": "formdata", - "formdata": [] - }, - "url": { - "raw": "{{url}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/assets/{{asset_id}}", - "host": [ - "{{url}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "assets", - "{{asset_id}}" - ] - } - }, - "response": [] - } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } } ] }, @@ -1920,7 +1738,19 @@ ], "request": { "method": "POST", - "header": [], + "header": [ + { + "key": "idempotencyKey", + "value": "{{$randomUUID}}", + "type": "text" + }, + { + "key": "tolerance", + "value": "300", + "description": "seconds", + "type": "text" + } + ], "body": { "mode": "formdata", "formdata": [ @@ -2241,51 +2071,6 @@ }, "response": [] }, - { - "name": "Transaction by id", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/{{transaction_id}}", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "transactions", - "{{transaction_id}}" - ] - } - }, - "response": [] - }, - { - "name": "Transactions", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "transactions" - ] - } - }, - "response": [] - }, { "name": "transactions", "event": [ @@ -2336,30 +2121,6 @@ }, "response": [] }, - { - "name": "Operations by account", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/accounts/{{account_id}}/operations", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "accounts", - "{{account_id}}", - "operations" - ] - } - }, - "response": [] - }, { "name": "Operation by account", "request": { @@ -2437,6 +2198,16 @@ ] } ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, "event": [ { "listen": "prerequest", From b5d92bec5cc189fa601dfc33f73998b1596ed1c1 Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Tue, 15 Oct 2024 18:56:51 +0000 Subject: [PATCH 06/62] chore(release): 1.16.0-beta.3 ## [1.16.0-beta.3](https://github.com/LerianStudio/midaz/compare/v1.16.0-beta.2...v1.16.0-beta.3) (2024-10-15) ### Features * implement get operation by portfolio :sparkles: ([35702ae](https://github.com/LerianStudio/midaz/commit/35702ae99ed667a001a317f8932796d6e540d32a)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92cf81d3..d24fb37e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.16.0-beta.3](https://github.com/LerianStudio/midaz/compare/v1.16.0-beta.2...v1.16.0-beta.3) (2024-10-15) + + +### Features + +* implement get operation by portfolio :sparkles: ([35702ae](https://github.com/LerianStudio/midaz/commit/35702ae99ed667a001a317f8932796d6e540d32a)) + ## [1.16.0-beta.2](https://github.com/LerianStudio/midaz/compare/v1.16.0-beta.1...v1.16.0-beta.2) (2024-10-15) ## [1.16.0-beta.1](https://github.com/LerianStudio/midaz/compare/v1.15.0...v1.16.0-beta.1) (2024-10-15) From 6ebff8a40ba097b0eaa4feb1106ebc29a5ba84dc Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Wed, 16 Oct 2024 12:52:31 -0300 Subject: [PATCH 07/62] feat: initialize CLI with root and version commands :sparkles: --- components/mdz/.golangci.yml | 13 + components/mdz/Makefile | 35 ++ components/mdz/main.go | 22 +- components/mdz/pkg/claims.go | 19 -- components/mdz/pkg/cmd/root/help.go | 222 ++++++++++++ components/mdz/pkg/cmd/root/root.go | 57 ++++ components/mdz/pkg/cmd/utils/utils.go | 7 + components/mdz/pkg/cmd/version/version.go | 37 ++ components/mdz/pkg/command.go | 392 ---------------------- components/mdz/pkg/config.go | 176 ---------- components/mdz/pkg/controller.go | 30 -- components/mdz/pkg/factory/factory.go | 23 ++ components/mdz/pkg/flags.go | 106 ------ components/mdz/pkg/http.go | 163 --------- components/mdz/pkg/iostreams/iostreams.go | 20 ++ components/mdz/pkg/manager.go | 73 ---- components/mdz/pkg/output/output.go | 41 +++ components/mdz/pkg/profile.go | 261 -------------- components/mdz/pkg/relyingparty.go | 14 - components/mdz/pkg/utils.go | 54 --- 20 files changed, 475 insertions(+), 1290 deletions(-) create mode 100644 components/mdz/.golangci.yml create mode 100644 components/mdz/Makefile delete mode 100644 components/mdz/pkg/claims.go create mode 100644 components/mdz/pkg/cmd/root/help.go create mode 100644 components/mdz/pkg/cmd/root/root.go create mode 100644 components/mdz/pkg/cmd/utils/utils.go create mode 100644 components/mdz/pkg/cmd/version/version.go delete mode 100644 components/mdz/pkg/command.go delete mode 100644 components/mdz/pkg/config.go delete mode 100644 components/mdz/pkg/controller.go create mode 100644 components/mdz/pkg/factory/factory.go delete mode 100644 components/mdz/pkg/flags.go delete mode 100644 components/mdz/pkg/http.go create mode 100644 components/mdz/pkg/iostreams/iostreams.go delete mode 100644 components/mdz/pkg/manager.go create mode 100644 components/mdz/pkg/output/output.go delete mode 100644 components/mdz/pkg/profile.go delete mode 100644 components/mdz/pkg/relyingparty.go delete mode 100644 components/mdz/pkg/utils.go diff --git a/components/mdz/.golangci.yml b/components/mdz/.golangci.yml new file mode 100644 index 00000000..c098be3d --- /dev/null +++ b/components/mdz/.golangci.yml @@ -0,0 +1,13 @@ +linters: + enable: + - revive + - errcheck + - unused + - staticcheck + - gocritic + +issues: + exclude-rules: + - path: _test\.go + text: "test files" + diff --git a/components/mdz/Makefile b/components/mdz/Makefile new file mode 100644 index 00000000..379cd3d0 --- /dev/null +++ b/components/mdz/Makefile @@ -0,0 +1,35 @@ +GO := $(shell which go) +NAME := mdz + +ifeq (, $(GO)) +$(error "No go binary found in your system, please install go version go1.23.2 before continuing") +endif + +.PHONY: get-lint-deps +get-lint-deps: + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +.PHONY: lint +lint: get-lint-deps + golangci-lint run ./... --verbose + +.PHONY: get-govulncheck-deps +get-govulncheck-deps: + go install golang.org/x/vuln/cmd/govulncheck@latest + +.PHONY: govulncheck +govulncheck: get-govulncheck-deps + govulncheck ./... + +.PHONY: gosec +gosec: get-gosec-deps + gosec ./... + +.PHONY: get-gosec-deps +get-gosec-deps: + go install github.com/securego/gosec/v2/cmd/gosec@latest + +.PHONY : build +build: + go version + go build -o ./bin/$(NAME) ./main.go diff --git a/components/mdz/main.go b/components/mdz/main.go index 77fb2453..abb3f713 100644 --- a/components/mdz/main.go +++ b/components/mdz/main.go @@ -1,9 +1,27 @@ package main import ( - "github.com/LerianStudio/midaz/components/mdz/cmd" + "fmt" + "os" + + "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/root" + "github.com/LerianStudio/midaz/components/mdz/pkg/factory" + "github.com/LerianStudio/midaz/components/mdz/pkg/output" ) func main() { - cmd.Execute() + f := factory.NewFactory() + cmd := root.NewCmdRoot(f) + if err := cmd.Execute(); err != nil { + printErr := output.Print(&output.ErrorOutput{ + GeneralOutput: output.GeneralOutput{ + Out: f.IOStreams.Err, + }, + Err: err, + }) + if printErr != nil { + fmt.Fprintf(os.Stderr, "Failed to print error output: %v\n", printErr) + os.Exit(1) + } + } } diff --git a/components/mdz/pkg/claims.go b/components/mdz/pkg/claims.go deleted file mode 100644 index 7af311ba..00000000 --- a/components/mdz/pkg/claims.go +++ /dev/null @@ -1,19 +0,0 @@ -package pkg - -type stackClaim struct { - ID string `json:"id"` - DisplayName string `json:"displayName"` -} -type organizationClaim struct { - ID string `json:"id"` - DisplayName string `json:"displayName"` - Stacks []stackClaim `json:"stacks"` -} -type ( - organizationsClaim []organizationClaim - userClaims struct { - Email string `json:"email"` - Subject string `json:"sub"` - Org organizationsClaim `json:"org"` - } -) diff --git a/components/mdz/pkg/cmd/root/help.go b/components/mdz/pkg/cmd/root/help.go new file mode 100644 index 00000000..98abcb02 --- /dev/null +++ b/components/mdz/pkg/cmd/root/help.go @@ -0,0 +1,222 @@ +package root + +import ( + "bytes" + "fmt" + "regexp" + "strings" + + "github.com/fatih/color" + "github.com/spf13/cobra" +) + +// help displays help for the current command, including description, synopsis, +// available commands, subcommands, examples and flag options. +func (f *factoryRoot) help(command *cobra.Command, args []string) { + if isRootCmd(command.Parent()) && len(args) >= 2 && args[1] != + "--help" && args[1] != "-h" { + nestedSuggestFunc(command, args[1]) + return + } + + var ( + baseCommands []string + subcmdCommands []string + examples []string + ) + + // If the command is not a root command, add it to the list of subcommands. + // Otherwise, add it to the list of base commands. + for _, c := range command.Commands() { + if c.Short == "" { + continue + } + + if c.Hidden { + continue + } + + s := rpad(c.Name(), c.NamePadding()) + c.Short + + switch { + case c.Annotations["Category"] == "skip": + continue + case !isRootCmd(c.Parent()): + // Help of subcommand + subcmdCommands = append(subcmdCommands, s) + continue + default: + baseCommands = append(baseCommands, s) + continue + } + } + + type helpEntry struct { + Title string + Body string + } + + if len(command.Example) > 0 { + examples = append(examples, command.Example) + } + + longText := command.Long + if longText == "" { + longText = command.Short + } + + styleTitle := color.Bold + styleBody := color.FgHiWhite + + helpEntries := []helpEntry{} + + helpEntries = append(helpEntries, helpEntry{"", color.New(color.Bold).Sprint(f.factory.CLIVersion)}) + + if longText != "" { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("DESCRIPTION"), + Body: color.New(styleBody).Sprint(longText), + }) + } + + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("SYNOPSIS"), + Body: color.New(styleBody).Sprint(command.UseLine()), + }) + + if len(examples) > 0 { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("EXAMPLES"), + Body: color.New(color.FgYellow).Sprint(strings.Join(examples, "\n")), + }) + } + + if len(baseCommands) > 0 { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("AVAILABLE COMMANDS"), + Body: color.New(styleBody).Sprint(strings.Join(baseCommands, "\n")), + }) + } + + if len(subcmdCommands) > 0 { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("AVAILABLE SUBCOMMANDS"), + Body: color.New(styleBody).Sprint(strings.Join(subcmdCommands, "\n")), + }) + } + + flagUsages := command.LocalFlags().FlagUsages() + if flagUsages != "" { + if isRootCmd(command) { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("GLOBAL OPTIONS"), + Body: color.New(styleBody).Sprint(dedent(flagUsages)), + }) + } else { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("LOCAL OPTIONS"), + Body: color.New(styleBody).Sprint(dedent(flagUsages)), + }) + } + } + + inheritedFlagUsages := command.InheritedFlags().FlagUsages() + if inheritedFlagUsages != "" { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("GLOBAL OPTIONS"), + Body: color.New(styleBody).Sprint(dedent(inheritedFlagUsages)), + }) + } + + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(styleTitle).Sprint("LEARN MORE"), + Body: color.New(styleBody).Sprint("Use 'mdz --help' for more information about a command"), + }) + + out := command.OutOrStdout() + for _, e := range helpEntries { + if e.Title != "" { + // If there is a title, add indentation to each line in the body + fmt.Fprintln(out, e.Title) + fmt.Fprintln(out, Indent(strings.Trim(e.Body, "\r\n"), " ")) + } else { + // If there is no title print the body as is + fmt.Fprintln(out, e.Body) + } + fmt.Fprintln(out) + } +} + +// nestedSuggestFunc suggests corrections when an invalid command is supplied. +// If “help” is the argument, it suggests “--help”. Otherwise, it calculates suggestions +// based on the minimum distance between the supplied command and the available commands. +func nestedSuggestFunc(command *cobra.Command, arg string) { + command.Printf("unknown command %q for %q\n", arg, command.CommandPath()) + var candidates []string + + if arg == "help" { + candidates = []string{"--help"} + } else { + if command.SuggestionsMinimumDistance <= 0 { + command.SuggestionsMinimumDistance = 2 + } + candidates = command.SuggestionsFor(arg) + } + + if len(candidates) > 0 { + command.Print("\nDid you mean this?\n") + for _, c := range candidates { + command.Printf("\t%s\n", c) + } + } + + command.Print("\n") +} + +// isRootCmd checks if the command is the root command +// root if it doesn't have a parent command (HasParent returns false) +func isRootCmd(command *cobra.Command) bool { + return command != nil && !command.HasParent() +} + +// rpad adds spacing to the right of a string up to the size specified in padding. +func rpad(s string, padding int) string { + template := fmt.Sprintf("%%-%ds ", padding) + return fmt.Sprintf(template, s) +} + +// dedent removes the smallest common indentation from all lines in a string. +func dedent(s string) string { + lines := strings.Split(s, "\n") + minIndent := -1 + + for _, l := range lines { + if len(l) == 0 { + continue + } + + indent := len(l) - len(strings.TrimLeft(l, " ")) + if minIndent == -1 || indent < minIndent { + minIndent = indent + } + } + + if minIndent <= 0 { + return s + } + + var buf bytes.Buffer + for _, l := range lines { + fmt.Fprintln(&buf, strings.TrimPrefix(l, strings.Repeat(" ", minIndent))) + } + return strings.TrimSuffix(buf.String(), "\n") +} + +// Indent Adds an indentation level to all lines of a string +func Indent(s, indent string) string { + var lineRE = regexp.MustCompile(`(?m)^`) + if len(strings.TrimSpace(s)) == 0 { + return s + } + return lineRE.ReplaceAllLiteralString(s, indent) +} diff --git a/components/mdz/pkg/cmd/root/root.go b/components/mdz/pkg/cmd/root/root.go new file mode 100644 index 00000000..aa48fad0 --- /dev/null +++ b/components/mdz/pkg/cmd/root/root.go @@ -0,0 +1,57 @@ +package root + +import ( + "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/utils" + "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/version" + "github.com/LerianStudio/midaz/components/mdz/pkg/factory" + "github.com/fatih/color" + "github.com/spf13/cobra" +) + +type factoryRoot struct { + factory *factory.Factory +} + +func (f *factoryRoot) setCmds(cmd *cobra.Command) { + cmd.AddCommand(version.NewCmdVersion(f.factory)) +} + +func (f *factoryRoot) setFlags(cmd *cobra.Command) { + cmd.Flags().BoolP("help", "h", false, "Displays more information about the Mdz CLI") +} + +func NewCmdRoot(f *factory.Factory) *cobra.Command { + fRoot := factoryRoot{ + factory: f, + } + + cmd := &cobra.Command{ + Use: "mdz", + Short: "Midaz CLI is a command-line tool for interacting with the Midaz ledger", + Long: utils.Format( + "Midaz is an open-source ledger designed to offer multi-asset and multi-currency", + "transaction capabilities within a single, natively immutable and fully auditable platform.", + ), + Version: fRoot.factory.CLIVersion, + Example: utils.Format( + "$ mdz", + "$ mdz -h", + "$ mdz --help", + ), + SilenceErrors: true, // Silence errors, so the help message won't be shown on flag error + SilenceUsage: true, // Silence usage on error + } + + cmd.SetIn(fRoot.factory.IOStreams.In) + cmd.SetOut(fRoot.factory.IOStreams.Out) + cmd.SetErr(fRoot.factory.IOStreams.Err) + + cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { + fRoot.help(cmd, args) + }) + + cmd.SetVersionTemplate(color.New(color.Bold).Sprint(fRoot.factory.CLIVersion)) + fRoot.setCmds(cmd) + fRoot.setFlags(cmd) + return cmd +} diff --git a/components/mdz/pkg/cmd/utils/utils.go b/components/mdz/pkg/cmd/utils/utils.go new file mode 100644 index 00000000..af4bb961 --- /dev/null +++ b/components/mdz/pkg/cmd/utils/utils.go @@ -0,0 +1,7 @@ +package utils + +import "strings" + +func Format(commands ...string) string { + return strings.Join(commands, "\n") +} diff --git a/components/mdz/pkg/cmd/version/version.go b/components/mdz/pkg/cmd/version/version.go new file mode 100644 index 00000000..395100c1 --- /dev/null +++ b/components/mdz/pkg/cmd/version/version.go @@ -0,0 +1,37 @@ +package version + +import ( + "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/utils" + "github.com/LerianStudio/midaz/components/mdz/pkg/factory" + "github.com/LerianStudio/midaz/components/mdz/pkg/output" + "github.com/fatih/color" + "github.com/spf13/cobra" +) + +type factoryVersion struct { + factory *factory.Factory +} + +func (f *factoryVersion) runE(_ *cobra.Command, _ []string) error { + return output.Print(&output.GeneralOutput{ + Msg: color.New(color.Bold).Sprint(f.factory.CLIVersion), + Out: f.factory.IOStreams.Out}) +} + +func NewCmdVersion(f *factory.Factory) *cobra.Command { + fVersion := factoryVersion{ + factory: f, + } + cmd := &cobra.Command{ + Use: "version", + Short: "Returns the CLI version", + Long: "Displays the version of the CLI binary installed in the computer.", + Example: utils.Format( + "$ mdz version", + "$ mdz version -h", + ), + RunE: fVersion.runE, + } + cmd.Flags().BoolP("help", "h", false, "Displays more information about the Midaz CLI") + return cmd +} diff --git a/components/mdz/pkg/command.go b/components/mdz/pkg/command.go deleted file mode 100644 index f0feed0a..00000000 --- a/components/mdz/pkg/command.go +++ /dev/null @@ -1,392 +0,0 @@ -package pkg - -import ( - "encoding/json" - "fmt" - - "github.com/pkg/errors" - "github.com/segmentio/ksuid" - "github.com/spf13/cobra" -) - -const ( - stackFlag = "stack" - organizationFlag = "organization" - outputFlag = "output" -) - -var ( - - // ErrOrganizationNotSpecified indicates that no organization was specified when one was required. - ErrOrganizationNotSpecified = errors.New("organization not specified") - - // ErrMultipleOrganizationsFound indicates that more than one organization was found when only one was expected, and no specific organization was specified. - ErrMultipleOrganizationsFound = errors.New("found more than one organization and no organization specified") -) - -// GetSelectedOrganization retrieves the selected organization from the command. -func GetSelectedOrganization(cmd *cobra.Command) string { - return GetString(cmd, organizationFlag) -} - -// RetrieveOrganizationIDFromFlagOrProfile retrieves the organization ID from the command flag or profile. -func RetrieveOrganizationIDFromFlagOrProfile(cmd *cobra.Command, cfg *Config) (string, error) { - if id := GetSelectedOrganization(cmd); id != "" { - return id, nil - } - - if defaultOrganization := GetCurrentProfile(cmd, cfg).GetDefaultOrganization(); defaultOrganization != "" { - return defaultOrganization, nil - } - - return "", ErrOrganizationNotSpecified -} - -// GetSelectedStackID retrieves the selected stack ID from the command. -func GetSelectedStackID(cmd *cobra.Command) string { - return GetString(cmd, stackFlag) -} - -// CommandOption is an interface for options that can be applied to a cobra.Command. -type CommandOption interface { - apply(cmd *cobra.Command) -} - -// CommandOptionFn is a function that applies a CommandOption to a cobra.Command. -type CommandOptionFn func(cmd *cobra.Command) - -func (fn CommandOptionFn) apply(cmd *cobra.Command) { - fn(cmd) -} - -// WithPersistentStringFlag is a helper function that returns a CommandOptionFn that applies a persistent string flag to a cobra.Command. -func WithPersistentStringFlag(name, defaultValue, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.PersistentFlags().String(name, defaultValue, help) - } -} - -// WithStringFlag is a helper function that returns a CommandOptionFn that applies a string flag to a cobra.Command. -func WithStringFlag(name, defaultValue, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Flags().String(name, defaultValue, help) - } -} - -// WithPersistentStringPFlag is a helper function that returns a CommandOptionFn that applies a persistent string flag to a cobra.Command. -func WithPersistentStringPFlag(name, short, defaultValue, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.PersistentFlags().StringP(name, short, defaultValue, help) - } -} - -// WithBoolFlag is a helper function that returns a CommandOptionFn that applies a boolean flag to a cobra.Command. -func WithBoolFlag(name string, defaultValue bool, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Flags().Bool(name, defaultValue, help) - } -} - -// WithAliases is a helper function that returns a CommandOptionFn that applies aliases to a cobra.Command. -func WithAliases(aliases ...string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Aliases = aliases - } -} - -// WithPersistentBoolPFlag is a helper function that returns a CommandOptionFn that applies a persistent boolean flag to a cobra.Command. -func WithPersistentBoolPFlag(name, short string, defaultValue bool, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.PersistentFlags().BoolP(name, short, defaultValue, help) - } -} - -// WithPersistentBoolFlag is a helper function that returns a CommandOptionFn that applies a persistent boolean flag to a cobra.Command. -func WithPersistentBoolFlag(name string, defaultValue bool, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.PersistentFlags().Bool(name, defaultValue, help) - } -} - -// WithIntFlag is a helper function that returns a CommandOptionFn that applies an integer flag to a cobra.Command. -func WithIntFlag(name string, defaultValue int, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Flags().Int(name, defaultValue, help) - } -} - -// WithStringSliceFlag is a helper function that returns a CommandOptionFn that applies a string slice flag to a cobra.Command. -func WithStringSliceFlag(name string, defaultValue []string, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Flags().StringSlice(name, defaultValue, help) - } -} - -// WithStringArrayFlag is a helper function that returns a CommandOptionFn that applies a string array flag to a cobra.Command. -func WithStringArrayFlag(name string, defaultValue []string, help string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Flags().StringArray(name, defaultValue, help) - } -} - -// WithHiddenFlag is a helper function that returns a CommandOptionFn that applies a hidden flag to a cobra.Command. -func WithHiddenFlag(name string) CommandOptionFn { - return func(cmd *cobra.Command) { - _ = cmd.Flags().MarkHidden(name) - } -} - -// WithHidden is a helper function that returns a CommandOptionFn that applies a hidden flag to a cobra.Command. -func WithHidden() CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Hidden = true - } -} - -// WithRunE is a helper function that returns a CommandOptionFn that applies a run function to a cobra.Command. -func WithRunE(fn func(cmd *cobra.Command, args []string) error) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.RunE = fn - } -} - -// WithPersistentPreRunE is a helper function that returns a CommandOptionFn that applies a persistent pre-run function to a cobra.Command. -func WithPersistentPreRunE(fn func(cmd *cobra.Command, args []string) error) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.PersistentPreRunE = fn - } -} - -// WithPreRunE is a helper function that returns a CommandOptionFn that applies a pre-run function to a cobra.Command. -func WithPreRunE(fn func(cmd *cobra.Command, args []string) error) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.PreRunE = fn - } -} - -// WithDeprecatedFlag is a helper function that returns a CommandOptionFn that applies a deprecated flag to a cobra.Command. -func WithDeprecatedFlag(name, message string) CommandOptionFn { - return func(cmd *cobra.Command) { - _ = cmd.Flags().MarkDeprecated(name, message) - } -} - -// WithDeprecated is a helper function that returns a CommandOptionFn that applies a deprecated flag to a cobra.Command. -func WithDeprecated(message string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Deprecated = message - } -} - -// WithChildCommands is a helper function that returns a CommandOptionFn that applies child commands to a cobra.Command. -func WithChildCommands(cmds ...*cobra.Command) CommandOptionFn { - return func(cmd *cobra.Command) { - for _, child := range cmds { - cmd.AddCommand(child) - } - } -} - -// WithShortDescription is a helper function that returns a CommandOptionFn that applies a short description to a cobra.Command. -func WithShortDescription(v string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Short = v - } -} - -// WithArgs is a helper function that returns a CommandOptionFn that applies positional arguments to a cobra.Command. -func WithArgs(p cobra.PositionalArgs) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Args = p - } -} - -// WithValidArgs is a helper function that returns a CommandOptionFn that applies valid arguments to a cobra.Command. -func WithValidArgs(validArgs ...string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.ValidArgs = validArgs - } -} - -// WithValidArgsFunction returns a CommandOptionFn that sets a custom validation function for command arguments. -func WithValidArgsFunction(fn func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.ValidArgsFunction = fn - } -} - -// WithDescription is a helper function that returns a CommandOptionFn that applies a description to a cobra.Command. -func WithDescription(v string) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.Long = v - } -} - -// WithSilenceUsage is a helper function that returns a CommandOptionFn that applies silence usage to a cobra.Command. -func WithSilenceUsage() CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.SilenceUsage = true - } -} - -// WithSilenceError is a helper function that returns a CommandOptionFn that applies silence error to a cobra.Command. -func WithSilenceError() CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.SilenceErrors = true - } -} - -// NewStackCommand is a helper function that returns a new stack command with the given options. -func NewStackCommand(use string, opts ...CommandOption) *cobra.Command { - cmd := NewMembershipCommand(use, - append(opts, - WithPersistentStringFlag(stackFlag, "", "Specific stack (not required if only one stack is present)"), - )..., - ) - - _ = cmd.RegisterFlagCompletionFunc("stack", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - cfg, err := GetConfig(cmd) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - - profile := GetCurrentProfile(cmd, cfg) - - claims, err := profile.getUserInfo() - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - - selectedOrganization := GetSelectedOrganization(cmd) - if selectedOrganization == "" { - selectedOrganization = profile.defaultOrganization - } - - ret := make([]string, 0) - - for _, org := range claims.Org { - if selectedOrganization != "" && selectedOrganization != org.ID { - continue - } - - for _, stack := range org.Stacks { - ret = append(ret, fmt.Sprintf("%s\t%s", stack.ID, stack.DisplayName)) - } - } - - return ret, cobra.ShellCompDirectiveDefault - }) - - return cmd -} - -// WithController wraps a controller's Run method as a cobra command's RunE function. -func WithController[T any](c Controller[T]) CommandOptionFn { - return func(cmd *cobra.Command) { - cmd.RunE = func(cmd *cobra.Command, args []string) error { - renderable, err := c.Run(cmd, args) - if err != nil { - return err - } - - err = WithRender(cmd, args, c, renderable) - if err != nil { - return err - } - - return nil - } - } -} - -// WithRender handles the rendering of the output based on the output flag. -func WithRender[T any](cmd *cobra.Command, args []string, controller Controller[T], renderable Renderable) error { - output := GetString(cmd, OutputFlag) - - switch output { - case "json": - export := ExportedData{ - Data: controller.GetStore(), - } - - out, err := json.Marshal(export) - if err != nil { - return err - } - - if err := json.NewEncoder(cmd.OutOrStdout()).Encode(out); err != nil { - return err - } - default: - return renderable.Render(cmd, args) - } - - return nil -} - -// NewMembershipCommand is a helper function that returns a new membership command with the given options. -func NewMembershipCommand(use string, opts ...CommandOption) *cobra.Command { - cmd := NewCommand(use, - append(opts, - WithPersistentStringFlag(organizationFlag, "", "Selected organization (not required if only one organization is present)"), - )..., - ) - - _ = cmd.RegisterFlagCompletionFunc("organization", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - cfg, err := GetConfig(cmd) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - - profile := GetCurrentProfile(cmd, cfg) - - claims, err := profile.getUserInfo() - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - - ret := make([]string, 0) - for _, org := range claims.Org { - ret = append(ret, fmt.Sprintf("%s\t%s", org.ID, org.DisplayName)) - } - - return ret, cobra.ShellCompDirectiveDefault - }) - - return cmd -} - -// NewCommand creates a new cobra command with the specified use string and options. -// -// Parameters: -// - use: a string representing the use of the command. -// - opts: variadic CommandOption options. -// Return type: -// - *cobra.Command: a pointer to the created cobra command. -func NewCommand(use string, opts ...CommandOption) *cobra.Command { - cmd := &cobra.Command{ - Use: use, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - if GetBool(cmd, TelemetryFlag) { - cfg, err := GetConfig(cmd) - if err != nil { - return - } - - if cfg.GetUniqueID() == "" { - uniqueID := ksuid.New().String() - cfg.SetUniqueID(uniqueID) - err = cfg.Persist() - if err != nil { - return - } - } - } - }, - } - for _, opt := range opts { - opt.apply(cmd) - } - - return cmd -} diff --git a/components/mdz/pkg/config.go b/components/mdz/pkg/config.go deleted file mode 100644 index ca9261a6..00000000 --- a/components/mdz/pkg/config.go +++ /dev/null @@ -1,176 +0,0 @@ -package pkg - -import ( - "encoding/json" - - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type persistedConfig struct { - CurrentProfile string `json:"currentProfile"` - Profiles map[string]*Profile `json:"profiles"` - UniqueID string `json:"uniqueID"` -} - -// Config represents the configuration for the application. -// It encapsulates details such as the current profile in use, a unique identifier for the configuration, -// a map of profile names to Profile instances, and a reference to the ConfigManager responsible for managing this configuration. -type Config struct { - currentProfile string - uniqueID string - profiles map[string]*Profile - manager *ConfigManager -} - -// MarshalJSON implements the json.Marshaler interface for Config. -// It converts the Config instance into a JSON-encoded byte slice. -func (c *Config) MarshalJSON() ([]byte, error) { - return json.Marshal(persistedConfig{ - CurrentProfile: c.currentProfile, - Profiles: c.profiles, - UniqueID: c.uniqueID, - }) -} - -// UnmarshalJSON implements the json.Unmarshaler interface for Config. -// It populates the Config instance with data from a JSON-encoded byte slice. -func (c *Config) UnmarshalJSON(data []byte) error { - cfg := &persistedConfig{} - if err := json.Unmarshal(data, cfg); err != nil { - return err - } - - *c = Config{ - currentProfile: cfg.CurrentProfile, - profiles: cfg.Profiles, - uniqueID: cfg.UniqueID, - } - - return nil -} - -// GetProfile retrieves a profile by name from the configuration. -// If the profile does not exist, it returns nil. -func (c *Config) GetProfile(name string) *Profile { - p := c.profiles[name] - if p != nil { - p.config = c - } - - return p -} - -// GetProfileOrDefault retrieves a profile by name from the configuration. -// If the profile does not exist, it creates a new profile with the given membership URI and returns it. -func (c *Config) GetProfileOrDefault(name, membershipURI string) *Profile { - p := c.GetProfile(name) - if p == nil { - if c.profiles == nil { - c.profiles = map[string]*Profile{} - } - - f := &Profile{ - membershipURI: membershipURI, - config: c, - } - - c.profiles[name] = f - - return f - } - - return p -} - -// DeleteProfile removes a profile from the configuration by name. -// If the profile does not exist, it returns an error. -func (c *Config) DeleteProfile(s string) error { - _, ok := c.profiles[s] - if !ok { - return errors.New("not found") - } - - delete(c.profiles, s) - - return nil -} - -// Persist saves the configuration to the file system. -// It uses the ConfigManager to update the configuration file with the current configuration. -func (c *Config) Persist() error { - return c.manager.UpdateConfig(c) -} - -// SetCurrentProfile sets the current profile to the given name and profile. -// It also updates the current profile name to the given name. -func (c *Config) SetCurrentProfile(name string, profile *Profile) { - c.profiles[name] = profile - c.currentProfile = name -} - -// SetUniqueID sets the unique identifier for the configuration. -func (c *Config) SetUniqueID(id string) { - c.uniqueID = id -} - -// SetProfile sets the profile with the given name to the given profile. -func (c *Config) SetProfile(name string, profile *Profile) { - c.profiles[name] = profile -} - -// GetUniqueID retrieves the unique identifier for the configuration. -func (c *Config) GetUniqueID() string { - return c.uniqueID -} - -// GetProfiles retrieves the map of profile names to Profile instances from the configuration. -func (c *Config) GetProfiles() map[string]*Profile { - return c.profiles -} - -// GetCurrentProfileName retrieves the name of the current profile from the configuration. -func (c *Config) GetCurrentProfileName() string { - return c.currentProfile -} - -// SetCurrentProfileName sets the name of the current profile to the given string. -func (c *Config) SetCurrentProfileName(s string) { - c.currentProfile = s -} - -// GetConfig retrieves the configuration from the file system. -// It uses the ConfigManager to load the configuration from the file system. -func GetConfig(cmd *cobra.Command) (*Config, error) { - return GetConfigManager(cmd).Load() -} - -// GetConfigManager retrieves the ConfigManager instance associated with the given cobra.Command. -// It uses the FileFlag to determine the configuration file path and returns a new ConfigManager instance. -func GetConfigManager(cmd *cobra.Command) *ConfigManager { - return NewConfigManager(GetString(cmd, FileFlag)) -} - -// GetCurrentProfileName retrieves the name of the current profile from the given cobra.Command and configuration. -// If the ProfileFlag is set, it returns the value of the ProfileFlag. -// Otherwise, it returns the current profile name from the configuration. -func GetCurrentProfileName(cmd *cobra.Command, config *Config) string { - if profile := GetString(cmd, ProfileFlag); profile != "" { - return profile - } - - currentProfileName := config.GetCurrentProfileName() - - if currentProfileName == "" { - currentProfileName = "default" - } - - return currentProfileName -} - -// GetCurrentProfile retrieves the current profile from the given cobra.Command and configuration. -// It returns the current profile from the configuration. -// If the current profile does not exist, it creates a new profile with the default membership URI and returns it. -func GetCurrentProfile(cmd *cobra.Command, cfg *Config) *Profile { - return cfg.GetProfileOrDefault(GetCurrentProfileName(cmd, cfg), defaultMembershipURI) -} diff --git a/components/mdz/pkg/controller.go b/components/mdz/pkg/controller.go deleted file mode 100644 index ba342598..00000000 --- a/components/mdz/pkg/controller.go +++ /dev/null @@ -1,30 +0,0 @@ -package pkg - -import ( - "github.com/spf13/cobra" -) - -// Renderable defines an interface for objects that can render themselves. -// It requires implementing the Render method, which takes a cobra.Command and -// a slice of strings (arguments) and returns an error. -type Renderable interface { - Render(cmd *cobra.Command, args []string) error -} - -// Controller is a generic interface that defines the structure of a controller -// capable of handling commands. It requires two methods: -// - GetStore, which returns a store of type T. -// - Run, which takes a cobra.Command and a slice of strings (arguments), -// and returns a Renderable and an error. This method is responsible for -// executing the command's logic. -type Controller[T any] interface { - GetStore() T - Run(cmd *cobra.Command, args []string) (Renderable, error) -} - -// ExportedData represents a generic structure for data that can be exported. -// It contains a single field, Data, which can hold any type of value. The field -// is tagged with `json:"data"` to specify its JSON key when serialized. -type ExportedData struct { - Data any `json:"data"` -} diff --git a/components/mdz/pkg/factory/factory.go b/components/mdz/pkg/factory/factory.go new file mode 100644 index 00000000..08ae8e1e --- /dev/null +++ b/components/mdz/pkg/factory/factory.go @@ -0,0 +1,23 @@ +package factory + +import ( + "net/http" + + "github.com/LerianStudio/midaz/components/mdz/pkg/iostreams" +) + +const CLIVersion = "Mdz CLI 1.0.0" + +type Factory struct { + CLIVersion string + HTTPClient *http.Client + IOStreams *iostreams.IOStreams +} + +func NewFactory() *Factory { + return &Factory{ + CLIVersion: CLIVersion, + HTTPClient: &http.Client{}, + IOStreams: iostreams.System(), + } +} diff --git a/components/mdz/pkg/flags.go b/components/mdz/pkg/flags.go deleted file mode 100644 index 2167cf51..00000000 --- a/components/mdz/pkg/flags.go +++ /dev/null @@ -1,106 +0,0 @@ -package pkg - -import ( - "os" - "strconv" - "strings" - "time" - - "github.com/iancoleman/strcase" - "github.com/spf13/cobra" -) - -const ( - // MembershipURIFlag specifies the URI for membership - MembershipURIFlag = "membership-uri" - // FileFlag specifies the configuration file - FileFlag = "config" - // ProfileFlag specifies the profile to use - ProfileFlag = "profile" - // OutputFlag specifies the output format - OutputFlag = "output" - // DebugFlag specifies whether to run the command in debug mode - DebugFlag = "debug" - // TelemetryFlag specifies whether to enable telemetry - TelemetryFlag = "telemetry" -) - -// GetBool retrieves the boolean value of the specified flag from the command. -func GetBool(cmd *cobra.Command, flagName string) bool { - v, err := cmd.Flags().GetBool(flagName) - if err != nil { - fromEnv := strings.ToLower(os.Getenv(strcase.ToScreamingSnake(flagName))) - return fromEnv == "true" || fromEnv == "1" - } - - return v -} - -// GetString retrieves the string value of the specified flag from the command. -func GetString(cmd *cobra.Command, flagName string) string { - v, err := cmd.Flags().GetString(flagName) - if err != nil || v == "" { - return os.Getenv(strcase.ToScreamingSnake(flagName)) - } - - return v -} - -// GetStringSlice retrieves the string slice value of the specified flag from the command. -func GetStringSlice(cmd *cobra.Command, flagName string) []string { - v, err := cmd.Flags().GetStringSlice(flagName) - if err != nil || len(v) == 0 { - envVar := os.Getenv(strcase.ToScreamingSnake(flagName)) - if envVar == "" { - return []string{} - } - - return strings.Split(envVar, " ") - } - - return v -} - -// GetInt retrieves the integer value of the specified flag from the command. -func GetInt(cmd *cobra.Command, flagName string) int { - v, err := cmd.Flags().GetInt(flagName) - if err != nil { - v := os.Getenv(strcase.ToScreamingSnake(flagName)) - if v != "" { - v, err := strconv.Atoi(v) - if err != nil { - return 0 - } - - return v - } - - return 0 - } - - return v -} - -// GetDateTime retrieves the time value of the specified flag from the command. -func GetDateTime(cmd *cobra.Command, flagName string) (*time.Time, error) { - v, err := cmd.Flags().GetString(flagName) - if err != nil || v == "" { - v = os.Getenv(strcase.ToScreamingSnake(flagName)) - } - - if v == "" { - return nil, nil - } - - t, err := time.Parse(time.RFC3339, v) - if err != nil { - return nil, err - } - - return &t, nil -} - -// Ptr returns a pointer to the given value. -func Ptr[T any](t T) *T { - return &t -} diff --git a/components/mdz/pkg/http.go b/components/mdz/pkg/http.go deleted file mode 100644 index a5fd52a6..00000000 --- a/components/mdz/pkg/http.go +++ /dev/null @@ -1,163 +0,0 @@ -package pkg - -import ( - "bytes" - "crypto/tls" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httputil" - - "github.com/TylerBrock/colorjson" - "github.com/spf13/cobra" -) - -// GetHTTPClient creates and returns a new HTTP client configured based on the provided -// cobra.Command flags and default headers. It utilizes the NewHTTPClient function, -// passing in the values of the InsecureTlsFlag and DebugFlag, along with any -// defaultHeaders specified. This allows for the creation of a customized http.Client -// instance tailored to the needs of the application, including support for insecure -// TLS connections and debugging capabilities. -func GetHTTPClient(cmd *cobra.Command, defaultHeaders map[string][]string) *http.Client { - return NewHTTPClient( - GetBool(cmd, DebugFlag), // Enables or disables debugging output. - defaultHeaders, // Sets default headers for all requests made by the client. - ) -} - -// RoundTripperFn is a function type that implements the http.RoundTripper interface. -// It allows any function with the appropriate signature to be used as an http.RoundTripper. -// This is useful for creating custom transport behaviors in an http.Client. -type RoundTripperFn func(req *http.Request) (*http.Response, error) - -// RoundTrip executes the RoundTripperFn function, effectively making RoundTripperFn -// an http.RoundTripper. This method allows RoundTripperFn to satisfy the http.RoundTripper -// interface, enabling its use as a custom transport mechanism within an http.Client. -func (fn RoundTripperFn) RoundTrip(req *http.Request) (*http.Response, error) { - return fn(req) -} - -func printBody(data []byte) { - if len(data) == 0 { - return - } - - raw := make(map[string]any) - - if err := json.Unmarshal(data, &raw); err == nil { - f := colorjson.NewFormatter() - f.Indent = 2 - - colorized, err := f.Marshal(raw) - if err != nil { - panic(err) - } - - fmt.Println(string(colorized)) - } else { - fmt.Println(string(data)) - } -} - -func debugRoundTripper(rt http.RoundTripper) RoundTripperFn { - return func(req *http.Request) (*http.Response, error) { - data, err := httputil.DumpRequest(req, false) - if err != nil { - panic(err) - } - - fmt.Println(string(data)) - - if req.Body != nil { - data, err = io.ReadAll(req.Body) - if err != nil { - panic(err) - } - - if err := req.Body.Close(); err != nil { - panic(err) - } - - req.Body = io.NopCloser(bytes.NewBuffer(data)) - - printBody(data) - } - - rsp, err := rt.RoundTrip(req) - if err != nil { - return nil, err - } - - data, err = httputil.DumpResponse(rsp, false) - if err != nil { - panic(err) - } - - fmt.Println(string(data)) - - if rsp.Body != nil { - data, err = io.ReadAll(rsp.Body) - if err != nil { - panic(err) - } - - if err := rsp.Body.Close(); err != nil { - panic(err) - } - - rsp.Body = io.NopCloser(bytes.NewBuffer(data)) - printBody(data) - } - - return rsp, nil - } -} - -func defaultHeadersRoundTripper(rt http.RoundTripper, headers map[string][]string) RoundTripperFn { - return func(req *http.Request) (*http.Response, error) { - for k, v := range headers { - for _, vv := range v { - req.Header.Add(k, vv) - } - } - - return rt.RoundTrip(req) - } -} - -// NewHTTPClient initializes and returns a new http.Client with customizable behavior. -// It allows for the configuration of TLS insecurity (skipping TLS verification), -// enabling a debug mode for additional logging, and setting default headers for all requests. -// -// Parameters: -// - insecureTLS: If true, the client will accept any TLS certificate presented by the server -// and any host name in that certificate. This is useful for testing with self-signed certificates. -// - debug: If true, wraps the transport in a debugging layer that logs all requests and responses. -// This is helpful for development and troubleshooting. -// - defaultHeaders: A map of header names to their values which will be added to every request -// made by this client. Useful for setting headers like `Authorization` or `User-Agent` that -// should be included in all requests. -// -// Returns: -// - A pointer to an initialized http.Client configured as specified. -func NewHTTPClient(debug bool, defaultHeaders map[string][]string) *http.Client { - var transport http.RoundTripper = &http.Transport{ - TLSClientConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - InsecureSkipVerify: false, - }, - } - - if debug { - transport = debugRoundTripper(transport) - } - - if len(defaultHeaders) > 0 { - transport = defaultHeadersRoundTripper(transport, defaultHeaders) - } - - return &http.Client{ - Transport: transport, - } -} diff --git a/components/mdz/pkg/iostreams/iostreams.go b/components/mdz/pkg/iostreams/iostreams.go new file mode 100644 index 00000000..393e8e61 --- /dev/null +++ b/components/mdz/pkg/iostreams/iostreams.go @@ -0,0 +1,20 @@ +package iostreams + +import ( + "io" + "os" +) + +type IOStreams struct { + In io.ReadCloser + Out io.Writer + Err io.Writer +} + +func System() *IOStreams { + return &IOStreams{ + In: os.Stdin, + Out: os.Stdout, + Err: os.Stderr, + } +} diff --git a/components/mdz/pkg/manager.go b/components/mdz/pkg/manager.go deleted file mode 100644 index 9f6b2f6a..00000000 --- a/components/mdz/pkg/manager.go +++ /dev/null @@ -1,73 +0,0 @@ -package pkg - -import ( - "encoding/json" - "os" - "path" -) - -const ( - defaultMembershipURI = "https://app.midaz.cloud/api" -) - -// ConfigManager is a struct that use a string configFilePath -type ConfigManager struct { - configFilePath string -} - -// Load is a func that load a filepath and return a *Config of application -func (m *ConfigManager) Load() (*Config, error) { - f, err := os.Open(m.configFilePath) - if err != nil { - if os.IsNotExist(err) { - return &Config{ - profiles: map[string]*Profile{}, - manager: m, - }, nil - } - - return nil, err - } - defer f.Close() - - cfg := &Config{} - if err := json.NewDecoder(f).Decode(cfg); err != nil { - return nil, err - } - - cfg.manager = m - if cfg.profiles == nil { - cfg.profiles = map[string]*Profile{} - } - - return cfg, nil -} - -// UpdateConfig is a func that update a *Config of application -func (m *ConfigManager) UpdateConfig(config *Config) error { - if err := os.MkdirAll(path.Dir(m.configFilePath), 0o700); err != nil { - return err - } - - f, err := os.OpenFile(m.configFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600) - if err != nil { - return err - } - defer f.Close() - - enc := json.NewEncoder(f) - enc.SetIndent("", " ") - - if err := enc.Encode(config); err != nil { - return err - } - - return nil -} - -// NewConfigManager is a func that return a struc of *ConfigManager -func NewConfigManager(configFilePath string) *ConfigManager { - return &ConfigManager{ - configFilePath: configFilePath, - } -} diff --git a/components/mdz/pkg/output/output.go b/components/mdz/pkg/output/output.go new file mode 100644 index 00000000..64e156a7 --- /dev/null +++ b/components/mdz/pkg/output/output.go @@ -0,0 +1,41 @@ +package output + +import ( + "fmt" + "io" +) + +type Output interface { + Output() error +} + +func Print(out Output) error { + return out.Output() +} + +type GeneralOutput struct { + Msg string + Out io.Writer +} + +func (o *GeneralOutput) Output() error { + if _, err := fmt.Fprintf(o.Out, "%s\n", o.Msg); err != nil { + return err + } + return nil +} + +type ErrorOutput struct { + GeneralOutput GeneralOutput + Err error +} + +func (o *ErrorOutput) Output() error { + if o.Err != nil { + _, err := fmt.Fprintf(o.GeneralOutput.Out, "Error: %s\n", o.Err.Error()) + if err != nil { + return err + } + } + return nil +} diff --git a/components/mdz/pkg/profile.go b/components/mdz/pkg/profile.go deleted file mode 100644 index b5136f97..00000000 --- a/components/mdz/pkg/profile.go +++ /dev/null @@ -1,261 +0,0 @@ -package pkg - -import ( - "context" - "encoding/json" - "net/http" - "sort" - "strings" - "time" - - "github.com/golang-jwt/jwt" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/zitadel/oidc/v3/pkg/client/rp" - "github.com/zitadel/oidc/v3/pkg/oidc" - "golang.org/x/oauth2" -) - -// ErrInvalidAuthentication is an error that occurs when the authentication token is invalid. -type ErrInvalidAuthentication struct { - err error -} - -// Error returns the error message for ErrInvalidAuthentication. -// -// No parameters. -// Returns a string. -func (e ErrInvalidAuthentication) Error() string { - return e.err.Error() -} - -// Unwrap returns the underlying error of ErrInvalidAuthentication. -// -// No parameters. -// Returns an error. -func (e ErrInvalidAuthentication) Unwrap() error { - return e.err -} - -// Is checks if the provided error is of type ErrInvalidAuthentication. -func (e ErrInvalidAuthentication) Is(err error) bool { - _, ok := err.(*ErrInvalidAuthentication) - return ok -} - -// IsInvalidAuthentication checks if the provided error is an instance of ErrInvalidAuthentication. -func IsInvalidAuthentication(err error) bool { - return errors.Is(err, &ErrInvalidAuthentication{}) -} - -func newErrInvalidAuthentication(err error) *ErrInvalidAuthentication { - return &ErrInvalidAuthentication{ - err: err, - } -} - -// AuthClient is the name of the OIDC client. -const AuthClient = "mdz" - -type persistedProfile struct { - MembershipURI string `json:"membershipURI"` - Token *oidc.AccessTokenResponse `json:"token"` - DefaultOrganization string `json:"defaultOrganization"` -} - -// Profile represents a user profile. -type Profile struct { - membershipURI string - token *oidc.AccessTokenResponse - defaultOrganization string - config *Config -} - -// UpdateToken updates the token for the Profile. -// -// token *oidc.AccessTokenResponse - The new access token to be set. -func (p *Profile) UpdateToken(token *oidc.AccessTokenResponse) { - p.token = token -} - -// SetMembershipURI sets the membership URI for the Profile. -// -// Takes a string parameter. -func (p *Profile) SetMembershipURI(v string) { - p.membershipURI = v -} - -// MarshalJSON generates the JSON encoding for the Profile struct. -// -// No parameters. -// Returns a byte slice and an error. -func (p *Profile) MarshalJSON() ([]byte, error) { - return json.Marshal(persistedProfile{ - MembershipURI: p.membershipURI, - Token: p.token, - DefaultOrganization: p.defaultOrganization, - }) -} - -// UnmarshalJSON parses the JSON-encoded data and stores the result in the Profile struct. -// -// It takes a byte slice data as a parameter. -// Returns an error. -func (p *Profile) UnmarshalJSON(data []byte) error { - cfg := &persistedProfile{} - if err := json.Unmarshal(data, cfg); err != nil { - return err - } - - *p = Profile{ - membershipURI: cfg.MembershipURI, - token: cfg.Token, - defaultOrganization: cfg.DefaultOrganization, - } - - return nil -} - -// GetMembershipURI returns the membership URI of the Profile. -// -// No parameters. -// Returns a string. -func (p *Profile) GetMembershipURI() string { - return p.membershipURI -} - -// GetDefaultOrganization returns the default organization for the Profile. -// -// No parameters. -// Returns a string. -func (p *Profile) GetDefaultOrganization() string { - return p.defaultOrganization -} - -// GetToken retrieves and refreshes the OAuth2 token if needed. -// -// Parameters: -// - ctx: the context for the HTTP request -// - httpClient: the HTTP client to use for making HTTP requests -// -// Returns: -// - *oauth2.Token: the OAuth2 token retrieved or refreshed -// - error: an error if any occurred during the token retrieval or refresh -func (p *Profile) GetToken(ctx context.Context, httpClient *http.Client) (*oauth2.Token, error) { - if p.token == nil { - return nil, errors.New("not authenticated") - } - - if p.token != nil { - claims := &oidc.AccessTokenClaims{} - - if _, err := oidc.ParseToken(p.token.AccessToken, claims); err != nil { - return nil, newErrInvalidAuthentication(errors.Wrap(err, "parsing token")) - } - - if claims.Expiration.AsTime().Before(time.Now()) { - relyingParty, err := GetAuthRelyingParty(ctx, httpClient, p.membershipURI) - if err != nil { - return nil, err - } - - newToken, err := rp.RefreshTokens[*oidc.IDTokenClaims](ctx, relyingParty, p.token.RefreshToken, "", "") - if err != nil { - return nil, newErrInvalidAuthentication(errors.Wrap(err, "refreshing token")) - } - - p.UpdateToken(&oidc.AccessTokenResponse{ - AccessToken: newToken.AccessToken, - TokenType: newToken.TokenType, - RefreshToken: newToken.RefreshToken, - IDToken: newToken.Extra("id_token").(string), - }) - - if err := p.config.Persist(); err != nil { - return nil, err - } - } - } - - claims := &oidc.AccessTokenClaims{} - if _, err := oidc.ParseToken(p.token.AccessToken, claims); err != nil { - return nil, newErrInvalidAuthentication(err) - } - - return &oauth2.Token{ - AccessToken: p.token.AccessToken, - TokenType: p.token.TokenType, - RefreshToken: p.token.RefreshToken, - Expiry: claims.Expiration.AsTime(), - }, nil -} - -// GetClaims returns the jwt claims and an error. -// -// No parameters. -// Returns jwt.MapClaims and error. -func (p *Profile) GetClaims() (jwt.MapClaims, error) { - claims := jwt.MapClaims{} - parser := jwt.Parser{} - - if _, _, err := parser.ParseUnverified(p.token.AccessToken, claims); err != nil { - return nil, err - } - - return claims, nil -} - -func (p *Profile) getUserInfo() (*userClaims, error) { - claims := &userClaims{} - if p.token != nil && p.token.IDToken != "" { - _, err := oidc.ParseToken(p.token.IDToken, claims) - if err != nil { - return nil, err - } - } - - return claims, nil -} - -// SetDefaultOrganization sets the default organization -func (p *Profile) SetDefaultOrganization(o string) { - p.defaultOrganization = o -} - -// IsConnected is connected -func (p *Profile) IsConnected() bool { - return p.token != nil -} - -// CurrentProfile profile -type CurrentProfile Profile - -// ListProfiles generates a list of profiles based on the toComplete string. -// -// Parameters: -// -// cmd: *cobra.Command - the command object -// toComplete: string - the string to complete -// -// Return type: -// -// []string: list of profile strings -// error: any error that occurred -func ListProfiles(cmd *cobra.Command, toComplete string) ([]string, error) { - config, err := GetConfig(cmd) - if err != nil { - return []string{}, err - } - - ret := make([]string, 0) - - for p := range config.GetProfiles() { - if strings.HasPrefix(p, toComplete) { - ret = append(ret, p) - } - } - - sort.Strings(ret) - - return ret, nil -} diff --git a/components/mdz/pkg/relyingparty.go b/components/mdz/pkg/relyingparty.go deleted file mode 100644 index a75afe34..00000000 --- a/components/mdz/pkg/relyingparty.go +++ /dev/null @@ -1,14 +0,0 @@ -package pkg - -import ( - "context" - "net/http" - - "github.com/zitadel/oidc/v3/pkg/client/rp" -) - -// GetAuthRelyingParty returns a NewRelyingPartyOIDC that creates an (OIDC) -func GetAuthRelyingParty(ctx context.Context, httpClient *http.Client, membershipURI string) (rp.RelyingParty, error) { - return rp.NewRelyingPartyOIDC(ctx, membershipURI, AuthClient, "", - "", []string{"openid", "email", "offline_access", "supertoken", "accesses"}, rp.WithHTTPClient(httpClient)) -} diff --git a/components/mdz/pkg/utils.go b/components/mdz/pkg/utils.go deleted file mode 100644 index 184fdf7a..00000000 --- a/components/mdz/pkg/utils.go +++ /dev/null @@ -1,54 +0,0 @@ -package pkg - -import ( - "errors" -) - -// Map func that appends slices -func Map[SRC, DST any](srcs []SRC, mapper func(SRC) DST) []DST { - ret := make([]DST, 0) - for _, src := range srcs { - ret = append(ret, mapper(src)) - } - - return ret -} - -// MapMap func that compare and appends slices -func MapMap[KEY comparable, VALUE, DST any](srcs map[KEY]VALUE, mapper func(KEY, VALUE) DST) []DST { - ret := make([]DST, 0) - for k, v := range srcs { - ret = append(ret, mapper(k, v)) - } - - return ret -} - -// MapKeys func that compare and appends slices -func MapKeys[K comparable, V any](m map[K]V) []K { - ret := make([]K, 0) - for k := range m { - ret = append(ret, k) - } - - return ret -} - -// Prepend func that return two append items -func Prepend[V any](array []V, items ...V) []V { - return append(items, array...) -} - -// ContainValue func that valid if contains value -func ContainValue[V comparable](array []V, value V) bool { - for _, v := range array { - if v == value { - return true - } - } - - return false -} - -// ErrOpenningBrowser is a struct that return an error when opening browser -var ErrOpenningBrowser = errors.New("opening browser") From 6ea0f05eae6adfd181af250037defb6c4e4311cc Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Wed, 16 Oct 2024 17:18:57 -0300 Subject: [PATCH 08/62] style: fix linting issues across multiple files :gem: --- .golangci.yml | 12 +- Makefile | 2 +- components/mdz/.golangci.yml | 144 ++++++++++++++++++- components/mdz/Makefile | 16 ++- components/mdz/cmd/login/login.go | 162 ---------------------- components/mdz/cmd/root.go | 54 -------- components/mdz/cmd/ui/ui.go | 95 ------------- components/mdz/cmd/version/version.go | 68 --------- components/mdz/main.go | 1 + components/mdz/pkg/cmd/root/help.go | 113 ++++++++------- components/mdz/pkg/cmd/root/root.go | 1 + components/mdz/pkg/cmd/version/version.go | 4 +- components/mdz/pkg/output/output.go | 2 + go.mod | 2 + go.sum | 2 + 15 files changed, 229 insertions(+), 449 deletions(-) delete mode 100644 components/mdz/cmd/login/login.go delete mode 100644 components/mdz/cmd/root.go delete mode 100644 components/mdz/cmd/ui/ui.go delete mode 100644 components/mdz/cmd/version/version.go diff --git a/.golangci.yml b/.golangci.yml index 3295d0c0..0066f070 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,18 +8,10 @@ linters: - dupword # Detects duplicate words. - durationcheck - errchkjson - - exportloopref # Detects pointers to enclosing loop variables. - - gocritic # Metalinter; detects bugs, performance, and styling issues. + - copyloopvar - gocyclo - - gofumpt # Detects whether code was gofumpt-ed. - - goimports - - gosec # Detects security problems. - - gosimple - loggercheck - - govet - # - golint - ineffassign - - megacheck - wsl - misspell # Detects commonly misspelled English words in comments. - nakedret @@ -34,12 +26,10 @@ linters: - tenv # Detects using os.Setenv instead of t.Setenv. - thelper # Detects test helpers without t.Helper(). - tparallel # Detects inappropriate usage of t.Parallel(). - - typecheck - unconvert # Detects unnecessary type conversions. - unparam - unused - usestdlibvars - - vet - wastedassign - errcheck diff --git a/Makefile b/Makefile index f2544d0d..52def8a0 100644 --- a/Makefile +++ b/Makefile @@ -72,4 +72,4 @@ transaction: all-services: $(MAKE) -C $(AUTH_DIR) $(COMMAND) && \ $(MAKE) -C $(LEDGER_DIR) $(COMMAND) && \ - $(MAKE) -C $(TRANSACTION_DIR) $(COMMAND) \ No newline at end of file + $(MAKE) -C $(TRANSACTION_DIR) $(COMMAND) diff --git a/components/mdz/.golangci.yml b/components/mdz/.golangci.yml index c098be3d..0066f070 100644 --- a/components/mdz/.golangci.yml +++ b/components/mdz/.golangci.yml @@ -1,13 +1,145 @@ linters: enable: - - revive - - errcheck + - bodyclose + - gocognit + - goconst + - depguard + - dogsled + - dupword # Detects duplicate words. + - durationcheck + - errchkjson + - copyloopvar + - gocyclo + - loggercheck + - ineffassign + - wsl + - misspell # Detects commonly misspelled English words in comments. + - nakedret + - nilerr # Detects code that returns nil even if it checks that the error is not nil. + - nolintlint # Detects ill-formed or insufficient nolint directives. + - perfsprint # Detects fmt.Sprintf uses that can be replaced with a faster alternative. + - prealloc # Detects slice declarations that could potentially be pre-allocated. + - predeclared # Detects code that shadows one of Go's predeclared identifiers + - reassign + - revive # Metalinter; drop-in replacement for golint. + - stylecheck # Replacement for golint + - tenv # Detects using os.Setenv instead of t.Setenv. + - thelper # Detects test helpers without t.Helper(). + - tparallel # Detects inappropriate usage of t.Parallel(). + - unconvert # Detects unnecessary type conversions. + - unparam - unused - - staticcheck - - gocritic + - usestdlibvars + - wastedassign + - errcheck +run: + timeout: 5m + tests: false + +linters-settings: + depguard: + rules: + main: + deny: + - pkg: io/ioutil + desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil + gocyclo: + min-complexity: 16 + govet: + enable: + - shadow + settings: + shadow: + strict: true + revive: + rules: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-shadowing + - name: import-shadowing + severity: warning + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block + - name: empty-block + severity: warning + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-lines + - name: empty-lines + severity: warning + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#use-any + - name: use-any + severity: warning + disabled: false issues: + # The default exclusion rules are a bit too permissive, so copying the relevant ones below + exclude-use-default: false + exclude: + - parameter .* always receives exclude-rules: + # We prefer to use an "exclude-list" so that new "default" exclusions are not + # automatically inherited. We can decide whether or not to follow upstream + # defaults when updating golang-ci-lint versions. + # Unfortunately, this means we have to copy the whole exclusion pattern, as + # (unlike the "include" option), the "exclude" option does not take exclusion + # ID's. + # + # These exclusion patterns are copied from the default excluses at: + # https://github.com/golangci/golangci-lint/blob/v1.44.0/pkg/config/issues.go#L10-L104 + # EXC0001 + - text: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked" + linters: + - errcheck + # EXC0003 + - text: "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this" + linters: + - revive + # EXC0006 + - text: "Use of unsafe calls should be audited" + linters: + - gosec + # EXC0007 + - text: "Subprocess launch(ed with variable|ing should be audited)" + linters: + - gosec + # EXC0008 + - text: "G307" + linters: + - gosec + # EXC0009 + - text: "(Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)" + linters: + - gosec + # EXC0010 + - text: "Potential file inclusion via variable" + linters: + - gosec + - text: "G113" + linters: + - gosec + - text: "G104" + linters: + - gosec + - text: "G204: Subprocess launched with a potential tainted input or cmd arguments" + linters: + - gosec + - text: "G306: Expect WriteFile permissions to be 0600 or less" + linters: + - gosec + - text: "package-comments: should have a package comment" + linters: + - revive - path: _test\.go - text: "test files" - + linters: + - errcheck + - gosec + - text: "ST1000: at least one file in a package should have a package comment" + linters: + - stylecheck + # Allow "err" and "ok" vars to shadow existing declarations, otherwise we get too many false positives. + - text: '^shadow: declaration of "(err|ok)" shadows declaration' + linters: + - govet + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-issues-per-linter: 0 + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same-issues: 0 diff --git a/components/mdz/Makefile b/components/mdz/Makefile index 379cd3d0..e64d6d84 100644 --- a/components/mdz/Makefile +++ b/components/mdz/Makefile @@ -11,7 +11,7 @@ get-lint-deps: .PHONY: lint lint: get-lint-deps - golangci-lint run ./... --verbose + golangci-lint run --fix ./... --verbose .PHONY: get-govulncheck-deps get-govulncheck-deps: @@ -21,13 +21,21 @@ get-govulncheck-deps: govulncheck: get-govulncheck-deps govulncheck ./... +.PHONY: get-gosec-deps +get-gosec-deps: + go install github.com/securego/gosec/v2/cmd/gosec@latest + .PHONY: gosec gosec: get-gosec-deps gosec ./... -.PHONY: get-gosec-deps -get-gosec-deps: - go install github.com/securego/gosec/v2/cmd/gosec@latest +.PHONY: get-perfsprint-deps +get-perfsprint-deps: + go get github.com/catenacyber/perfsprint@latest + +.PHONY : perfsprint +perfsprint: get-perfsprint-deps + perfsprint ./... .PHONY : build build: diff --git a/components/mdz/cmd/login/login.go b/components/mdz/cmd/login/login.go deleted file mode 100644 index af6d9a6c..00000000 --- a/components/mdz/cmd/login/login.go +++ /dev/null @@ -1,162 +0,0 @@ -package login - -import ( - "context" - "errors" - "fmt" - "net/url" - "time" - - "github.com/LerianStudio/midaz/components/mdz/pkg" - "github.com/pkg/browser" - "github.com/pterm/pterm" - - "github.com/spf13/cobra" - "github.com/zitadel/oidc/v3/pkg/client/rp" - "github.com/zitadel/oidc/v3/pkg/oidc" -) - -// LogIn func that can log in on midaz -func LogIn(ctx context.Context, dialog Dialog, relyingParty rp.RelyingParty) (*oidc.AccessTokenResponse, error) { - deviceCode, err := rp.DeviceAuthorization(ctx, relyingParty.OAuthConfig().Scopes, relyingParty, nil) - if err != nil { - return nil, err - } - - uri, err := url.Parse(deviceCode.VerificationURI) - if err != nil { - panic(err) - } - - query := uri.Query() - query.Set("user_code", deviceCode.UserCode) - uri.RawQuery = query.Encode() - - if err := browser.OpenURL(uri.String()); err != nil { - if !errors.Is(err, pkg.ErrOpenningBrowser) { - return nil, err - } - - fmt.Println("No browser detected") - } - - dialog.DisplayURIAndCode(deviceCode.VerificationURI, deviceCode.UserCode) - - return rp.DeviceAccessToken(ctx, deviceCode.DeviceCode, time.Duration(deviceCode.Interval)*time.Second, relyingParty) -} - -// Dialog provides an interface for DisplayURIAndCode -type Dialog interface { - DisplayURIAndCode(uri, code string) -} - -// DialogFn is a func that implements uri and code -type DialogFn func(uri, code string) - -// DisplayURIAndCode is a func that return a type DialogFn -func (fn DialogFn) DisplayURIAndCode(uri, code string) { - fn(uri, code) -} - -// Store is a struct designed to encapsulate payload data. -type Store struct { - Profile *pkg.Profile `json:"-"` - DeviceCode string `json:"deviceCode"` - LoginURI string `json:"loginUri"` - BrowserURL string `json:"browserUrl"` - Success bool `json:"success"` -} - -// Controller is a struct to encapsulate a *Store struct. -type Controller struct { - store *Store -} - -// NewDefaultLoginStore is a func that return a struct *Store -func NewDefaultLoginStore() *Store { - return &Store{ - Profile: nil, - DeviceCode: "", - LoginURI: "", - BrowserURL: "", - Success: false, - } -} - -// GetStore is a func that return a struct *Store -func (c *Controller) GetStore() *Store { - return c.store -} - -// NewLoginController is a func that return a struct *Controller -func NewLoginController() *Controller { - return &Controller{ - store: NewDefaultLoginStore(), - } -} - -// Run is a fun that executes Open func and return a Renderable interface -func (c *Controller) Run(cmd *cobra.Command, args []string) (pkg.Renderable, error) { - cfg, err := pkg.GetConfig(cmd) - if err != nil { - return nil, err - } - - profile := pkg.GetCurrentProfile(cmd, cfg) - - membershipURI, err := cmd.Flags().GetString(pkg.MembershipURIFlag) - if err != nil { - return nil, err - } - - if membershipURI == "" { - membershipURI = profile.GetMembershipURI() - } - - relyingParty, err := pkg.GetAuthRelyingParty(cmd.Context(), pkg.GetHTTPClient(cmd, map[string][]string{}), membershipURI) - if err != nil { - return nil, err - } - - c.store.Profile = profile - - ret, err := LogIn(cmd.Context(), DialogFn(func(uri, code string) { - c.store.DeviceCode = code - c.store.LoginURI = uri - fmt.Println("Link :", fmt.Sprintf("%s?user_code=%s", c.store.LoginURI, c.store.DeviceCode)) - }), relyingParty) - if err != nil { - return nil, err - } - - if ret != nil { - c.store.Success = true - - profile.UpdateToken(ret) - } - - profile.SetMembershipURI(membershipURI) - - currentProfileName := pkg.GetCurrentProfileName(cmd, cfg) - - cfg.SetCurrentProfile(currentProfileName, profile) - - return c, cfg.Persist() -} - -// Render is a func that show if you are logged -func (c *Controller) Render(cmd *cobra.Command, args []string) error { - pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Logged!") - return nil -} - -// NewCommand is a func that execute some commands -func NewCommand() *cobra.Command { - return pkg.NewCommand("login", - pkg.WithStringFlag(pkg.MembershipURIFlag, "", "service url"), - pkg.WithHiddenFlag(pkg.MembershipURIFlag), - pkg.WithShortDescription("Login"), - pkg.WithArgs(cobra.ExactArgs(0)), - pkg.WithController[*Store](NewLoginController()), - ) -} diff --git a/components/mdz/cmd/root.go b/components/mdz/cmd/root.go deleted file mode 100644 index 54949d85..00000000 --- a/components/mdz/cmd/root.go +++ /dev/null @@ -1,54 +0,0 @@ -package cmd - -import ( - "context" - "fmt" - "os" - "os/signal" - - "github.com/LerianStudio/midaz/components/mdz/cmd/login" - "github.com/LerianStudio/midaz/components/mdz/cmd/ui" - "github.com/LerianStudio/midaz/components/mdz/cmd/version" - - "github.com/spf13/cobra" -) - -// NewRootCommand is a func that use cmd commands -func NewRootCommand() *cobra.Command { - var cfgFile string - - var debug bool - - cmd := &cobra.Command{ - Use: "mdz", - Short: "mdz is the CLI interface to use Midaz services", - } - - // Global flags - cmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.mdz.yaml)") - cmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "enable debug mode") - - // Subcommands - - // cmd.AddCommand(auth.NewCommand()) // TODO - // cmd.AddCommand(ledger.NewCommand()) // TODO - cmd.AddCommand(login.NewCommand()) - cmd.AddCommand(ui.NewCommand()) - cmd.AddCommand(version.NewCommand()) - - return cmd -} - -// Execute is a func that open nem root command -func Execute() { - cobra.EnableCommandSorting = false - ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) - - if err := NewRootCommand().ExecuteContext(ctx); err != nil { - fmt.Println(err) - - os.Exit(1) - } - - defer cancel() -} diff --git a/components/mdz/cmd/ui/ui.go b/components/mdz/cmd/ui/ui.go deleted file mode 100644 index 25950351..00000000 --- a/components/mdz/cmd/ui/ui.go +++ /dev/null @@ -1,95 +0,0 @@ -package ui - -import ( - "fmt" - "os/exec" - "runtime" - - "github.com/LerianStudio/midaz/components/mdz/pkg" - "github.com/spf13/cobra" -) - -// Payload is a struct designed to encapsulate payload data. -type Payload struct { - StackURL string `json:"stackUrl"` - Found bool `json:"browserFound"` -} - -// Controller is a struct designed to encapsulate payload data. -type Controller struct { - store *Payload -} - -var _ pkg.Controller[*Payload] = (*Controller)(nil) - -// NewDefaultUIStore is a func that returns a *UiStruct struct -func NewDefaultUIStore() *Payload { - return &Payload{ - StackURL: "https://console.midaz.cloud", - Found: false, - } -} - -// NewUIController is a func that returns a *Controller struct -func NewUIController() *Controller { - return &Controller{ - store: NewDefaultUIStore(), - } -} - -func openURL(url string) error { - var ( - cmd string - args []string - ) - - switch runtime.GOOS { - case "windows": - cmd = "cmd" - args = []string{"/c", "start"} - case "darwin": - cmd = "open" - default: // "linux", "freebsd", "openbsd", "netbsd" - cmd = "xdg-open" - } - - args = append(args, url) - - return startCommand(cmd, args...) -} - -func startCommand(cmd string, args ...string) error { - c := exec.Command(cmd, args...) - - return c.Start() -} - -// GetStore is a func that returns a *Payload struct -func (c *Controller) GetStore() *Payload { - return c.store -} - -// Run is a fun that executes Open func and return an interface -func (c *Controller) Run(cmd *cobra.Command, args []string) (pkg.Renderable, error) { - if err := openURL(c.store.StackURL); err != nil { - c.store.Found = true - } - - return c, nil -} - -// Render is a func that open Url -func (c *Controller) Render(cmd *cobra.Command, args []string) error { - fmt.Println("Opening url: ", c.store.StackURL) - - return nil -} - -// NewCommand is a func that execute some commands -func NewCommand() *cobra.Command { - return pkg.NewStackCommand("ui", - pkg.WithShortDescription("Open UI"), - pkg.WithArgs(cobra.ExactArgs(0)), - pkg.WithController[*Payload](NewUIController()), - ) -} diff --git a/components/mdz/cmd/version/version.go b/components/mdz/cmd/version/version.go deleted file mode 100644 index bdd113dc..00000000 --- a/components/mdz/cmd/version/version.go +++ /dev/null @@ -1,68 +0,0 @@ -package version - -import ( - "github.com/LerianStudio/midaz/components/mdz/pkg" - "github.com/pterm/pterm" - "github.com/spf13/cobra" -) - -// Version variable to set mdz version -var Version = "mdz version mdz1.0.0" - -// Store is a struct designed to encapsulate payload data. -type Store struct { - Version string `json:"version"` - BuildDate string `json:"buildDate"` - Commit string `json:"commit"` -} - -// Controller is a struct that return *VersionStore struct -type Controller struct { - store *Store -} - -var _ pkg.Controller[*Store] = (*Controller)(nil) - -// NewDefaultVersionStore return a *VersionStore struct with the version -func NewDefaultVersionStore() *Store { - return &Store{ - Version: Version, - } -} - -// NewVersionController return a *Controller struct with a new version store -func NewVersionController() *Controller { - return &Controller{ - store: NewDefaultVersionStore(), - } -} - -// NewCommand is a func that execute some commands and return a *cobra.Command struct -func NewCommand() *cobra.Command { - return pkg.NewCommand("version", - pkg.WithShortDescription("Get version"), - pkg.WithArgs(cobra.ExactArgs(0)), - pkg.WithController(NewVersionController()), - ) -} - -// GetStore is a func that return a *VersionStore struct -func (c *Controller) GetStore() *Store { - return c.store -} - -// Run is a func that return a Renderable interface -func (c *Controller) Run(cmd *cobra.Command, args []string) (pkg.Renderable, error) { - return c, nil -} - -// Render is a func that receive a struct *cobra.Command -func (c *Controller) Render(cmd *cobra.Command, args []string) error { - tableData := pterm.TableData{} - tableData = append(tableData, []string{pterm.LightCyan("Version"), c.store.Version}) - - return pterm.DefaultTable. - WithWriter(cmd.OutOrStdout()). - WithData(tableData). - Render() -} diff --git a/components/mdz/main.go b/components/mdz/main.go index abb3f713..d7ea1c0e 100644 --- a/components/mdz/main.go +++ b/components/mdz/main.go @@ -12,6 +12,7 @@ import ( func main() { f := factory.NewFactory() cmd := root.NewCmdRoot(f) + if err := cmd.Execute(); err != nil { printErr := output.Print(&output.ErrorOutput{ GeneralOutput: output.GeneralOutput{ diff --git a/components/mdz/pkg/cmd/root/help.go b/components/mdz/pkg/cmd/root/help.go index 98abcb02..a352d473 100644 --- a/components/mdz/pkg/cmd/root/help.go +++ b/components/mdz/pkg/cmd/root/help.go @@ -10,98 +10,105 @@ import ( "github.com/spf13/cobra" ) +type helpEntry struct { + Title string + Body string +} + // help displays help for the current command, including description, synopsis, // available commands, subcommands, examples and flag options. func (f *factoryRoot) help(command *cobra.Command, args []string) { - if isRootCmd(command.Parent()) && len(args) >= 2 && args[1] != - "--help" && args[1] != "-h" { + if isRootCmd(command.Parent()) && len(args) >= 2 && args[1] != "--help" && args[1] != "-h" { nestedSuggestFunc(command, args[1]) return } + baseCommands, subcmdCommands := f.collectCommands(command) + examples := f.collectExamples(command) + helpEntries := f.buildHelpEntries(command, baseCommands, subcmdCommands, examples) + + f.outputHelp(helpEntries, command) +} + +// collectCommands collects base commands and subcommands +func (f *factoryRoot) collectCommands(command *cobra.Command) ([]string, []string) { var ( baseCommands []string subcmdCommands []string - examples []string ) - // If the command is not a root command, add it to the list of subcommands. - // Otherwise, add it to the list of base commands. for _, c := range command.Commands() { - if c.Short == "" { - continue - } - - if c.Hidden { + if c.Short == "" || c.Hidden { continue } s := rpad(c.Name(), c.NamePadding()) + c.Short - switch { - case c.Annotations["Category"] == "skip": + if c.Annotations["Category"] == "skip" { continue - case !isRootCmd(c.Parent()): - // Help of subcommand + } + + if !isRootCmd(c.Parent()) { subcmdCommands = append(subcmdCommands, s) - continue - default: + } else { baseCommands = append(baseCommands, s) - continue } } - type helpEntry struct { - Title string - Body string - } + return baseCommands, subcmdCommands +} + +// collectExamples collects help examples +func (f *factoryRoot) collectExamples(command *cobra.Command) []string { + var examples []string if len(command.Example) > 0 { examples = append(examples, command.Example) } + return examples +} + +// buildHelpEntries builds the help entries +func (f *factoryRoot) buildHelpEntries(command *cobra.Command, baseCommands, subcmdCommands, examples []string) []helpEntry { + var helpEntries []helpEntry + longText := command.Long if longText == "" { longText = command.Short } - styleTitle := color.Bold - styleBody := color.FgHiWhite - - helpEntries := []helpEntry{} - helpEntries = append(helpEntries, helpEntry{"", color.New(color.Bold).Sprint(f.factory.CLIVersion)}) - if longText != "" { helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("DESCRIPTION"), - Body: color.New(styleBody).Sprint(longText), + Title: color.New(color.Bold).Sprint("DESCRIPTION"), + Body: color.New(color.FgHiWhite).Sprint(longText), }) } helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("SYNOPSIS"), - Body: color.New(styleBody).Sprint(command.UseLine()), + Title: color.New(color.Bold).Sprint("SYNOPSIS"), + Body: color.New(color.FgHiWhite).Sprint(command.UseLine()), }) if len(examples) > 0 { helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("EXAMPLES"), + Title: color.New(color.Bold).Sprint("EXAMPLES"), Body: color.New(color.FgYellow).Sprint(strings.Join(examples, "\n")), }) } if len(baseCommands) > 0 { helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("AVAILABLE COMMANDS"), - Body: color.New(styleBody).Sprint(strings.Join(baseCommands, "\n")), + Title: color.New(color.Bold).Sprint("AVAILABLE COMMANDS"), + Body: color.New(color.FgHiWhite).Sprint(strings.Join(baseCommands, "\n")), }) } if len(subcmdCommands) > 0 { helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("AVAILABLE SUBCOMMANDS"), - Body: color.New(styleBody).Sprint(strings.Join(subcmdCommands, "\n")), + Title: color.New(color.Bold).Sprint("AVAILABLE SUBCOMMANDS"), + Body: color.New(color.FgHiWhite).Sprint(strings.Join(subcmdCommands, "\n")), }) } @@ -109,13 +116,13 @@ func (f *factoryRoot) help(command *cobra.Command, args []string) { if flagUsages != "" { if isRootCmd(command) { helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("GLOBAL OPTIONS"), - Body: color.New(styleBody).Sprint(dedent(flagUsages)), + Title: color.New(color.Bold).Sprint("GLOBAL OPTIONS"), + Body: color.New(color.FgHiWhite).Sprint(dedent(flagUsages)), }) } else { helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("LOCAL OPTIONS"), - Body: color.New(styleBody).Sprint(dedent(flagUsages)), + Title: color.New(color.Bold).Sprint("LOCAL OPTIONS"), + Body: color.New(color.FgHiWhite).Sprint(dedent(flagUsages)), }) } } @@ -123,26 +130,32 @@ func (f *factoryRoot) help(command *cobra.Command, args []string) { inheritedFlagUsages := command.InheritedFlags().FlagUsages() if inheritedFlagUsages != "" { helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("GLOBAL OPTIONS"), - Body: color.New(styleBody).Sprint(dedent(inheritedFlagUsages)), + Title: color.New(color.Bold).Sprint("GLOBAL OPTIONS"), + Body: color.New(color.FgHiWhite).Sprint(dedent(inheritedFlagUsages)), }) } helpEntries = append(helpEntries, helpEntry{ - Title: color.New(styleTitle).Sprint("LEARN MORE"), - Body: color.New(styleBody).Sprint("Use 'mdz --help' for more information about a command"), + Title: color.New(color.Bold).Sprint("LEARN MORE"), + Body: color.New(color.FgHiWhite).Sprint("Use 'mdz --help' for more information about a command"), }) + return helpEntries +} + +// outputHelp shows help entries +func (f *factoryRoot) outputHelp(helpEntries []helpEntry, command *cobra.Command) { out := command.OutOrStdout() + + // Loop over the help entries and print them for _, e := range helpEntries { if e.Title != "" { - // If there is a title, add indentation to each line in the body fmt.Fprintln(out, e.Title) fmt.Fprintln(out, Indent(strings.Trim(e.Body, "\r\n"), " ")) } else { - // If there is no title print the body as is fmt.Fprintln(out, e.Body) } + fmt.Fprintln(out) } } @@ -152,6 +165,7 @@ func (f *factoryRoot) help(command *cobra.Command, args []string) { // based on the minimum distance between the supplied command and the available commands. func nestedSuggestFunc(command *cobra.Command, arg string) { command.Printf("unknown command %q for %q\n", arg, command.CommandPath()) + var candidates []string if arg == "help" { @@ -160,11 +174,13 @@ func nestedSuggestFunc(command *cobra.Command, arg string) { if command.SuggestionsMinimumDistance <= 0 { command.SuggestionsMinimumDistance = 2 } + candidates = command.SuggestionsFor(arg) } if len(candidates) > 0 { command.Print("\nDid you mean this?\n") + for _, c := range candidates { command.Printf("\t%s\n", c) } @@ -209,14 +225,17 @@ func dedent(s string) string { for _, l := range lines { fmt.Fprintln(&buf, strings.TrimPrefix(l, strings.Repeat(" ", minIndent))) } + return strings.TrimSuffix(buf.String(), "\n") } // Indent Adds an indentation level to all lines of a string func Indent(s, indent string) string { - var lineRE = regexp.MustCompile(`(?m)^`) + lineRE := regexp.MustCompile(`(?m)^`) + if len(strings.TrimSpace(s)) == 0 { return s } + return lineRE.ReplaceAllLiteralString(s, indent) } diff --git a/components/mdz/pkg/cmd/root/root.go b/components/mdz/pkg/cmd/root/root.go index aa48fad0..7141edce 100644 --- a/components/mdz/pkg/cmd/root/root.go +++ b/components/mdz/pkg/cmd/root/root.go @@ -53,5 +53,6 @@ func NewCmdRoot(f *factory.Factory) *cobra.Command { cmd.SetVersionTemplate(color.New(color.Bold).Sprint(fRoot.factory.CLIVersion)) fRoot.setCmds(cmd) fRoot.setFlags(cmd) + return cmd } diff --git a/components/mdz/pkg/cmd/version/version.go b/components/mdz/pkg/cmd/version/version.go index 395100c1..715c1599 100644 --- a/components/mdz/pkg/cmd/version/version.go +++ b/components/mdz/pkg/cmd/version/version.go @@ -15,7 +15,8 @@ type factoryVersion struct { func (f *factoryVersion) runE(_ *cobra.Command, _ []string) error { return output.Print(&output.GeneralOutput{ Msg: color.New(color.Bold).Sprint(f.factory.CLIVersion), - Out: f.factory.IOStreams.Out}) + Out: f.factory.IOStreams.Out, + }) } func NewCmdVersion(f *factory.Factory) *cobra.Command { @@ -33,5 +34,6 @@ func NewCmdVersion(f *factory.Factory) *cobra.Command { RunE: fVersion.runE, } cmd.Flags().BoolP("help", "h", false, "Displays more information about the Midaz CLI") + return cmd } diff --git a/components/mdz/pkg/output/output.go b/components/mdz/pkg/output/output.go index 64e156a7..4ecec23a 100644 --- a/components/mdz/pkg/output/output.go +++ b/components/mdz/pkg/output/output.go @@ -22,6 +22,7 @@ func (o *GeneralOutput) Output() error { if _, err := fmt.Fprintf(o.Out, "%s\n", o.Msg); err != nil { return err } + return nil } @@ -37,5 +38,6 @@ func (o *ErrorOutput) Output() error { return err } } + return nil } diff --git a/go.mod b/go.mod index 5bff90ed..b796d815 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( require ( github.com/KyleBanks/depth v1.2.1 // indirect + github.com/catenacyber/perfsprint v0.7.1 // indirect github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -48,6 +49,7 @@ require ( go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel/metric v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect + golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect diff --git a/go.sum b/go.sum index 0ffff021..a469d779 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ github.com/bxcodec/dbresolver/v2 v2.2.0 h1:3Xg5Cw64khndjnWYiadP1mL1XU8eVxtkqcDad github.com/bxcodec/dbresolver/v2 v2.2.0/go.mod h1:xWb3HT8vrWUnoLVA7KQ+IcD9RvnzfRBqOkO9rKsg1rQ= github.com/casdoor/casdoor-go-sdk v1.1.0 h1:QW1pMoGG18X+GrcMolKKaTXCLDOpoYCu2kbfUZZQ+5A= github.com/casdoor/casdoor-go-sdk v1.1.0/go.mod h1:cMnkCQJgMYpgAlgEx8reSt1AVaDIQLcJ1zk5pzBaz+4= +github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc= +github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= From cfbacc7ffc95d23af16238434cd025f8110e9a7c Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Wed, 16 Oct 2024 17:52:20 -0300 Subject: [PATCH 09/62] test: test unit table simple for command root, version :rotating_light: --- components/mdz/pkg/cmd/root/root_test.go | 50 +++++++++++++++++ .../mdz/pkg/cmd/version/version_test.go | 55 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 components/mdz/pkg/cmd/root/root_test.go create mode 100644 components/mdz/pkg/cmd/version/version_test.go diff --git a/components/mdz/pkg/cmd/root/root_test.go b/components/mdz/pkg/cmd/root/root_test.go new file mode 100644 index 00000000..176dc7dd --- /dev/null +++ b/components/mdz/pkg/cmd/root/root_test.go @@ -0,0 +1,50 @@ +package root + +import ( + "bytes" + "testing" + + "github.com/LerianStudio/midaz/components/mdz/pkg/factory" + "github.com/LerianStudio/midaz/components/mdz/pkg/iostreams" + "github.com/stretchr/testify/assert" +) + +func TestNewCmdRoot(t *testing.T) { + tests := []struct { + name string + version string + expectedOut string + expectedErr string + expectedHelp string + }{ + { + name: "Standard output", + version: "1.0.0", + expectedOut: "1.0.0", + }, + { + name: "Version empty", + version: "", + expectedOut: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + outBuf := new(bytes.Buffer) + errBuf := new(bytes.Buffer) + f := &factory.Factory{ + CLIVersion: tt.version, + IOStreams: &iostreams.IOStreams{ + Out: outBuf, + Err: errBuf, + }, + } + + cmd := NewCmdRoot(f) + cmd.SetArgs([]string{"--help"}) + err := cmd.Execute() + assert.NoError(t, err) + }) + } +} diff --git a/components/mdz/pkg/cmd/version/version_test.go b/components/mdz/pkg/cmd/version/version_test.go new file mode 100644 index 00000000..1e7a19b2 --- /dev/null +++ b/components/mdz/pkg/cmd/version/version_test.go @@ -0,0 +1,55 @@ +package version + +import ( + "bytes" + "testing" + + "github.com/LerianStudio/midaz/components/mdz/pkg/factory" + "github.com/LerianStudio/midaz/components/mdz/pkg/iostreams" + "github.com/fatih/color" + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" +) + +func TestFactoryVersionRunE(t *testing.T) { + tests := []struct { + name string + version string + expected string + }{ + { + name: "Standard version output", + version: "1.0.0", + expected: color.New(color.Bold).Sprint("1.0.0") + "\n", + }, + { + name: "Empty version", + version: "", + expected: color.New(color.Bold).Sprint("") + "\n", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := &factory.Factory{ + CLIVersion: tt.version, + IOStreams: &iostreams.IOStreams{ + Out: new(bytes.Buffer), + }, + } + + fVersion := &factoryVersion{ + factory: f, + } + cmd := &cobra.Command{ + RunE: fVersion.runE, + } + + err := cmd.Execute() + assert.NoError(t, err) + + output := f.IOStreams.Out.(*bytes.Buffer).String() + assert.Equal(t, tt.expected, output) + }) + } +} From 8c310555cc926e54065f2cd0d72174d729fdcd59 Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Thu, 17 Oct 2024 13:27:46 +0000 Subject: [PATCH 10/62] chore(release): 1.19.0-beta.1 ## [1.19.0-beta.1](https://github.com/LerianStudio/midaz/compare/v1.18.0...v1.19.0-beta.1) (2024-10-17) ### Features * implement get operation by portfolio :sparkles: ([1e9322f](https://github.com/LerianStudio/midaz/commit/1e9322f8257672d95d850739609af87c673d7b56)) * initialize CLI with root and version commands :sparkles: ([6ebff8a](https://github.com/LerianStudio/midaz/commit/6ebff8a40ba097b0eaa4feb1106ebc29a5ba84dc)) ### Bug Fixes * resolve conflicts :bug: ([bc4b697](https://github.com/LerianStudio/midaz/commit/bc4b697c2e50cd1ec3cd41e0f96cb933a17b6a79)) --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab948b51..1378da2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [1.19.0-beta.1](https://github.com/LerianStudio/midaz/compare/v1.18.0...v1.19.0-beta.1) (2024-10-17) + + +### Features + +* implement get operation by portfolio :sparkles: ([1e9322f](https://github.com/LerianStudio/midaz/commit/1e9322f8257672d95d850739609af87c673d7b56)) +* initialize CLI with root and version commands :sparkles: ([6ebff8a](https://github.com/LerianStudio/midaz/commit/6ebff8a40ba097b0eaa4feb1106ebc29a5ba84dc)) + + +### Bug Fixes + +* resolve conflicts :bug: ([bc4b697](https://github.com/LerianStudio/midaz/commit/bc4b697c2e50cd1ec3cd41e0f96cb933a17b6a79)) + ## [1.18.0](https://github.com/LerianStudio/midaz/compare/v1.17.0...v1.18.0) (2024-10-16) From 981da7502d4c77e75de59415a428b972d658a3d9 Mon Sep 17 00:00:00 2001 From: "claudio.tessaro" Date: Thu, 17 Oct 2024 11:02:06 -0300 Subject: [PATCH 11/62] refactor: change message error to full payload :hammer: --- .../adapters/database/postgres/organization.postgresql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ledger/internal/adapters/database/postgres/organization.postgresql.go b/components/ledger/internal/adapters/database/postgres/organization.postgresql.go index 85985cca..9d643160 100644 --- a/components/ledger/internal/adapters/database/postgres/organization.postgresql.go +++ b/components/ledger/internal/adapters/database/postgres/organization.postgresql.go @@ -180,7 +180,7 @@ func (r *OrganizationPostgreSQLRepository) Find(ctx context.Context, id uuid.UUI var address string - row := db.QueryRowContext(ctx, `SELECT * FROM organization WHERE id = $1 AND deleted_at IS NULL`, id) + row := db.QueryRowContext(ctx, `SELECT * FROM organization WHERE id = $1`, id) if err := row.Scan(&organization.ID, &organization.ParentOrganizationID, &organization.LegalName, &organization.DoingBusinessAs, &organization.LegalDocument, &address, &organization.Status, &organization.StatusDescription, &organization.CreatedAt, &organization.UpdatedAt, &organization.DeletedAt); err != nil { From 8f8911cea6bd5375a27013ade56642025b2b535a Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Thu, 17 Oct 2024 15:04:06 +0000 Subject: [PATCH 12/62] chore(release): 1.19.0-beta.2 ## [1.19.0-beta.2](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.1...v1.19.0-beta.2) (2024-10-17) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1378da2c..aa0fb7ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## [1.19.0-beta.2](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.1...v1.19.0-beta.2) (2024-10-17) + ## [1.19.0-beta.1](https://github.com/LerianStudio/midaz/compare/v1.18.0...v1.19.0-beta.1) (2024-10-17) From 270ecfdc7aa14040aefa29ab09710aa6274acce9 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 16:19:16 -0300 Subject: [PATCH 13/62] feat: adds validation error for invalid path parameters :sparkles: --- common/constant/errors.go | 1 + common/errors.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/common/constant/errors.go b/common/constant/errors.go index 17bd574e..2dac649f 100644 --- a/common/constant/errors.go +++ b/common/constant/errors.go @@ -72,4 +72,5 @@ var ( ErrNoAccountIDsProvided = errors.New("0062") ErrFailedToRetrieveAccountsByAliases = errors.New("0063") ErrNoAccountsFound = errors.New("0064") + ErrInvalidPathParameter = errors.New("0065") ) diff --git a/common/errors.go b/common/errors.go index 069333d7..832437fe 100644 --- a/common/errors.go +++ b/common/errors.go @@ -685,6 +685,12 @@ func ValidateBusinessError(err error, entityType string, args ...any) error { Title: "No Accounts Found", Message: "No accounts were found in the search. Please review the search criteria and try again.", }, + cn.ErrInvalidPathParameter: ValidationError{ + EntityType: entityType, + Code: cn.ErrInvalidPathParameter.Error(), + Title: "Invalid Path Parameter", + Message: fmt.Sprintf("The provided path parameter(s) %s is/are not in the expected format. Please ensure the parameter adheres to the required format and try again.", args), + }, } if mappedError, found := errorMap[err]; found { From 6baa571275c876ab48760f882e48a400bd892196 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 16:27:34 -0300 Subject: [PATCH 14/62] feat: implements handler for parsing UUID path parameters :sparkles: --- common/net/http/withBody.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/common/net/http/withBody.go b/common/net/http/withBody.go index a738ffc9..3746ffb3 100644 --- a/common/net/http/withBody.go +++ b/common/net/http/withBody.go @@ -6,6 +6,9 @@ import ( "reflect" "strings" + cn "github.com/LerianStudio/midaz/common/constant" + "github.com/google/uuid" + "github.com/LerianStudio/midaz/common" "github.com/gofiber/fiber/v2" @@ -152,6 +155,30 @@ func ValidateStruct(s any) error { return nil } +// ParseUUIDPathParameters globally, considering all path parameters are UUIDs +func ParseUUIDPathParameters(c *fiber.Ctx) error { + params := c.AllParams() + + var invalidUUIDs []string + + for param, value := range params { + parsedUUID, err := uuid.Parse(value) + if err != nil { + invalidUUIDs = append(invalidUUIDs, param) + continue + } + + c.Locals(param, parsedUUID) + } + + if len(invalidUUIDs) > 0 { + err := common.ValidateBusinessError(cn.ErrInvalidPathParameter, "", invalidUUIDs) + return WithError(c, err) + } + + return c.Next() +} + //nolint:ireturn func newValidator() (*validator.Validate, ut.Translator) { locale := en.New() From d7135ff90f50f154a95928829142a37226be7629 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 16:36:32 -0300 Subject: [PATCH 15/62] fix: better formatting for error message :bug: --- common/net/http/withBody.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/net/http/withBody.go b/common/net/http/withBody.go index 3746ffb3..dd5b66c3 100644 --- a/common/net/http/withBody.go +++ b/common/net/http/withBody.go @@ -172,7 +172,7 @@ func ParseUUIDPathParameters(c *fiber.Ctx) error { } if len(invalidUUIDs) > 0 { - err := common.ValidateBusinessError(cn.ErrInvalidPathParameter, "", invalidUUIDs) + err := common.ValidateBusinessError(cn.ErrInvalidPathParameter, "", strings.Join(invalidUUIDs, ", ")) return WithError(c, err) } From 6153896bc83e0d3048a7223f89eafe6b6f2deae3 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 16:43:09 -0300 Subject: [PATCH 16/62] feat: adds UUID handler for routes with path parameters :sparkles: --- .../ledger/internal/ports/http/routes.go | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/components/ledger/internal/ports/http/routes.go b/components/ledger/internal/ports/http/routes.go index 9c7e4c81..a29b5299 100644 --- a/components/ledger/internal/ports/http/routes.go +++ b/components/ledger/internal/ports/http/routes.go @@ -25,45 +25,45 @@ func NewRouter(cc *mcasdoor.CasdoorConnection, ah *AccountHandler, ph *Portfolio // Organizations f.Post("/v1/organizations", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), lib.WithBody(new(o.CreateOrganizationInput), oh.CreateOrganization)) - f.Patch("/v1/organizations/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), lib.WithBody(new(o.UpdateOrganizationInput), oh.UpdateOrganization)) + f.Patch("/v1/organizations/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), lib.ParseUUIDPathParameters, lib.WithBody(new(o.UpdateOrganizationInput), oh.UpdateOrganization)) f.Get("/v1/organizations", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), oh.GetAllOrganizations) - f.Get("/v1/organizations/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), oh.GetOrganizationByID) - f.Delete("/v1/organizations/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), oh.DeleteOrganizationByID) + f.Get("/v1/organizations/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), lib.ParseUUIDPathParameters, oh.GetOrganizationByID) + f.Delete("/v1/organizations/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("organization"), lib.ParseUUIDPathParameters, oh.DeleteOrganizationByID) // Ledgers - f.Post("/v1/organizations/:organization_id/ledgers", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lib.WithBody(new(l.CreateLedgerInput), lh.CreateLedger)) - f.Patch("/v1/organizations/:organization_id/ledgers/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lib.WithBody(new(l.UpdateLedgerInput), lh.UpdateLedger)) - f.Get("/v1/organizations/:organization_id/ledgers", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lh.GetAllLedgers) - f.Get("/v1/organizations/:organization_id/ledgers/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lh.GetLedgerByID) - f.Delete("/v1/organizations/:organization_id/ledgers/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lh.DeleteLedgerByID) + f.Post("/v1/organizations/:organization_id/ledgers", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lib.ParseUUIDPathParameters, lib.WithBody(new(l.CreateLedgerInput), lh.CreateLedger)) + f.Patch("/v1/organizations/:organization_id/ledgers/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lib.ParseUUIDPathParameters, lib.WithBody(new(l.UpdateLedgerInput), lh.UpdateLedger)) + f.Get("/v1/organizations/:organization_id/ledgers", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lib.ParseUUIDPathParameters, lh.GetAllLedgers) + f.Get("/v1/organizations/:organization_id/ledgers/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lib.ParseUUIDPathParameters, lh.GetLedgerByID) + f.Delete("/v1/organizations/:organization_id/ledgers/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("ledger"), lib.ParseUUIDPathParameters, lh.DeleteLedgerByID) // Assets - f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/assets", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), lib.WithBody(new(s.CreateAssetInput), ih.CreateAsset)) - f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/assets/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), lib.WithBody(new(s.UpdateAssetInput), ih.UpdateAsset)) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/assets", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), ih.GetAllAssets) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/assets/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), ih.GetAssetByID) - f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/assets/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), ih.DeleteAssetByID) + f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/assets", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), lib.ParseUUIDPathParameters, lib.WithBody(new(s.CreateAssetInput), ih.CreateAsset)) + f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/assets/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), lib.ParseUUIDPathParameters, lib.WithBody(new(s.UpdateAssetInput), ih.UpdateAsset)) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/assets", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), lib.ParseUUIDPathParameters, ih.GetAllAssets) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/assets/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), lib.ParseUUIDPathParameters, ih.GetAssetByID) + f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/assets/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("asset"), lib.ParseUUIDPathParameters, ih.DeleteAssetByID) // Portfolios - f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), lib.WithBody(new(p.CreatePortfolioInput), ph.CreatePortfolio)) - f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), lib.WithBody(new(p.UpdatePortfolioInput), ph.UpdatePortfolio)) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), ph.GetAllPortfolios) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), ph.GetPortfolioByID) - f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), ph.DeletePortfolioByID) + f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), lib.ParseUUIDPathParameters, lib.WithBody(new(p.CreatePortfolioInput), ph.CreatePortfolio)) + f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), lib.ParseUUIDPathParameters, lib.WithBody(new(p.UpdatePortfolioInput), ph.UpdatePortfolio)) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), lib.ParseUUIDPathParameters, ph.GetAllPortfolios) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), lib.ParseUUIDPathParameters, ph.GetPortfolioByID) + f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("portfolio"), lib.ParseUUIDPathParameters, ph.DeletePortfolioByID) // Product - f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/products", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.WithBody(new(r.CreateProductInput), rh.CreateProduct)) - f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/products/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.WithBody(new(r.UpdateProductInput), rh.UpdateProduct)) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/products", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), rh.GetAllProducts) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/products/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), rh.GetProductByID) - f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/products/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), rh.DeleteProductByID) + f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/products", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.ParseUUIDPathParameters, lib.WithBody(new(r.CreateProductInput), rh.CreateProduct)) + f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/products/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.ParseUUIDPathParameters, lib.WithBody(new(r.UpdateProductInput), rh.UpdateProduct)) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/products", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.ParseUUIDPathParameters, rh.GetAllProducts) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/products/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.ParseUUIDPathParameters, rh.GetProductByID) + f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/products/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("product"), lib.ParseUUIDPathParameters, rh.DeleteProductByID) // Accounts - f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.WithBody(new(a.CreateAccountInput), ah.CreateAccount)) - f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.WithBody(new(a.UpdateAccountInput), ah.UpdateAccount)) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), ah.GetAllAccounts) - f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), ah.GetAccountByID) - f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), ah.DeleteAccountByID) + f.Post("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.CreateAccountInput), ah.CreateAccount)) + f.Patch("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, lib.WithBody(new(a.UpdateAccountInput), ah.UpdateAccount)) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.GetAllAccounts) + f.Get("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.GetAccountByID) + f.Delete("/v1/organizations/:organization_id/ledgers/:ledger_id/portfolios/:portfolio_id/accounts/:id", jwt.ProtectHTTP(), jwt.WithPermissionHTTP("account"), lib.ParseUUIDPathParameters, ah.DeleteAccountByID) // Health f.Get("/health", lib.Ping) From e2d284808c9c1d95d3d1192be2e4ba3e613318dc Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 16:57:28 -0300 Subject: [PATCH 17/62] fix: uses parsed uuid while retrieving organization :bug: --- .../ledger/internal/app/command/update-organization.go | 6 +++--- components/ledger/internal/app/query/get-id-organization.go | 6 +++--- components/ledger/internal/ports/http/organization.go | 6 ++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/components/ledger/internal/app/command/update-organization.go b/components/ledger/internal/app/command/update-organization.go index f61cdbe3..c9c326e0 100644 --- a/components/ledger/internal/app/command/update-organization.go +++ b/components/ledger/internal/app/command/update-organization.go @@ -15,7 +15,7 @@ import ( ) // UpdateOrganizationByID update an organization from the repository. -func (uc *UseCase) UpdateOrganizationByID(ctx context.Context, id string, uoi *o.UpdateOrganizationInput) (*o.Organization, error) { +func (uc *UseCase) UpdateOrganizationByID(ctx context.Context, id uuid.UUID, uoi *o.UpdateOrganizationInput) (*o.Organization, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to update organization: %v", uoi) @@ -37,7 +37,7 @@ func (uc *UseCase) UpdateOrganizationByID(ctx context.Context, id string, uoi *o Status: uoi.Status, } - organizationUpdated, err := uc.OrganizationRepo.Update(ctx, uuid.MustParse(id), organization) + organizationUpdated, err := uc.OrganizationRepo.Update(ctx, id, organization) if err != nil { logger.Errorf("Error updating organization on repo by id: %v", err) @@ -53,7 +53,7 @@ func (uc *UseCase) UpdateOrganizationByID(ctx context.Context, id string, uoi *o return nil, common.ValidateBusinessError(err, reflect.TypeOf(o.Organization{}).Name()) } - if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(o.Organization{}).Name(), id, uoi.Metadata); err != nil { + if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(o.Organization{}).Name(), id.String(), uoi.Metadata); err != nil { return nil, err } diff --git a/components/ledger/internal/app/query/get-id-organization.go b/components/ledger/internal/app/query/get-id-organization.go index 35fddf11..3cee27a9 100644 --- a/components/ledger/internal/app/query/get-id-organization.go +++ b/components/ledger/internal/app/query/get-id-organization.go @@ -15,11 +15,11 @@ import ( ) // GetOrganizationByID fetch a new organization from the repository -func (uc *UseCase) GetOrganizationByID(ctx context.Context, id string) (*o.Organization, error) { +func (uc *UseCase) GetOrganizationByID(ctx context.Context, id uuid.UUID) (*o.Organization, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving organization for id: %s", id) - organization, err := uc.OrganizationRepo.Find(ctx, uuid.MustParse(id)) + organization, err := uc.OrganizationRepo.Find(ctx, id) if err != nil { logger.Errorf("Error getting organization on repo by id: %v", err) @@ -31,7 +31,7 @@ func (uc *UseCase) GetOrganizationByID(ctx context.Context, id string) (*o.Organ } if organization != nil { - metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(o.Organization{}).Name(), id) + metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(o.Organization{}).Name(), id.String()) if err != nil { logger.Errorf("Error get metadata on mongodb organization: %v", err) return nil, err diff --git a/components/ledger/internal/ports/http/organization.go b/components/ledger/internal/ports/http/organization.go index 637d3e85..aa3f61bf 100644 --- a/components/ledger/internal/ports/http/organization.go +++ b/components/ledger/internal/ports/http/organization.go @@ -4,6 +4,8 @@ import ( "os" "reflect" + "github.com/google/uuid" + "github.com/LerianStudio/midaz/common" cn "github.com/LerianStudio/midaz/common/constant" @@ -47,7 +49,7 @@ func (handler *OrganizationHandler) UpdateOrganization(p any, c *fiber.Ctx) erro ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating update of Organization with ID: %s", id) payload := p.(*o.UpdateOrganizationInput) @@ -74,7 +76,7 @@ func (handler *OrganizationHandler) UpdateOrganization(p any, c *fiber.Ctx) erro func (handler *OrganizationHandler) GetOrganizationByID(c *fiber.Ctx) error { ctx := c.UserContext() - id := c.Params("id") + id := c.Locals("id").(uuid.UUID) logger := mlog.NewLoggerFromContext(ctx) From 866170a1d2bb849fc1ed002a9aed99d7ee43eecb Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 17:00:50 -0300 Subject: [PATCH 18/62] fix: uses parsed uuid while deleting organization :bug: --- components/ledger/internal/app/command/delete-organization.go | 4 ++-- components/ledger/internal/ports/http/organization.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/ledger/internal/app/command/delete-organization.go b/components/ledger/internal/app/command/delete-organization.go index c18a8268..fc52394c 100644 --- a/components/ledger/internal/app/command/delete-organization.go +++ b/components/ledger/internal/app/command/delete-organization.go @@ -15,11 +15,11 @@ import ( ) // DeleteOrganizationByID fetch a new organization from the repository -func (uc *UseCase) DeleteOrganizationByID(ctx context.Context, id string) error { +func (uc *UseCase) DeleteOrganizationByID(ctx context.Context, id uuid.UUID) error { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Remove organization for id: %s", id) - if err := uc.OrganizationRepo.Delete(ctx, uuid.MustParse(id)); err != nil { + if err := uc.OrganizationRepo.Delete(ctx, id); err != nil { logger.Errorf("Error deleting organization on repo by id: %v", err) if errors.Is(err, app.ErrDatabaseItemNotFound) { diff --git a/components/ledger/internal/ports/http/organization.go b/components/ledger/internal/ports/http/organization.go index aa3f61bf..9d5b6080 100644 --- a/components/ledger/internal/ports/http/organization.go +++ b/components/ledger/internal/ports/http/organization.go @@ -144,7 +144,7 @@ func (handler *OrganizationHandler) DeleteOrganizationByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating removal of Organization with ID: %s", id) if os.Getenv("ENV_NAME") == "production" { From ad1bcae482d2939c8e828b169b566d3a13be95cd Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 17:19:01 -0300 Subject: [PATCH 19/62] fix: uses parsed uuid while getting and updating a ledger :bug: --- .../ledger/internal/app/command/update-ledger.go | 8 ++++---- components/ledger/internal/app/query/get-id-ledger.go | 6 +++--- components/ledger/internal/ports/http/ledger.go | 10 ++++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/components/ledger/internal/app/command/update-ledger.go b/components/ledger/internal/app/command/update-ledger.go index 95313ea7..4321841a 100644 --- a/components/ledger/internal/app/command/update-ledger.go +++ b/components/ledger/internal/app/command/update-ledger.go @@ -15,17 +15,17 @@ import ( ) // UpdateLedgerByID update a ledger from the repository. -func (uc *UseCase) UpdateLedgerByID(ctx context.Context, organizationID, id string, uli *l.UpdateLedgerInput) (*l.Ledger, error) { +func (uc *UseCase) UpdateLedgerByID(ctx context.Context, organizationID, id uuid.UUID, uli *l.UpdateLedgerInput) (*l.Ledger, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to update ledger: %v", uli) ledger := &l.Ledger{ Name: uli.Name, - OrganizationID: organizationID, + OrganizationID: organizationID.String(), Status: uli.Status, } - ledgerUpdated, err := uc.LedgerRepo.Update(ctx, uuid.MustParse(organizationID), uuid.MustParse(id), ledger) + ledgerUpdated, err := uc.LedgerRepo.Update(ctx, organizationID, id, ledger) if err != nil { logger.Errorf("Error updating ledger on repo by id: %v", err) @@ -41,7 +41,7 @@ func (uc *UseCase) UpdateLedgerByID(ctx context.Context, organizationID, id stri return nil, common.ValidateBusinessError(err, reflect.TypeOf(l.Ledger{}).Name()) } - if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(l.Ledger{}).Name(), id, uli.Metadata); err != nil { + if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(l.Ledger{}).Name(), id.String(), uli.Metadata); err != nil { return nil, err } diff --git a/components/ledger/internal/app/query/get-id-ledger.go b/components/ledger/internal/app/query/get-id-ledger.go index dee65570..e723f804 100644 --- a/components/ledger/internal/app/query/get-id-ledger.go +++ b/components/ledger/internal/app/query/get-id-ledger.go @@ -15,11 +15,11 @@ import ( ) // GetLedgerByID Get a ledger from the repository by given id. -func (uc *UseCase) GetLedgerByID(ctx context.Context, organizationID, id string) (*l.Ledger, error) { +func (uc *UseCase) GetLedgerByID(ctx context.Context, organizationID, id uuid.UUID) (*l.Ledger, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving ledger for id: %s", id) - ledger, err := uc.LedgerRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(id)) + ledger, err := uc.LedgerRepo.Find(ctx, organizationID, id) if err != nil { logger.Errorf("Error getting ledger on repo by id: %v", err) @@ -31,7 +31,7 @@ func (uc *UseCase) GetLedgerByID(ctx context.Context, organizationID, id string) } if ledger != nil { - metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(l.Ledger{}).Name(), id) + metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(l.Ledger{}).Name(), id.String()) if err != nil { logger.Errorf("Error get metadata on mongodb ledger: %v", err) return nil, err diff --git a/components/ledger/internal/ports/http/ledger.go b/components/ledger/internal/ports/http/ledger.go index 3c046896..24fd3093 100644 --- a/components/ledger/internal/ports/http/ledger.go +++ b/components/ledger/internal/ports/http/ledger.go @@ -4,6 +4,8 @@ import ( "os" "reflect" + "github.com/google/uuid" + "github.com/LerianStudio/midaz/common" cn "github.com/LerianStudio/midaz/common/constant" @@ -50,10 +52,10 @@ func (handler *LedgerHandler) GetLedgerByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating retrieval of Ledger with ID: %s", id) - organizationID := c.Params("organization_id") + organizationID := c.Locals("organization_id").(uuid.UUID) ledger, err := handler.Query.GetLedgerByID(ctx, organizationID, id) if err != nil { @@ -118,10 +120,10 @@ func (handler *LedgerHandler) UpdateLedger(p any, c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating update of Ledger with ID: %s", id) - organizationID := c.Params("organization_id") + organizationID := c.Locals("organization_id").(uuid.UUID) payload := p.(*l.UpdateLedgerInput) logger.Infof("Request to update an Ledger with details: %#v", payload) From 2260a331e381d452bcab942f9f06864c60444f52 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 20:06:59 -0300 Subject: [PATCH 20/62] fix: uses parsed uuid while getting all organization ledgers :bug: --- components/ledger/internal/app/query/get-all-ledgers.go | 4 ++-- .../ledger/internal/app/query/get-all-metadata-ledgers.go | 4 ++-- components/ledger/internal/ports/http/ledger.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/ledger/internal/app/query/get-all-ledgers.go b/components/ledger/internal/app/query/get-all-ledgers.go index f3c2c81f..b2bea8a1 100644 --- a/components/ledger/internal/app/query/get-all-ledgers.go +++ b/components/ledger/internal/app/query/get-all-ledgers.go @@ -16,11 +16,11 @@ import ( ) // GetAllLedgers fetch all Ledgers from the repository -func (uc *UseCase) GetAllLedgers(ctx context.Context, organizationID string, filter commonHTTP.QueryHeader) ([]*l.Ledger, error) { +func (uc *UseCase) GetAllLedgers(ctx context.Context, organizationID uuid.UUID, filter commonHTTP.QueryHeader) ([]*l.Ledger, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving ledgers") - ledgers, err := uc.LedgerRepo.FindAll(ctx, uuid.MustParse(organizationID), filter.Limit, filter.Page) + ledgers, err := uc.LedgerRepo.FindAll(ctx, organizationID, filter.Limit, filter.Page) if err != nil { logger.Errorf("Error getting ledgers on repo: %v", err) diff --git a/components/ledger/internal/app/query/get-all-metadata-ledgers.go b/components/ledger/internal/app/query/get-all-metadata-ledgers.go index 677999b7..1fb2ab5c 100644 --- a/components/ledger/internal/app/query/get-all-metadata-ledgers.go +++ b/components/ledger/internal/app/query/get-all-metadata-ledgers.go @@ -16,7 +16,7 @@ import ( ) // GetAllMetadataLedgers fetch all Ledgers from the repository -func (uc *UseCase) GetAllMetadataLedgers(ctx context.Context, organizationID string, filter commonHTTP.QueryHeader) ([]*l.Ledger, error) { +func (uc *UseCase) GetAllMetadataLedgers(ctx context.Context, organizationID uuid.UUID, filter commonHTTP.QueryHeader) ([]*l.Ledger, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving ledgers") @@ -33,7 +33,7 @@ func (uc *UseCase) GetAllMetadataLedgers(ctx context.Context, organizationID str metadataMap[meta.EntityID] = meta.Data } - ledgers, err := uc.LedgerRepo.ListByIDs(ctx, uuid.MustParse(organizationID), uuids) + ledgers, err := uc.LedgerRepo.ListByIDs(ctx, organizationID, uuids) if err != nil { logger.Errorf("Error getting ledgers on repo by query params: %v", err) diff --git a/components/ledger/internal/ports/http/ledger.go b/components/ledger/internal/ports/http/ledger.go index 24fd3093..96b83d8e 100644 --- a/components/ledger/internal/ports/http/ledger.go +++ b/components/ledger/internal/ports/http/ledger.go @@ -73,7 +73,7 @@ func (handler *LedgerHandler) GetAllLedgers(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") + organizationID := c.Locals("organization_id").(uuid.UUID) headerParams := commonHTTP.ValidateParameters(c.Queries()) From 8dc3a97f8c859a6948cad099cd61888c8c016bee Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 20:12:58 -0300 Subject: [PATCH 21/62] fix: uses parsed uuid while deleting ledger by id :bug: --- components/ledger/internal/app/command/delete-ledger.go | 4 ++-- components/ledger/internal/ports/http/ledger.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/ledger/internal/app/command/delete-ledger.go b/components/ledger/internal/app/command/delete-ledger.go index b4b4acd5..18edc866 100644 --- a/components/ledger/internal/app/command/delete-ledger.go +++ b/components/ledger/internal/app/command/delete-ledger.go @@ -15,11 +15,11 @@ import ( ) // DeleteLedgerByID deletes a ledger from the repository -func (uc *UseCase) DeleteLedgerByID(ctx context.Context, organizationID, id string) error { +func (uc *UseCase) DeleteLedgerByID(ctx context.Context, organizationID, id uuid.UUID) error { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Remove ledger for id: %s", id) - if err := uc.LedgerRepo.Delete(ctx, uuid.MustParse(organizationID), uuid.MustParse(id)); err != nil { + if err := uc.LedgerRepo.Delete(ctx, organizationID, id); err != nil { logger.Errorf("Error deleting ledger on repo by id: %v", err) if errors.Is(err, app.ErrDatabaseItemNotFound) { diff --git a/components/ledger/internal/ports/http/ledger.go b/components/ledger/internal/ports/http/ledger.go index 96b83d8e..6aa4cdf7 100644 --- a/components/ledger/internal/ports/http/ledger.go +++ b/components/ledger/internal/ports/http/ledger.go @@ -151,10 +151,10 @@ func (handler *LedgerHandler) DeleteLedgerByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating removal of Ledeger with ID: %s", id) - organizationID := c.Params("organization_id") + organizationID := c.Locals("organization_id").(uuid.UUID) if os.Getenv("ENV_NAME") == "production" { logger.Errorf("Failed to remove Ledger with ID: %s in ", id) From 333bf4921d3f2fd48156ead07ac8b1b29d88d5fa Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 20:15:02 -0300 Subject: [PATCH 22/62] fix: uses parsed uuid while creating asset :bug: --- components/ledger/internal/ports/http/asset.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/ledger/internal/ports/http/asset.go b/components/ledger/internal/ports/http/asset.go index 0415d167..b30f606e 100644 --- a/components/ledger/internal/ports/http/asset.go +++ b/components/ledger/internal/ports/http/asset.go @@ -24,16 +24,16 @@ func (handler *AssetHandler) CreateAsset(a any, c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") + organizationID := c.Locals("organization_id").(uuid.UUID) logger.Infof("Initiating create of Asset with organization ID: %s", organizationID) - ledgerID := c.Params("ledger_id") + ledgerID := c.Locals("ledger_id").(uuid.UUID) logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID) payload := a.(*s.CreateAssetInput) logger.Infof("Request to create a Asset with details: %#v", payload) - asset, err := handler.Command.CreateAsset(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), payload) + asset, err := handler.Command.CreateAsset(ctx, organizationID, ledgerID, payload) if err != nil { return commonHTTP.WithError(c, err) } From 9c8b3a2f9747117e5149f3a515c8a5b582db4942 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 20:23:54 -0300 Subject: [PATCH 23/62] fix: uses parsed uuid while retrieving and updating asset :bug: --- .../ledger/internal/app/query/get-id-asset.go | 6 +++--- components/ledger/internal/ports/http/asset.go | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/ledger/internal/app/query/get-id-asset.go b/components/ledger/internal/app/query/get-id-asset.go index f1e00862..fdbbcfd3 100644 --- a/components/ledger/internal/app/query/get-id-asset.go +++ b/components/ledger/internal/app/query/get-id-asset.go @@ -15,11 +15,11 @@ import ( ) // GetAssetByID get an Asset from the repository by given id. -func (uc *UseCase) GetAssetByID(ctx context.Context, organizationID, ledgerID, id string) (*s.Asset, error) { +func (uc *UseCase) GetAssetByID(ctx context.Context, organizationID, ledgerID, id uuid.UUID) (*s.Asset, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving asset for id: %s", id) - asset, err := uc.AssetRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id)) + asset, err := uc.AssetRepo.Find(ctx, organizationID, ledgerID, id) if err != nil { logger.Errorf("Error getting asset on repo by id: %v", err) @@ -31,7 +31,7 @@ func (uc *UseCase) GetAssetByID(ctx context.Context, organizationID, ledgerID, i } if asset != nil { - metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(s.Asset{}).Name(), id) + metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(s.Asset{}).Name(), id.String()) if err != nil { logger.Errorf("Error get metadata on mongodb asset: %v", err) return nil, err diff --git a/components/ledger/internal/ports/http/asset.go b/components/ledger/internal/ports/http/asset.go index b30f606e..442d8941 100644 --- a/components/ledger/internal/ports/http/asset.go +++ b/components/ledger/internal/ports/http/asset.go @@ -98,9 +98,9 @@ func (handler *AssetHandler) GetAllAssets(c *fiber.Ctx) error { func (handler *AssetHandler) GetAssetByID(c *fiber.Ctx) error { ctx := c.UserContext() - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) logger := mlog.NewLoggerFromContext(ctx) @@ -122,16 +122,16 @@ func (handler *AssetHandler) UpdateAsset(a any, c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating update of Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) payload := a.(*s.UpdateAssetInput) logger.Infof("Request to update an Asset with details: %#v", payload) - _, err := handler.Command.UpdateAssetByID(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id), payload) + _, err := handler.Command.UpdateAssetByID(ctx, organizationID, ledgerID, id, payload) if err != nil { logger.Errorf("Failed to update Asset with ID: %s, Error: %s", id, err.Error()) return commonHTTP.WithError(c, err) From aadf8852154726bd4aef2e3295221b5472236ed9 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Thu, 17 Oct 2024 20:31:26 -0300 Subject: [PATCH 24/62] fix: uses parsed uuid while retrieving all assets from a ledger :bug: --- components/ledger/internal/app/query/get-all-asset.go | 4 ++-- .../ledger/internal/app/query/get-all-metadata-asset.go | 4 ++-- components/ledger/internal/ports/http/asset.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/ledger/internal/app/query/get-all-asset.go b/components/ledger/internal/app/query/get-all-asset.go index b604db01..75e638f9 100644 --- a/components/ledger/internal/app/query/get-all-asset.go +++ b/components/ledger/internal/app/query/get-all-asset.go @@ -16,11 +16,11 @@ import ( ) // GetAllAssets fetch all Asset from the repository -func (uc *UseCase) GetAllAssets(ctx context.Context, organizationID, ledgerID string, filter commonHTTP.QueryHeader) ([]*s.Asset, error) { +func (uc *UseCase) GetAllAssets(ctx context.Context, organizationID, ledgerID uuid.UUID, filter commonHTTP.QueryHeader) ([]*s.Asset, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving assets") - assets, err := uc.AssetRepo.FindAll(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), filter.Limit, filter.Page) + assets, err := uc.AssetRepo.FindAll(ctx, organizationID, ledgerID, filter.Limit, filter.Page) if err != nil { logger.Errorf("Error getting assets on repo: %v", err) diff --git a/components/ledger/internal/app/query/get-all-metadata-asset.go b/components/ledger/internal/app/query/get-all-metadata-asset.go index 5c18f08a..7add5a28 100644 --- a/components/ledger/internal/app/query/get-all-metadata-asset.go +++ b/components/ledger/internal/app/query/get-all-metadata-asset.go @@ -16,7 +16,7 @@ import ( ) // GetAllMetadataAssets fetch all Assets from the repository -func (uc *UseCase) GetAllMetadataAssets(ctx context.Context, organizationID, ledgerID string, filter commonHTTP.QueryHeader) ([]*s.Asset, error) { +func (uc *UseCase) GetAllMetadataAssets(ctx context.Context, organizationID, ledgerID uuid.UUID, filter commonHTTP.QueryHeader) ([]*s.Asset, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving assets") @@ -33,7 +33,7 @@ func (uc *UseCase) GetAllMetadataAssets(ctx context.Context, organizationID, led metadataMap[meta.EntityID] = meta.Data } - assets, err := uc.AssetRepo.ListByIDs(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuids) + assets, err := uc.AssetRepo.ListByIDs(ctx, organizationID, ledgerID, uuids) if err != nil { logger.Errorf("Error getting assets on repo by query params: %v", err) diff --git a/components/ledger/internal/ports/http/asset.go b/components/ledger/internal/ports/http/asset.go index 442d8941..189883d3 100644 --- a/components/ledger/internal/ports/http/asset.go +++ b/components/ledger/internal/ports/http/asset.go @@ -48,10 +48,10 @@ func (handler *AssetHandler) GetAllAssets(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") + organizationID := c.Locals("organization_id").(uuid.UUID) logger.Infof("Initiating create of Asset with organization ID: %s", organizationID) - ledgerID := c.Params("ledger_id") + ledgerID := c.Locals("ledger_id").(uuid.UUID) logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID) headerParams := commonHTTP.ValidateParameters(c.Queries()) From 4dfe76c1092412a129a60b09d408f71d8a59dca0 Mon Sep 17 00:00:00 2001 From: Andre Russowsky Date: Thu, 17 Oct 2024 22:25:50 -0300 Subject: [PATCH 25/62] fix: Invalid code format validation :bug: --- common/utils.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/utils.go b/common/utils.go index dac548a0..346d7dfa 100644 --- a/common/utils.go +++ b/common/utils.go @@ -100,7 +100,10 @@ func ValidateCurrency(code string) error { } for _, r := range code { - if unicode.IsLetter(r) && !unicode.IsUpper(r) { + if !unicode.IsLetter(r) { + return cn.ErrInvalidCodeFormat + } + if !unicode.IsUpper(r) { return cn.ErrCodeUppercaseRequirement } } From e8383cac7957d1f0d63ce20f71534052ab1e8703 Mon Sep 17 00:00:00 2001 From: Andre Russowsky Date: Thu, 17 Oct 2024 22:29:01 -0300 Subject: [PATCH 26/62] fix: Invalid code format validation :bug: --- common/utils.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/utils.go b/common/utils.go index 346d7dfa..20d90111 100644 --- a/common/utils.go +++ b/common/utils.go @@ -102,8 +102,7 @@ func ValidateCurrency(code string) error { for _, r := range code { if !unicode.IsLetter(r) { return cn.ErrInvalidCodeFormat - } - if !unicode.IsUpper(r) { + } else if !unicode.IsUpper(r) { return cn.ErrCodeUppercaseRequirement } } From 926ca9b758d7e69611afa903c035fa01218b108f Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 13:07:12 +0200 Subject: [PATCH 27/62] fix: remove unique constraint on database in code and reference on accounts; :bug: --- components/ledger/migrations/000003_create_asset_table.up.sql | 3 +-- .../ledger/migrations/000006_create_account_table.up.sql | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/components/ledger/migrations/000003_create_asset_table.up.sql b/components/ledger/migrations/000003_create_asset_table.up.sql index 0bc71ecc..a064c428 100644 --- a/components/ledger/migrations/000003_create_asset_table.up.sql +++ b/components/ledger/migrations/000003_create_asset_table.up.sql @@ -12,6 +12,5 @@ CREATE TABLE IF NOT EXISTS asset updated_at TIMESTAMP WITH TIME ZONE, deleted_at TIMESTAMP WITH TIME ZONE, FOREIGN KEY (ledger_id) REFERENCES ledger (id), - FOREIGN KEY (organization_id) REFERENCES organization (id), - UNIQUE (code) + FOREIGN KEY (organization_id) REFERENCES organization (id) ); \ No newline at end of file diff --git a/components/ledger/migrations/000006_create_account_table.up.sql b/components/ledger/migrations/000006_create_account_table.up.sql index 8fd91b57..15b17968 100644 --- a/components/ledger/migrations/000006_create_account_table.up.sql +++ b/components/ledger/migrations/000006_create_account_table.up.sql @@ -22,7 +22,6 @@ CREATE TABLE IF NOT EXISTS account updated_at TIMESTAMP WITH TIME ZONE, deleted_at TIMESTAMP WITH TIME ZONE, FOREIGN KEY (parent_account_id) REFERENCES account (id), - FOREIGN KEY (asset_code) REFERENCES asset (code), FOREIGN KEY (organization_id) REFERENCES organization (id), FOREIGN KEY (ledger_id) REFERENCES ledger (id), FOREIGN KEY (portfolio_id) REFERENCES portfolio (id), From 3a712820a16ede4cd50cdc1729c5abf0507950b0 Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 13:07:30 +0200 Subject: [PATCH 28/62] fix: add log; :bug: --- components/ledger/internal/ports/http/asset.go | 1 + 1 file changed, 1 insertion(+) diff --git a/components/ledger/internal/ports/http/asset.go b/components/ledger/internal/ports/http/asset.go index 0415d167..cd0342bd 100644 --- a/components/ledger/internal/ports/http/asset.go +++ b/components/ledger/internal/ports/http/asset.go @@ -35,6 +35,7 @@ func (handler *AssetHandler) CreateAsset(a any, c *fiber.Ctx) error { asset, err := handler.Command.CreateAsset(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), payload) if err != nil { + logger.Infof("Error to created Asset: %s", err.Error()) return commonHTTP.WithError(c, err) } From 9b71d2ee9bafba37b0eb9e1a0f328b5d10036d1e Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 13:08:33 +0200 Subject: [PATCH 29/62] fix: add parentheses on find name or asset query; :bug: --- .../internal/adapters/database/postgres/asset.postgresql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ledger/internal/adapters/database/postgres/asset.postgresql.go b/components/ledger/internal/adapters/database/postgres/asset.postgresql.go index e872a6ce..cf4ab8d9 100644 --- a/components/ledger/internal/adapters/database/postgres/asset.postgresql.go +++ b/components/ledger/internal/adapters/database/postgres/asset.postgresql.go @@ -93,7 +93,7 @@ func (r *AssetPostgreSQLRepository) FindByNameOrCode(ctx context.Context, organi return false, err } - rows, err := db.QueryContext(ctx, "SELECT * FROM asset WHERE organization_id = $1 AND ledger_id = $2 AND name LIKE $3 OR code = $4 AND deleted_at IS NULL ORDER BY created_at DESC", + rows, err := db.QueryContext(ctx, "SELECT * FROM asset WHERE organization_id = $1 AND ledger_id = $2 AND (name LIKE $3 OR code = $4) AND deleted_at IS NULL ORDER BY created_at DESC", organizationID, ledgerID, name, code) if err != nil { return false, err From d2481ebf4d3007df5337394c151360aca28ee69a Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 13:09:00 +0200 Subject: [PATCH 30/62] fix: add required in asset_code; :bug: --- components/ledger/internal/domain/portfolio/account/account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ledger/internal/domain/portfolio/account/account.go b/components/ledger/internal/domain/portfolio/account/account.go index f172c497..0dea77e5 100644 --- a/components/ledger/internal/domain/portfolio/account/account.go +++ b/components/ledger/internal/domain/portfolio/account/account.go @@ -36,7 +36,7 @@ type AccountPostgreSQLModel struct { // CreateAccountInput is a struct design to encapsulate request create payload data. type CreateAccountInput struct { - AssetCode string `json:"assetCode"` + AssetCode string `json:"assetCode" validate:"required"` Name string `json:"name"` Alias *string `json:"alias"` Type string `json:"type"` From 2375963e26657972f22ac714c905775bdf0ed5d5 Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 13:09:22 +0200 Subject: [PATCH 31/62] fix: create validation on code to certify that asset_code exist on assets before insert in accounts; :bug: --- .../ledger/internal/app/command/create-account.go | 14 ++++++++++++++ .../ledger/internal/app/command/create-asset.go | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/components/ledger/internal/app/command/create-account.go b/components/ledger/internal/app/command/create-account.go index e6169353..335aa92e 100644 --- a/components/ledger/internal/app/command/create-account.go +++ b/components/ledger/internal/app/command/create-account.go @@ -46,6 +46,20 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, Scale: &balanceValue, } + if err := common.ValidateCurrency(cai.AssetCode); err != nil { + return nil, common.ValidateBusinessError(cn.ErrInvalidCodeFormat, reflect.TypeOf(a.Account{}).Name()) + } + + isAsset, err := uc.AssetRepo.FindByNameOrCode(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), "", cai.AssetCode) + if err != nil { + logger.Errorf("Error to find asset by asset code: %v", err.Error()) + return nil, err + } + + if !isAsset { + return nil, common.ValidateBusinessError(cn.ErrAssetCodeNotFound, reflect.TypeOf(a.Account{}).Name()) + } + if cai.EntityID == nil { portfolio, err := uc.PortfolioRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID)) if err != nil { diff --git a/components/ledger/internal/app/command/create-asset.go b/components/ledger/internal/app/command/create-asset.go index 8f6850ad..07044b07 100644 --- a/components/ledger/internal/app/command/create-asset.go +++ b/components/ledger/internal/app/command/create-asset.go @@ -2,6 +2,7 @@ package command import ( "context" + cn "github.com/LerianStudio/midaz/common/constant" "reflect" "time" @@ -36,12 +37,17 @@ func (uc *UseCase) CreateAsset(ctx context.Context, organizationID, ledgerID uui } } - _, err := uc.AssetRepo.FindByNameOrCode(ctx, organizationID, ledgerID, cii.Name, cii.Code) + isAsset, err := uc.AssetRepo.FindByNameOrCode(ctx, organizationID, ledgerID, cii.Name, cii.Code) if err != nil { logger.Errorf("Error creating asset: %v", err) return nil, err } + if !isAsset { + return nil, common.ValidateBusinessError(cn.ErrAssetCodeNotFound, reflect.TypeOf(s.Asset{}).Name()) + } + + asset := &s.Asset{ Name: cii.Name, Type: cii.Type, From 5c5ca6ae32b783e710c1a8da73e7efb24e492923 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 08:18:46 -0300 Subject: [PATCH 32/62] fix (asset): uses parsed uuid while deleting :bug: --- components/ledger/internal/ports/http/asset.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/ledger/internal/ports/http/asset.go b/components/ledger/internal/ports/http/asset.go index 189883d3..5414a2fb 100644 --- a/components/ledger/internal/ports/http/asset.go +++ b/components/ledger/internal/ports/http/asset.go @@ -154,13 +154,13 @@ func (handler *AssetHandler) DeleteAssetByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating removal of Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) - if err := handler.Command.DeleteAssetByID(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id)); err != nil { + if err := handler.Command.DeleteAssetByID(ctx, organizationID, ledgerID, id); err != nil { logger.Errorf("Failed to remove Asset with Ledger ID: %s and Asset ID: %s, Error: %s", ledgerID, id, err.Error()) return commonHTTP.WithError(c, err) } From 583890a6c1d178b95b41666a91600a60d3053123 Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 13:30:36 +0200 Subject: [PATCH 33/62] fix: adjust to validate if exists code on assets; :bug: --- components/ledger/internal/app/command/create-account.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/components/ledger/internal/app/command/create-account.go b/components/ledger/internal/app/command/create-account.go index 335aa92e..7fbee04a 100644 --- a/components/ledger/internal/app/command/create-account.go +++ b/components/ledger/internal/app/command/create-account.go @@ -50,12 +50,7 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, return nil, common.ValidateBusinessError(cn.ErrInvalidCodeFormat, reflect.TypeOf(a.Account{}).Name()) } - isAsset, err := uc.AssetRepo.FindByNameOrCode(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), "", cai.AssetCode) - if err != nil { - logger.Errorf("Error to find asset by asset code: %v", err.Error()) - return nil, err - } - + isAsset, _ := uc.AssetRepo.FindByNameOrCode(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), "", cai.AssetCode) if !isAsset { return nil, common.ValidateBusinessError(cn.ErrAssetCodeNotFound, reflect.TypeOf(a.Account{}).Name()) } From 398a52914390d741d652c82f68df8e785cfd8db3 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 08:35:58 -0300 Subject: [PATCH 34/62] fix (portfolio): uses parsed uuid for retrieving and updating :bug: --- .../ledger/internal/app/command/update-portfolio.go | 6 +++--- .../ledger/internal/app/query/get-id-portfolio.go | 6 +++--- components/ledger/internal/ports/http/portfolio.go | 13 +++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/components/ledger/internal/app/command/update-portfolio.go b/components/ledger/internal/app/command/update-portfolio.go index 4a429c02..2045b2ad 100644 --- a/components/ledger/internal/app/command/update-portfolio.go +++ b/components/ledger/internal/app/command/update-portfolio.go @@ -15,7 +15,7 @@ import ( ) // UpdatePortfolioByID update a portfolio from the repository by given id. -func (uc *UseCase) UpdatePortfolioByID(ctx context.Context, organizationID, ledgerID, id string, upi *p.UpdatePortfolioInput) (*p.Portfolio, error) { +func (uc *UseCase) UpdatePortfolioByID(ctx context.Context, organizationID, ledgerID, id uuid.UUID, upi *p.UpdatePortfolioInput) (*p.Portfolio, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to update portfolio: %v", upi) @@ -24,7 +24,7 @@ func (uc *UseCase) UpdatePortfolioByID(ctx context.Context, organizationID, ledg Status: upi.Status, } - portfolioUpdated, err := uc.PortfolioRepo.Update(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id), portfolio) + portfolioUpdated, err := uc.PortfolioRepo.Update(ctx, organizationID, ledgerID, id, portfolio) if err != nil { logger.Errorf("Error updating portfolio on repo by id: %v", err) @@ -40,7 +40,7 @@ func (uc *UseCase) UpdatePortfolioByID(ctx context.Context, organizationID, ledg return nil, common.ValidateBusinessError(err, reflect.TypeOf(p.Portfolio{}).Name()) } - if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(p.Portfolio{}).Name(), id, upi.Metadata); err != nil { + if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(p.Portfolio{}).Name(), id.String(), upi.Metadata); err != nil { return nil, err } diff --git a/components/ledger/internal/app/query/get-id-portfolio.go b/components/ledger/internal/app/query/get-id-portfolio.go index a3c374ea..f1fcb6ec 100644 --- a/components/ledger/internal/app/query/get-id-portfolio.go +++ b/components/ledger/internal/app/query/get-id-portfolio.go @@ -15,11 +15,11 @@ import ( ) // GetPortfolioByID get a Portfolio from the repository by given id. -func (uc *UseCase) GetPortfolioByID(ctx context.Context, organizationID, ledgerID, id string) (*p.Portfolio, error) { +func (uc *UseCase) GetPortfolioByID(ctx context.Context, organizationID, ledgerID, id uuid.UUID) (*p.Portfolio, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving portfolio for id: %s", id) - portfolio, err := uc.PortfolioRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id)) + portfolio, err := uc.PortfolioRepo.Find(ctx, organizationID, ledgerID, id) if err != nil { logger.Errorf("Error getting portfolio on repo by id: %v", err) @@ -31,7 +31,7 @@ func (uc *UseCase) GetPortfolioByID(ctx context.Context, organizationID, ledgerI } if portfolio != nil { - metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(p.Portfolio{}).Name(), id) + metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(p.Portfolio{}).Name(), id.String()) if err != nil { logger.Errorf("Error get metadata on mongodb portfolio: %v", err) return nil, err diff --git a/components/ledger/internal/ports/http/portfolio.go b/components/ledger/internal/ports/http/portfolio.go index 99ff0a4e..a6fa1a71 100644 --- a/components/ledger/internal/ports/http/portfolio.go +++ b/components/ledger/internal/ports/http/portfolio.go @@ -8,6 +8,7 @@ import ( "github.com/LerianStudio/midaz/components/ledger/internal/app/query" p "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/portfolio" "github.com/gofiber/fiber/v2" + "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" ) @@ -95,9 +96,9 @@ func (handler *PortfolioHandler) GetAllPortfolios(c *fiber.Ctx) error { func (handler *PortfolioHandler) GetPortfolioByID(c *fiber.Ctx) error { ctx := c.UserContext() - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) logger := mlog.NewLoggerFromContext(ctx) @@ -119,9 +120,9 @@ func (handler *PortfolioHandler) UpdatePortfolio(i any, c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) logger.Infof("Initiating update of Portfolio with Organization: %s Ledger ID: %s and Portfolio ID: %s", organizationID, ledgerID, id) From a1817091640de24bad22e43eaddccd86b21dcf82 Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 13:50:24 +0200 Subject: [PATCH 35/62] fix: remove copyloopvar and perfsprint; :bug: --- .golangci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 0066f070..e0a084c7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,7 +8,6 @@ linters: - dupword # Detects duplicate words. - durationcheck - errchkjson - - copyloopvar - gocyclo - loggercheck - ineffassign @@ -17,7 +16,6 @@ linters: - nakedret - nilerr # Detects code that returns nil even if it checks that the error is not nil. - nolintlint # Detects ill-formed or insufficient nolint directives. - - perfsprint # Detects fmt.Sprintf uses that can be replaced with a faster alternative. - prealloc # Detects slice declarations that could potentially be pre-allocated. - predeclared # Detects code that shadows one of Go's predeclared identifiers - reassign From 8a50b6304d5c3dcf148f49b69a8ca19c59eb97df Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Fri, 18 Oct 2024 11:51:09 +0000 Subject: [PATCH 36/62] chore(release): 1.19.0-beta.3 ## [1.19.0-beta.3](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.2...v1.19.0-beta.3) (2024-10-18) ### Bug Fixes * Invalid code format validation :bug: ([e8383ca](https://github.com/LerianStudio/midaz/commit/e8383cac7957d1f0d63ce20f71534052ab1e8703)) * Invalid code format validation :bug: ([4dfe76c](https://github.com/LerianStudio/midaz/commit/4dfe76c1092412a129a60b09d408f71d8a59dca0)) --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa0fb7ae..9bc3254e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.19.0-beta.3](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.2...v1.19.0-beta.3) (2024-10-18) + + +### Bug Fixes + +* Invalid code format validation :bug: ([e8383ca](https://github.com/LerianStudio/midaz/commit/e8383cac7957d1f0d63ce20f71534052ab1e8703)) +* Invalid code format validation :bug: ([4dfe76c](https://github.com/LerianStudio/midaz/commit/4dfe76c1092412a129a60b09d408f71d8a59dca0)) + ## [1.19.0-beta.2](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.1...v1.19.0-beta.2) (2024-10-17) ## [1.19.0-beta.1](https://github.com/LerianStudio/midaz/compare/v1.18.0...v1.19.0-beta.1) (2024-10-17) From d4eab0c7b2b9589be42285b8c104fe66f4e791e4 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 08:52:02 -0300 Subject: [PATCH 37/62] fix (portfolio): uses parsed uuid for retrieving all :bug: --- .../internal/app/query/get-all-metadata-portfolios.go | 4 ++-- .../ledger/internal/app/query/get-all-portfolios.go | 4 ++-- components/ledger/internal/ports/http/portfolio.go | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/ledger/internal/app/query/get-all-metadata-portfolios.go b/components/ledger/internal/app/query/get-all-metadata-portfolios.go index 8720852a..895ea28f 100644 --- a/components/ledger/internal/app/query/get-all-metadata-portfolios.go +++ b/components/ledger/internal/app/query/get-all-metadata-portfolios.go @@ -16,7 +16,7 @@ import ( ) // GetAllMetadataPortfolios fetch all Portfolios from the repository -func (uc *UseCase) GetAllMetadataPortfolios(ctx context.Context, organizationID, ledgerID string, filter commonHTTP.QueryHeader) ([]*p.Portfolio, error) { +func (uc *UseCase) GetAllMetadataPortfolios(ctx context.Context, organizationID, ledgerID uuid.UUID, filter commonHTTP.QueryHeader) ([]*p.Portfolio, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving portfolios") @@ -33,7 +33,7 @@ func (uc *UseCase) GetAllMetadataPortfolios(ctx context.Context, organizationID, metadataMap[meta.EntityID] = meta.Data } - portfolios, err := uc.PortfolioRepo.ListByIDs(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuids) + portfolios, err := uc.PortfolioRepo.ListByIDs(ctx, organizationID, ledgerID, uuids) if err != nil { logger.Errorf("Error getting portfolios on repo by query params: %v", err) diff --git a/components/ledger/internal/app/query/get-all-portfolios.go b/components/ledger/internal/app/query/get-all-portfolios.go index 9387a051..a0aa83ba 100644 --- a/components/ledger/internal/app/query/get-all-portfolios.go +++ b/components/ledger/internal/app/query/get-all-portfolios.go @@ -16,11 +16,11 @@ import ( ) // GetAllPortfolio fetch all Portfolio from the repository -func (uc *UseCase) GetAllPortfolio(ctx context.Context, organizationID, ledgerID string, filter commonHTTP.QueryHeader) ([]*p.Portfolio, error) { +func (uc *UseCase) GetAllPortfolio(ctx context.Context, organizationID, ledgerID uuid.UUID, filter commonHTTP.QueryHeader) ([]*p.Portfolio, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving portfolios") - portfolios, err := uc.PortfolioRepo.FindAll(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), filter.Limit, filter.Page) + portfolios, err := uc.PortfolioRepo.FindAll(ctx, organizationID, ledgerID, filter.Limit, filter.Page) if err != nil { logger.Errorf("Error getting portfolios on repo: %v", err) diff --git a/components/ledger/internal/ports/http/portfolio.go b/components/ledger/internal/ports/http/portfolio.go index a6fa1a71..2d61df20 100644 --- a/components/ledger/internal/ports/http/portfolio.go +++ b/components/ledger/internal/ports/http/portfolio.go @@ -48,9 +48,9 @@ func (handler *PortfolioHandler) GetAllPortfolios(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - logger.Infof("Get Portfolios with Organization: %s and Ledger ID: %s", organizationID, ledgerID) + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + logger.Infof("Get Portfolios with Organization: %s and Ledger ID: %s", organizationID.String(), ledgerID.String()) headerParams := commonHTTP.ValidateParameters(c.Queries()) @@ -102,7 +102,7 @@ func (handler *PortfolioHandler) GetPortfolioByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Initiating retrieval of Portfolio with Organization: %s Ledger ID: %s and Portfolio ID: %s", organizationID, ledgerID, id) + logger.Infof("Initiating retrieval of Portfolio with Organization: %s Ledger ID: %s and Portfolio ID: %s", organizationID.String(), ledgerID.String(), id.String()) portfolio, err := handler.Query.GetPortfolioByID(ctx, organizationID, ledgerID, id) if err != nil { From a1983d3bb2fea40a0ae246e0769d63e1600923d0 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 09:03:28 -0300 Subject: [PATCH 38/62] fix (portfolio): uses parsed uuid for deleting :bug: --- .../internal/app/command/delete-portfolio.go | 6 ++--- .../ledger/internal/ports/http/portfolio.go | 24 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/components/ledger/internal/app/command/delete-portfolio.go b/components/ledger/internal/app/command/delete-portfolio.go index 518ae056..48bd6796 100644 --- a/components/ledger/internal/app/command/delete-portfolio.go +++ b/components/ledger/internal/app/command/delete-portfolio.go @@ -15,11 +15,11 @@ import ( ) // DeletePortfolioByID deletes a portfolio from the repository by ids. -func (uc *UseCase) DeletePortfolioByID(ctx context.Context, organizationID, ledgerID, id string) error { +func (uc *UseCase) DeletePortfolioByID(ctx context.Context, organizationID, ledgerID, id uuid.UUID) error { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Remove portfolio for id: %s", id) + logger.Infof("Remove portfolio for id: %s", id.String()) - if err := uc.PortfolioRepo.Delete(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id)); err != nil { + if err := uc.PortfolioRepo.Delete(ctx, organizationID, ledgerID, id); err != nil { logger.Errorf("Error deleting portfolio on repo by id: %v", err) if errors.Is(err, app.ErrDatabaseItemNotFound) { diff --git a/components/ledger/internal/ports/http/portfolio.go b/components/ledger/internal/ports/http/portfolio.go index 2d61df20..6e0c039e 100644 --- a/components/ledger/internal/ports/http/portfolio.go +++ b/components/ledger/internal/ports/http/portfolio.go @@ -106,11 +106,11 @@ func (handler *PortfolioHandler) GetPortfolioByID(c *fiber.Ctx) error { portfolio, err := handler.Query.GetPortfolioByID(ctx, organizationID, ledgerID, id) if err != nil { - logger.Errorf("Failed to retrieve Portfolio with Ledger ID: %s and Portfolio ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to retrieve Portfolio with Ledger ID: %s and Portfolio ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully retrieved Portfolio with Ledger ID: %s and Portfolio ID: %s", ledgerID, id) + logger.Infof("Successfully retrieved Portfolio with Ledger ID: %s and Portfolio ID: %s", ledgerID.String(), id.String()) return commonHTTP.OK(c, portfolio) } @@ -124,24 +124,24 @@ func (handler *PortfolioHandler) UpdatePortfolio(i any, c *fiber.Ctx) error { ledgerID := c.Locals("ledger_id").(uuid.UUID) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating update of Portfolio with Organization: %s Ledger ID: %s and Portfolio ID: %s", organizationID, ledgerID, id) + logger.Infof("Initiating update of Portfolio with Organization: %s Ledger ID: %s and Portfolio ID: %s", organizationID.String(), ledgerID.String(), id.String()) payload := i.(*p.UpdatePortfolioInput) logger.Infof("Request to update an Portfolio with details: %#v", payload) _, err := handler.Command.UpdatePortfolioByID(ctx, organizationID, ledgerID, id, payload) if err != nil { - logger.Errorf("Failed to update Portfolio with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to update Portfolio with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } portfolio, err := handler.Query.GetPortfolioByID(ctx, organizationID, ledgerID, id) if err != nil { - logger.Errorf("Failed to retrieve Portfolio with Ledger ID: %s and Portfolio ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to retrieve Portfolio with Ledger ID: %s and Portfolio ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully updated Portfolio with Ledger ID: %s and Portfolio ID: %s", ledgerID, id) + logger.Infof("Successfully updated Portfolio with Ledger ID: %s and Portfolio ID: %s", ledgerID.String(), id.String()) return commonHTTP.OK(c, portfolio) } @@ -152,18 +152,18 @@ func (handler *PortfolioHandler) DeletePortfolioByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating removal of Portfolio with Organization: %s Ledger ID: %s and Portfolio ID: %s", organizationID, ledgerID, id) + logger.Infof("Initiating removal of Portfolio with Organization: %s Ledger ID: %s and Portfolio ID: %s", organizationID.String(), ledgerID.String(), id.String()) if err := handler.Command.DeletePortfolioByID(ctx, organizationID, ledgerID, id); err != nil { - logger.Errorf("Failed to remove Portfolio with Ledger ID: %s and Portfolio ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to remove Portfolio with Ledger ID: %s and Portfolio ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully removed Portfolio with Ledger ID: %s and Portfolio ID: %s", ledgerID, id) + logger.Infof("Successfully removed Portfolio with Ledger ID: %s and Portfolio ID: %s", ledgerID.String(), id.String()) return commonHTTP.NoContent(c) } From 2a11025df5db3ec2953c0c9455f226dd32e3602c Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 09:08:38 -0300 Subject: [PATCH 39/62] fix (product): uses parsed uuid on create :bug: --- components/ledger/internal/app/command/create-product.go | 8 ++++---- components/ledger/internal/ports/http/product.go | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/components/ledger/internal/app/command/create-product.go b/components/ledger/internal/app/command/create-product.go index 449393b8..fb5a0056 100644 --- a/components/ledger/internal/app/command/create-product.go +++ b/components/ledger/internal/app/command/create-product.go @@ -13,7 +13,7 @@ import ( ) // CreateProduct creates a new product persists data in the repository. -func (uc *UseCase) CreateProduct(ctx context.Context, organizationID, ledgerID string, cpi *r.CreateProductInput) (*r.Product, error) { +func (uc *UseCase) CreateProduct(ctx context.Context, organizationID, ledgerID uuid.UUID, cpi *r.CreateProductInput) (*r.Product, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to create product: %v", cpi) @@ -28,15 +28,15 @@ func (uc *UseCase) CreateProduct(ctx context.Context, organizationID, ledgerID s product := &r.Product{ ID: uuid.New().String(), - LedgerID: ledgerID, - OrganizationID: organizationID, + LedgerID: ledgerID.String(), + OrganizationID: organizationID.String(), Name: cpi.Name, Status: status, CreatedAt: time.Now(), UpdatedAt: time.Now(), } - _, err := uc.ProductRepo.FindByName(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), cpi.Name) + _, err := uc.ProductRepo.FindByName(ctx, organizationID, ledgerID, cpi.Name) if err != nil { return nil, err } diff --git a/components/ledger/internal/ports/http/product.go b/components/ledger/internal/ports/http/product.go index 582b2d9a..6e5b1123 100644 --- a/components/ledger/internal/ports/http/product.go +++ b/components/ledger/internal/ports/http/product.go @@ -8,6 +8,7 @@ import ( "github.com/LerianStudio/midaz/components/ledger/internal/app/query" r "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/product" "github.com/gofiber/fiber/v2" + "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" ) @@ -23,9 +24,9 @@ func (handler *ProductHandler) CreateProduct(i any, c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - logger.Infof("Initiating create of Product with organization ID: %s and ledger ID: %s", organizationID, ledgerID) + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + logger.Infof("Initiating create of Product with organization ID: %s and ledger ID: %s", organizationID.String(), ledgerID.String()) payload := i.(*r.CreateProductInput) logger.Infof("Request to create a Product with details: %#v", payload) From 707be656984aaea2c839be70f6c7c17e84375866 Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 14:13:15 +0200 Subject: [PATCH 40/62] fix: remove goconst :bug: --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index e0a084c7..8bf0c234 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,7 +2,6 @@ linters: enable: - bodyclose - gocognit - - goconst - depguard - dogsled - dupword # Detects duplicate words. From c97ce38e010e864f08312a50b62dd90f02da920c Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 09:17:21 -0300 Subject: [PATCH 41/62] fix (product): uses parsed uuid on get and update :bug: --- .../internal/app/command/update-product.go | 6 ++--- .../internal/app/query/get-id-product.go | 8 +++--- .../ledger/internal/ports/http/product.go | 26 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/components/ledger/internal/app/command/update-product.go b/components/ledger/internal/app/command/update-product.go index b70cc37d..6df2284a 100644 --- a/components/ledger/internal/app/command/update-product.go +++ b/components/ledger/internal/app/command/update-product.go @@ -15,7 +15,7 @@ import ( ) // UpdateProductByID update a product from the repository by given id. -func (uc *UseCase) UpdateProductByID(ctx context.Context, organizationID, ledgerID, id string, upi *r.UpdateProductInput) (*r.Product, error) { +func (uc *UseCase) UpdateProductByID(ctx context.Context, organizationID, ledgerID, id uuid.UUID, upi *r.UpdateProductInput) (*r.Product, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to update product: %v", upi) @@ -24,7 +24,7 @@ func (uc *UseCase) UpdateProductByID(ctx context.Context, organizationID, ledger Status: upi.Status, } - productUpdated, err := uc.ProductRepo.Update(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id), product) + productUpdated, err := uc.ProductRepo.Update(ctx, organizationID, ledgerID, id, product) if err != nil { logger.Errorf("Error updating product on repo by id: %v", err) @@ -40,7 +40,7 @@ func (uc *UseCase) UpdateProductByID(ctx context.Context, organizationID, ledger return nil, common.ValidateBusinessError(err, reflect.TypeOf(r.Product{}).Name()) } - if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(r.Product{}).Name(), id, upi.Metadata); err != nil { + if err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(r.Product{}).Name(), id.String(), upi.Metadata); err != nil { return nil, err } diff --git a/components/ledger/internal/app/query/get-id-product.go b/components/ledger/internal/app/query/get-id-product.go index 2b6f355a..63747b09 100644 --- a/components/ledger/internal/app/query/get-id-product.go +++ b/components/ledger/internal/app/query/get-id-product.go @@ -15,11 +15,11 @@ import ( ) // GetProductByID get a Product from the repository by given id. -func (uc *UseCase) GetProductByID(ctx context.Context, organizationID, ledgerID, id string) (*r.Product, error) { +func (uc *UseCase) GetProductByID(ctx context.Context, organizationID, ledgerID, id uuid.UUID) (*r.Product, error) { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Retrieving product for id: %s", id) + logger.Infof("Retrieving product for id: %s", id.String()) - product, err := uc.ProductRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id)) + product, err := uc.ProductRepo.Find(ctx, organizationID, ledgerID, id) if err != nil { logger.Errorf("Error getting product on repo by id: %v", err) @@ -31,7 +31,7 @@ func (uc *UseCase) GetProductByID(ctx context.Context, organizationID, ledgerID, } if product != nil { - metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(r.Product{}).Name(), id) + metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(r.Product{}).Name(), id.String()) if err != nil { logger.Errorf("Error get metadata on mongodb product: %v", err) return nil, err diff --git a/components/ledger/internal/ports/http/product.go b/components/ledger/internal/ports/http/product.go index 6e5b1123..083419c9 100644 --- a/components/ledger/internal/ports/http/product.go +++ b/components/ledger/internal/ports/http/product.go @@ -95,18 +95,18 @@ func (handler *ProductHandler) GetProductByID(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") - logger.Infof("Initiating retrieval of Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID, ledgerID, id) + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) + logger.Infof("Initiating retrieval of Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID.String(), ledgerID.String(), id.String()) product, err := handler.Query.GetProductByID(ctx, organizationID, ledgerID, id) if err != nil { - logger.Errorf("Failed to retrieve Product with Ledger ID: %s and Product ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to retrieve Product with Ledger ID: %s and Product ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully retrieved Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID, ledgerID, id) + logger.Infof("Successfully retrieved Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID.String(), ledgerID.String(), id.String()) return commonHTTP.OK(c, product) } @@ -116,27 +116,27 @@ func (handler *ProductHandler) UpdateProduct(i any, c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") - logger.Infof("Initiating update of Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID, ledgerID, id) + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) + logger.Infof("Initiating update of Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID.String(), ledgerID.String(), id.String()) payload := i.(*r.UpdateProductInput) logger.Infof("Request to update an Product with details: %#v", payload) _, err := handler.Command.UpdateProductByID(ctx, organizationID, ledgerID, id, payload) if err != nil { - logger.Errorf("Failed to update Product with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to update Product with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } product, err := handler.Query.GetProductByID(ctx, organizationID, ledgerID, id) if err != nil { - logger.Errorf("Failed to retrieve Product with Ledger ID: %s and Product ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to retrieve Product with Ledger ID: %s and Product ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully updated Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID, ledgerID, id) + logger.Infof("Successfully updated Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID.String(), ledgerID.String(), id.String()) return commonHTTP.OK(c, product) } From 041b5286aaa2c746e79baa4b783a8d4e9eeae344 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 09:23:19 -0300 Subject: [PATCH 42/62] fix (product): uses parsed uuid for getting all :bug: --- .../ledger/internal/app/query/get-all-metadata-products.go | 4 ++-- components/ledger/internal/app/query/get-all-products.go | 4 ++-- components/ledger/internal/ports/http/product.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/ledger/internal/app/query/get-all-metadata-products.go b/components/ledger/internal/app/query/get-all-metadata-products.go index d6a63865..0b06f074 100644 --- a/components/ledger/internal/app/query/get-all-metadata-products.go +++ b/components/ledger/internal/app/query/get-all-metadata-products.go @@ -16,7 +16,7 @@ import ( ) // GetAllMetadataProducts fetch all Products from the repository -func (uc *UseCase) GetAllMetadataProducts(ctx context.Context, organizationID, ledgerID string, filter commonHTTP.QueryHeader) ([]*r.Product, error) { +func (uc *UseCase) GetAllMetadataProducts(ctx context.Context, organizationID, ledgerID uuid.UUID, filter commonHTTP.QueryHeader) ([]*r.Product, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving products") @@ -33,7 +33,7 @@ func (uc *UseCase) GetAllMetadataProducts(ctx context.Context, organizationID, l metadataMap[meta.EntityID] = meta.Data } - products, err := uc.ProductRepo.FindByIDs(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuids) + products, err := uc.ProductRepo.FindByIDs(ctx, organizationID, ledgerID, uuids) if err != nil { logger.Errorf("Error getting products on repo by query params: %v", err) diff --git a/components/ledger/internal/app/query/get-all-products.go b/components/ledger/internal/app/query/get-all-products.go index b9c670f8..9cc92a06 100644 --- a/components/ledger/internal/app/query/get-all-products.go +++ b/components/ledger/internal/app/query/get-all-products.go @@ -16,11 +16,11 @@ import ( ) // GetAllProducts fetch all Product from the repository -func (uc *UseCase) GetAllProducts(ctx context.Context, organizationID, ledgerID string, filter commonHTTP.QueryHeader) ([]*r.Product, error) { +func (uc *UseCase) GetAllProducts(ctx context.Context, organizationID, ledgerID uuid.UUID, filter commonHTTP.QueryHeader) ([]*r.Product, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving products") - products, err := uc.ProductRepo.FindAll(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), filter.Limit, filter.Page) + products, err := uc.ProductRepo.FindAll(ctx, organizationID, ledgerID, filter.Limit, filter.Page) if err != nil { logger.Errorf("Error getting products on repo: %v", err) diff --git a/components/ledger/internal/ports/http/product.go b/components/ledger/internal/ports/http/product.go index 083419c9..0d6839d0 100644 --- a/components/ledger/internal/ports/http/product.go +++ b/components/ledger/internal/ports/http/product.go @@ -46,9 +46,9 @@ func (handler *ProductHandler) GetAllProducts(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - logger.Infof("Get Products with organization ID: %s and ledger ID: %s", organizationID, ledgerID) + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + logger.Infof("Get Products with organization ID: %s and ledger ID: %s", organizationID.String(), ledgerID.String()) headerParams := commonHTTP.ValidateParameters(c.Queries()) From 35f7ed40519cb815299273520302a2d28958f949 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 09:26:32 -0300 Subject: [PATCH 43/62] fix (product): uses parsed uuid on delete :bug: --- .../ledger/internal/app/command/delete-product.go | 6 +++--- components/ledger/internal/ports/http/product.go | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/components/ledger/internal/app/command/delete-product.go b/components/ledger/internal/app/command/delete-product.go index 8a9208e0..2ccae86b 100644 --- a/components/ledger/internal/app/command/delete-product.go +++ b/components/ledger/internal/app/command/delete-product.go @@ -15,11 +15,11 @@ import ( ) // DeleteProductByID delete a product from the repository by ids. -func (uc *UseCase) DeleteProductByID(ctx context.Context, organizationID, ledgerID, id string) error { +func (uc *UseCase) DeleteProductByID(ctx context.Context, organizationID, ledgerID, id uuid.UUID) error { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Remove product for id: %s", id) + logger.Infof("Remove product for id: %s", id.String()) - if err := uc.ProductRepo.Delete(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id)); err != nil { + if err := uc.ProductRepo.Delete(ctx, organizationID, ledgerID, id); err != nil { logger.Errorf("Error deleting product on repo by id: %v", err) if errors.Is(err, app.ErrDatabaseItemNotFound) { diff --git a/components/ledger/internal/ports/http/product.go b/components/ledger/internal/ports/http/product.go index 0d6839d0..02eeac3c 100644 --- a/components/ledger/internal/ports/http/product.go +++ b/components/ledger/internal/ports/http/product.go @@ -147,18 +147,18 @@ func (handler *ProductHandler) DeleteProductByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating removal of Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID, ledgerID, id) + logger.Infof("Initiating removal of Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID.String(), ledgerID.String(), id.String()) if err := handler.Command.DeleteProductByID(ctx, organizationID, ledgerID, id); err != nil { - logger.Errorf("Failed to remove Product with Ledger ID: %s and Product ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to remove Product with Ledger ID: %s and Product ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully removed Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID, ledgerID, id) + logger.Infof("Successfully removed Product with Organization ID: %s and Ledger ID: %s and Product ID: %s", organizationID.String(), ledgerID.String(), id.String()) return commonHTTP.NoContent(c) } From 2a00555386b9b5b52a35aa6ed7fd17000a3d10cf Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 09:55:52 -0300 Subject: [PATCH 44/62] fix (account): uses parsed uuid on creation :bug: --- .../ledger/internal/app/command/create-account.go | 14 +++++++------- components/ledger/internal/ports/http/account.go | 9 +++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/components/ledger/internal/app/command/create-account.go b/components/ledger/internal/app/command/create-account.go index e6169353..43067248 100644 --- a/components/ledger/internal/app/command/create-account.go +++ b/components/ledger/internal/app/command/create-account.go @@ -15,7 +15,7 @@ import ( ) // CreateAccount creates a new account persists data in the repository. -func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, portfolioID string, cai *a.CreateAccountInput) (*a.Account, error) { +func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, cai *a.CreateAccountInput) (*a.Account, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to create account: %v", cai) @@ -47,7 +47,7 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, } if cai.EntityID == nil { - portfolio, err := uc.PortfolioRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID)) + portfolio, err := uc.PortfolioRepo.Find(ctx, organizationID, ledgerID, portfolioID) if err != nil { logger.Errorf("Error find portfolio to get Entity ID: %v", err) return nil, err @@ -57,7 +57,7 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, } if !common.IsNilOrEmpty(cai.ParentAccountID) { - acc, err := uc.AccountRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), uuid.MustParse(*cai.ParentAccountID)) + acc, err := uc.AccountRepo.Find(ctx, organizationID, ledgerID, portfolioID, uuid.MustParse(*cai.ParentAccountID)) if err != nil { return nil, err } @@ -68,7 +68,7 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, } if !common.IsNilOrEmpty(cai.Alias) { - _, err := uc.AccountRepo.FindByAlias(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), *cai.Alias) + _, err := uc.AccountRepo.FindByAlias(ctx, organizationID, ledgerID, portfolioID, *cai.Alias) if err != nil { return nil, err } @@ -82,9 +82,9 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, Type: cai.Type, ParentAccountID: cai.ParentAccountID, ProductID: cai.ProductID, - OrganizationID: organizationID, - PortfolioID: portfolioID, - LedgerID: ledgerID, + OrganizationID: organizationID.String(), + PortfolioID: portfolioID.String(), + LedgerID: ledgerID.String(), EntityID: *cai.EntityID, Balance: balance, Status: status, diff --git a/components/ledger/internal/ports/http/account.go b/components/ledger/internal/ports/http/account.go index 0e4d1311..09514d25 100644 --- a/components/ledger/internal/ports/http/account.go +++ b/components/ledger/internal/ports/http/account.go @@ -8,6 +8,7 @@ import ( "github.com/LerianStudio/midaz/components/ledger/internal/app/query" a "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account" "github.com/gofiber/fiber/v2" + "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" ) @@ -22,11 +23,11 @@ func (handler *AccountHandler) CreateAccount(i any, c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - portfolioID := c.Params("portfolio_id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + portfolioID := c.Locals("portfolio_id").(uuid.UUID) - logger.Infof("Initiating create of Account with Portfolio ID: %s", portfolioID) + logger.Infof("Initiating create of Account with Portfolio ID: %s", portfolioID.String()) payload := i.(*a.CreateAccountInput) logger.Infof("Request to create a Account with details: %#v", payload) From 991e9dfe57b7af5689f065f47fa1ed18753244f2 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 10:01:53 -0300 Subject: [PATCH 45/62] fix (account): uses parsed uuid on update :bug: --- .../ledger/internal/app/command/update-account.go | 6 +++--- components/ledger/internal/ports/http/account.go | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/ledger/internal/app/command/update-account.go b/components/ledger/internal/app/command/update-account.go index 03cbd339..007385bb 100644 --- a/components/ledger/internal/app/command/update-account.go +++ b/components/ledger/internal/app/command/update-account.go @@ -15,7 +15,7 @@ import ( ) // UpdateAccount update an account from the repository by given id. -func (uc *UseCase) UpdateAccount(ctx context.Context, organizationID, ledgerID, portfolioID, id string, uai *a.UpdateAccountInput) (*a.Account, error) { +func (uc *UseCase) UpdateAccount(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID, uai *a.UpdateAccountInput) (*a.Account, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to update account: %v", uai) @@ -31,7 +31,7 @@ func (uc *UseCase) UpdateAccount(ctx context.Context, organizationID, ledgerID, Metadata: uai.Metadata, } - accountUpdated, err := uc.AccountRepo.Update(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), uuid.MustParse(id), account) + accountUpdated, err := uc.AccountRepo.Update(ctx, organizationID, ledgerID, portfolioID, id, account) if err != nil { logger.Errorf("Error updating account on repo by id: %v", err) @@ -47,7 +47,7 @@ func (uc *UseCase) UpdateAccount(ctx context.Context, organizationID, ledgerID, return nil, common.ValidateBusinessError(err, reflect.TypeOf(a.Account{}).Name()) } - err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(a.Account{}).Name(), id, uai.Metadata) + err := uc.MetadataRepo.Update(ctx, reflect.TypeOf(a.Account{}).Name(), id.String(), uai.Metadata) if err != nil { return nil, err } diff --git a/components/ledger/internal/ports/http/account.go b/components/ledger/internal/ports/http/account.go index 09514d25..4eb3a244 100644 --- a/components/ledger/internal/ports/http/account.go +++ b/components/ledger/internal/ports/http/account.go @@ -122,23 +122,23 @@ func (handler *AccountHandler) UpdateAccount(i any, c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - portfolioID := c.Params("portfolio_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + portfolioID := c.Locals("portfolio_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating update of Account with Portfolio ID: %s and Account ID: %s", portfolioID, id) + logger.Infof("Initiating update of Account with Portfolio ID: %s and Account ID: %s", portfolioID.String(), id.String()) payload := i.(*a.UpdateAccountInput) logger.Infof("Request to update an Account with details: %#v", payload) account, err := handler.Command.UpdateAccount(ctx, organizationID, ledgerID, portfolioID, id, payload) if err != nil { - logger.Errorf("Failed to update Account with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to update Account with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully updated Account with Portfolio ID: %s and Account ID: %s", portfolioID, id) + logger.Infof("Successfully updated Account with Portfolio ID: %s and Account ID: %s", portfolioID.String(), id.String()) return commonHTTP.OK(c, account) } From b3b40f604aed52395cdc21bf9f22f80426876b6c Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 10:12:47 -0300 Subject: [PATCH 46/62] fix (account): uses parsed uuid for retrieving all :bug: --- components/ledger/internal/app/query/get-all-accounts.go | 4 ++-- .../internal/app/query/get-all-metadata-accounts.go | 4 ++-- components/ledger/internal/ports/http/account.go | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/ledger/internal/app/query/get-all-accounts.go b/components/ledger/internal/app/query/get-all-accounts.go index 1f9a951d..d21ecb25 100644 --- a/components/ledger/internal/app/query/get-all-accounts.go +++ b/components/ledger/internal/app/query/get-all-accounts.go @@ -16,11 +16,11 @@ import ( ) // GetAllAccount fetch all Account from the repository -func (uc *UseCase) GetAllAccount(ctx context.Context, organizationID, ledgerID, portfolioID string, filter commonHTTP.QueryHeader) ([]*a.Account, error) { +func (uc *UseCase) GetAllAccount(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, filter commonHTTP.QueryHeader) ([]*a.Account, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving accounts") - accounts, err := uc.AccountRepo.FindAll(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), filter.Limit, filter.Page) + accounts, err := uc.AccountRepo.FindAll(ctx, organizationID, ledgerID, portfolioID, filter.Limit, filter.Page) if err != nil { logger.Errorf("Error getting accounts on repo: %v", err) diff --git a/components/ledger/internal/app/query/get-all-metadata-accounts.go b/components/ledger/internal/app/query/get-all-metadata-accounts.go index 56b9ee6b..b4fbf53f 100644 --- a/components/ledger/internal/app/query/get-all-metadata-accounts.go +++ b/components/ledger/internal/app/query/get-all-metadata-accounts.go @@ -16,7 +16,7 @@ import ( ) // GetAllMetadataAccounts fetch all Accounts from the repository -func (uc *UseCase) GetAllMetadataAccounts(ctx context.Context, organizationID, ledgerID, portfolioID string, filter commonHTTP.QueryHeader) ([]*a.Account, error) { +func (uc *UseCase) GetAllMetadataAccounts(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, filter commonHTTP.QueryHeader) ([]*a.Account, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving accounts") @@ -33,7 +33,7 @@ func (uc *UseCase) GetAllMetadataAccounts(ctx context.Context, organizationID, l metadataMap[meta.EntityID] = meta.Data } - accounts, err := uc.AccountRepo.ListByIDs(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), uuids) + accounts, err := uc.AccountRepo.ListByIDs(ctx, organizationID, ledgerID, portfolioID, uuids) if err != nil { logger.Errorf("Error getting accounts on repo by query params: %v", err) diff --git a/components/ledger/internal/ports/http/account.go b/components/ledger/internal/ports/http/account.go index 4eb3a244..e678235d 100644 --- a/components/ledger/internal/ports/http/account.go +++ b/components/ledger/internal/ports/http/account.go @@ -47,11 +47,11 @@ func (handler *AccountHandler) GetAllAccounts(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - portfolioID := c.Params("portfolio_id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + portfolioID := c.Locals("portfolio_id").(uuid.UUID) - logger.Infof("Get Accounts with Portfolio ID: %s", portfolioID) + logger.Infof("Get Accounts with Portfolio ID: %s", portfolioID.String()) headerParams := commonHTTP.ValidateParameters(c.Queries()) From 4d22c8c5be0f6498c5305ed01e1121efbe4e8987 Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 15:41:41 +0200 Subject: [PATCH 47/62] fix: go sec and lint; :bug: --- components/ledger/internal/app/command/create-account.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/ledger/internal/app/command/create-account.go b/components/ledger/internal/app/command/create-account.go index 7fbee04a..0c19b857 100644 --- a/components/ledger/internal/app/command/create-account.go +++ b/components/ledger/internal/app/command/create-account.go @@ -23,10 +23,6 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, cai.Name = cai.AssetCode + " " + cai.Type + " account" } - if common.IsNilOrEmpty(cai.Alias) { - cai.Alias = nil - } - var status a.Status if cai.Status.IsEmpty() { status = a.Status{ From aea4d466bf5edd441bcced5c8bae4cbdcc4cbf8e Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 10:42:04 -0300 Subject: [PATCH 48/62] fix (account): uses parsed uuid for retrieving by id :bug: --- .../ledger/internal/app/query/get-id-account.go | 6 +++--- components/ledger/internal/ports/http/account.go | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/ledger/internal/app/query/get-id-account.go b/components/ledger/internal/app/query/get-id-account.go index 58bf4ede..35558bd1 100644 --- a/components/ledger/internal/app/query/get-id-account.go +++ b/components/ledger/internal/app/query/get-id-account.go @@ -15,11 +15,11 @@ import ( ) // GetAccountByID get an Account from the repository by given id. -func (uc *UseCase) GetAccountByID(ctx context.Context, organizationID, ledgerID, portfolioID, id string) (*a.Account, error) { +func (uc *UseCase) GetAccountByID(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID) (*a.Account, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Retrieving account for id: %s", id) - account, err := uc.AccountRepo.Find(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), uuid.MustParse(id)) + account, err := uc.AccountRepo.Find(ctx, organizationID, ledgerID, portfolioID, id) if err != nil { logger.Errorf("Error getting account on repo by id: %v", err) @@ -31,7 +31,7 @@ func (uc *UseCase) GetAccountByID(ctx context.Context, organizationID, ledgerID, } if account != nil { - metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(a.Account{}).Name(), id) + metadata, err := uc.MetadataRepo.FindByEntity(ctx, reflect.TypeOf(a.Account{}).Name(), id.String()) if err != nil { logger.Errorf("Error get metadata on mongodb account: %v", err) return nil, err diff --git a/components/ledger/internal/ports/http/account.go b/components/ledger/internal/ports/http/account.go index e678235d..ebb8ed32 100644 --- a/components/ledger/internal/ports/http/account.go +++ b/components/ledger/internal/ports/http/account.go @@ -97,22 +97,22 @@ func (handler *AccountHandler) GetAllAccounts(c *fiber.Ctx) error { func (handler *AccountHandler) GetAccountByID(c *fiber.Ctx) error { ctx := c.UserContext() - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - portfolioID := c.Params("portfolio_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + portfolioID := c.Locals("portfolio_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Initiating retrieval of Account with Portfolio ID: %s and Account ID: %s", portfolioID, id) + logger.Infof("Initiating retrieval of Account with Portfolio ID: %s and Account ID: %s", portfolioID.String(), id.String()) account, err := handler.Query.GetAccountByID(ctx, organizationID, ledgerID, portfolioID, id) if err != nil { - logger.Errorf("Failed to retrieve Account with Portfolio ID: %s and Account ID: %s, Error: %s", portfolioID, id, err.Error()) + logger.Errorf("Failed to retrieve Account with Portfolio ID: %s and Account ID: %s, Error: %s", portfolioID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully retrieved Account with Portfolio ID: %s and Account ID: %s", portfolioID, id) + logger.Infof("Successfully retrieved Account with Portfolio ID: %s and Account ID: %s", portfolioID.String(), id.String()) return commonHTTP.OK(c, account) } From d84ac6135bc921d9df46dc878db4f00288305755 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 10:45:50 -0300 Subject: [PATCH 49/62] fix (account): uses parsed uuid on delete :bug: --- .../ledger/internal/app/command/delete-account.go | 6 +++--- components/ledger/internal/ports/http/account.go | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/ledger/internal/app/command/delete-account.go b/components/ledger/internal/app/command/delete-account.go index 980dc540..09cf28a1 100644 --- a/components/ledger/internal/app/command/delete-account.go +++ b/components/ledger/internal/app/command/delete-account.go @@ -15,11 +15,11 @@ import ( ) // DeleteAccountByID delete an account from the repository by ids. -func (uc *UseCase) DeleteAccountByID(ctx context.Context, organizationID, ledgerID, portfolioID, id string) error { +func (uc *UseCase) DeleteAccountByID(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID) error { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Remove account for id: %s", id) + logger.Infof("Remove account for id: %s", id.String()) - if err := uc.AccountRepo.Delete(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(portfolioID), uuid.MustParse(id)); err != nil { + if err := uc.AccountRepo.Delete(ctx, organizationID, ledgerID, portfolioID, id); err != nil { logger.Errorf("Error deleting account on repo by id: %v", err) if errors.Is(err, app.ErrDatabaseItemNotFound) { diff --git a/components/ledger/internal/ports/http/account.go b/components/ledger/internal/ports/http/account.go index ebb8ed32..6de214d4 100644 --- a/components/ledger/internal/ports/http/account.go +++ b/components/ledger/internal/ports/http/account.go @@ -148,19 +148,19 @@ func (handler *AccountHandler) DeleteAccountByID(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - ledgerID := c.Params("ledger_id") - portfolioID := c.Params("portfolio_id") - id := c.Params("id") + organizationID := c.Locals("organization_id").(uuid.UUID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + portfolioID := c.Locals("portfolio_id").(uuid.UUID) + id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating removal of Account with Portfolio ID: %s and Account ID: %s", portfolioID, id) + logger.Infof("Initiating removal of Account with Portfolio ID: %s and Account ID: %s", portfolioID.String(), id.String()) if err := handler.Command.DeleteAccountByID(ctx, organizationID, ledgerID, portfolioID, id); err != nil { - logger.Errorf("Failed to remove Account with Portfolio ID: %s and Account ID: %s, Error: %s", portfolioID, id, err.Error()) + logger.Errorf("Failed to remove Account with Portfolio ID: %s and Account ID: %s, Error: %s", portfolioID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully removed Account with Portfolio ID: %s and Account ID: %s", portfolioID, id) + logger.Infof("Successfully removed Account with Portfolio ID: %s and Account ID: %s", portfolioID.String(), id.String()) return commonHTTP.NoContent(c) } From c4ed7e3f3f27110d2dd99f6492bac5edd1809036 Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 16:20:26 +0200 Subject: [PATCH 50/62] refactor: update postman :hammer: --- postman/MIDAZ.postman_collection.json | 489 ++++++++++++-------------- 1 file changed, 231 insertions(+), 258 deletions(-) diff --git a/postman/MIDAZ.postman_collection.json b/postman/MIDAZ.postman_collection.json index 5047f0e0..fd22513e 100644 --- a/postman/MIDAZ.postman_collection.json +++ b/postman/MIDAZ.postman_collection.json @@ -1,10 +1,10 @@ { "info": { - "_postman_id": "34212af8-3dc4-49f9-87e1-01da185da3d2", + "_postman_id": "78088a93-9c50-492b-a84f-c47ab92f4911", "name": "MIDAZ", - "description": "## **How generate token to use on MIDAZ \n \n**\n\n\n\n\n\n\n\n\n\n", + "description": "## **How generate token to use on MIDAZ**\n\n\n\n\n\n\n\n\n\n", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "38753084" + "_exporter_id": "32592108" }, "item": [ { @@ -1709,11 +1709,66 @@ { "name": "Transaction", "item": [ + { + "name": "Transaction JSON", + "item": [ + { + "name": "Transaction", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const jsonData = JSON.parse(responseBody);", + "if (jsonData.hasOwnProperty('id')) {", + " console.log(\"transaction_id before: \" + pm.collectionVariables.get(\"transaction_id\"));", + " pm.collectionVariables.set(\"transaction_id\", jsonData.id);", + " console.log(\"transaction_id after: \" + pm.collectionVariables.get(\"transaction_id\"));", + "}" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"chartOfAccountsGroupName\": \"PAG_CONTAS_CODE_1\",\n \"description\": \"description for the transaction mcgregor to jeff value of 100 reais\",\n \"metadata\": {\n \"mensagem\": \"pagamento\",\n \"valor\": \"100\"\n },\n \"send\": {\n \"asset\": \"BRL\",\n \"value\": \"100\",\n \"scale\": \"1\",\n \"source\": {\n \"from\": [\n {\n \"account\": \"@mcgregor\",\n \"amount\": {\n \"asset\": \"BRL\",\n \"value\": \"100\",\n \"scale\": \"1\"\n },\n \"share\": {},\n \"description\": \"pagamento de emprestimo jeff e teste de devolucao\",\n \"chartOfAccountsG\": \"\",\n \"metadata\": {\n \"1\": \"m\",\n \"Cpf\": \"43049498x\"\n },\n \"isFrom\": true\n }\n ],\n \"source\": {}\n }\n },\n \"distribute\": {\n \"to\": [\n {\n \"account\": \"@jeff\",\n \"amount\": {},\n \"share\": {\n \"percentage\": 50\n },\n \"chartOfAccountsG\": \"\",\n \"metadata\": {\n \"mensagem\": \"tks\"\n }\n },\n {\n \"account\": \"@wallet_46631173\",\n \"amount\": {},\n \"share\": {\n \"percentage\": 35\n },\n \"chartOfAccountsG\": \"\"\n },\n {\n \"account\": \"@wallet_03621341\",\n \"amount\": {},\n \"share\": {},\n \"remaining\": \"remaining\",\n \"chartOfAccountsG\": \"\"\n }\n ],\n \"distribute\": {}\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/json", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "transactions", + "json" + ] + }, + "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." + }, + "response": [] + } + ] + }, { "name": "Transaction DSL", "item": [ { - "name": "Transactions DSL", + "name": "Transaction", "event": [ { "listen": "test", @@ -1753,47 +1808,12 @@ "key": "dsl", "description": "test 1", "type": "file", - "src": "postman-cloud:///1ef2418e-2c63-43f0-8b92-4d38a5dd8157" - }, - { - "key": "dsl", - "description": "ok", - "type": "file", - "src": [], - "disabled": true - }, - { - "key": "dsl", - "description": "empty", - "type": "file", - "src": [], - "disabled": true - }, - { - "key": "dsl", - "description": "error", - "type": "file", - "src": [], - "disabled": true - }, - { - "key": "dsl", - "description": "wrong extension", - "type": "file", - "src": [], - "disabled": true - }, - { - "key": "dsl", - "description": "template", - "type": "file", - "src": [], - "disabled": true + "src": "/Users/mcgregor/Documents/LERIAND/POSTMAN/examples/mcgregor-to-jeff.gold" } ] }, "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions", + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/dsl", "host": [ "{{url_transaction}}" ], @@ -1803,7 +1823,8 @@ "{{organization_id}}", "ledgers", "{{ledger_id}}", - "transactions" + "transactions", + "dsl" ] }, "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." @@ -1816,7 +1837,7 @@ "name": "Transaction Template", "item": [ { - "name": "transactions Template", + "name": "Transaction", "event": [ { "listen": "test", @@ -1847,7 +1868,7 @@ } }, "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions", + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/templates", "host": [ "{{url_transaction}}" ], @@ -1857,7 +1878,8 @@ "{{organization_id}}", "ledgers", "{{ledger_id}}", - "transactions" + "transactions", + "templates" ] }, "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." @@ -2024,210 +2046,6 @@ } ] }, - { - "name": "Transaction JSON", - "item": [ - { - "name": "Transactions Body", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "const jsonData = JSON.parse(responseBody);", - "if (jsonData.hasOwnProperty('id')) {", - " console.log(\"transaction_id before: \" + pm.collectionVariables.get(\"transaction_id\"));", - " pm.collectionVariables.set(\"transaction_id\", jsonData.id);", - " console.log(\"transaction_id after: \" + pm.collectionVariables.get(\"transaction_id\"));", - "}" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"transactionTypeCode\": \"PIX_OUT\",\n \"variables\": {\n \"amount\": 100,\n \"source\": \"@gabriel\",\n \"fee\": 1\n },\n \"metadata\": {\n \"anyKey\": \"anyValue\",\n \"anotherKey\": \"anotherValue\"\n },\n \"parentTransactionId\": null,\n \"description\": \"My first transaction using Midaz!\", //optional\n \"inheritMetadata\": false,\n \"inheritDescription\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "transactions" - ] - }, - "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." - }, - "response": [] - } - ] - }, - { - "name": "Operations", - "item": [ - { - "name": "Operations by account", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/accounts/{{account_id}}/operations", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "accounts", - "{{account_id}}", - "operations" - ] - } - }, - "response": [] - }, - { - "name": "Operation by account", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/accounts/{{account_id}}/operations/{{operation_id}}", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "accounts", - "{{account_id}}", - "operations", - "{{operation_id}}" - ] - } - }, - "response": [] - }, - { - "name": "Operations by portfolio", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/portfolios/{{portfolio_id}}/operations", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "portfolios", - "{{portfolio_id}}", - "operations" - ] - } - }, - "response": [] - }, - { - "name": "Operation by portfolio", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/portfolios/{{portfolio_id}}/operations/{{operation_id}}", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "portfolios", - "{{portfolio_id}}", - "operations", - "{{operation_id}}" - ] - } - }, - "response": [] - }, - { - "name": "operations", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "PATCH", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"description\": \"description for the transaction mcgregor to jeff value of 100 reais\",\n \"metadata\": {\n \"mensagem\": \"pagamento\",\n \"valor\": \"100\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/{{transaction_id}}/operations/{{operation_id}}", - "host": [ - "{{url_transaction}}" - ], - "path": [ - "v1", - "organizations", - "{{organization_id}}", - "ledgers", - "{{ledger_id}}", - "transactions", - "{{transaction_id}}", - "operations", - "{{operation_id}}" - ] - }, - "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." - }, - "response": [] - } - ] - }, { "name": "transactions", "event": [ @@ -2319,6 +2137,156 @@ "response": [] } ] + }, + { + "name": "Operations", + "item": [ + { + "name": "operations", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"description\": \"description for the transaction mcgregor to jeff value of 100 reais\",\n \"metadata\": {\n \"mensagem\": \"pagamento\",\n \"valor\": \"100\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/transactions/{{transaction_id}}/operations/{{operation_id}}", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "transactions", + "{{transaction_id}}", + "operations", + "{{operation_id}}" + ] + }, + "description": "This is a POST request, submitting data to an API via the request body. This request submits JSON data, and the data is reflected in the response.\n\nA successful POST request typically returns a `200 OK` or `201 Created` response code." + }, + "response": [] + }, + { + "name": "Account -> Operations", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/accounts/{{account_id}}/operations", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "accounts", + "{{account_id}}", + "operations" + ] + } + }, + "response": [] + }, + { + "name": "Accounts -> Operation by id", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/accounts/{{account_id}}/operations/{{operation_id}}", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "accounts", + "{{account_id}}", + "operations", + "{{operation_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Portofolios -> Operations", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/portfolios/{{portfolio_id}}/operations", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "portfolios", + "{{portfolio_id}}", + "operations" + ] + } + }, + "response": [] + }, + { + "name": "Portfolios -> Operation by id", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{url_transaction}}/v1/organizations/{{organization_id}}/ledgers/{{ledger_id}}/portfolios/{{portfolio_id}}/operations/{{operation_id}}", + "host": [ + "{{url_transaction}}" + ], + "path": [ + "v1", + "organizations", + "{{organization_id}}", + "ledgers", + "{{ledger_id}}", + "portfolios", + "{{portfolio_id}}", + "operations", + "{{operation_id}}" + ] + } + }, + "response": [] + } + ] } ], "auth": { @@ -2422,6 +2390,16 @@ } ], "variable": [ + { + "key": "client_secret", + "value": "dd03f916cacf4a98c6a413d9c38ba102dce436a9", + "type": "default" + }, + { + "key": "client_id", + "value": "9670e0ca55a29a466d31", + "type": "default" + }, { "key": "url_auth", "value": "http://127.0.0.1:8000", @@ -2434,7 +2412,7 @@ }, { "key": "url_transaction", - "value": "http://127.0.0.1:3003", + "value": "http://127.0.0.1:3005", "type": "default" }, { @@ -2473,14 +2451,9 @@ "type": "default" }, { - "key": "client_id", - "value": "9670e0ca55a29a466d31", - "type": "default" - }, - { - "key": "client_secret", - "value": "dd03f916cacf4a98c6a413d9c38ba102dce436a9", - "type": "default" + "key": "operation_id", + "value": "", + "type": "string" } ] } \ No newline at end of file From b6cef8192df96eab16a5917ab376e9d1d8be70ca Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 11:22:09 -0300 Subject: [PATCH 51/62] fix (organization): uuid logging format :bug: --- .../internal/app/query/get-id-organization.go | 2 +- .../internal/ports/http/organization.go | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/components/ledger/internal/app/query/get-id-organization.go b/components/ledger/internal/app/query/get-id-organization.go index 3cee27a9..2a938306 100644 --- a/components/ledger/internal/app/query/get-id-organization.go +++ b/components/ledger/internal/app/query/get-id-organization.go @@ -17,7 +17,7 @@ import ( // GetOrganizationByID fetch a new organization from the repository func (uc *UseCase) GetOrganizationByID(ctx context.Context, id uuid.UUID) (*o.Organization, error) { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Retrieving organization for id: %s", id) + logger.Infof("Retrieving organization for id: %s", id.String()) organization, err := uc.OrganizationRepo.Find(ctx, id) if err != nil { diff --git a/components/ledger/internal/ports/http/organization.go b/components/ledger/internal/ports/http/organization.go index 9d5b6080..3a8931f9 100644 --- a/components/ledger/internal/ports/http/organization.go +++ b/components/ledger/internal/ports/http/organization.go @@ -50,24 +50,24 @@ func (handler *OrganizationHandler) UpdateOrganization(p any, c *fiber.Ctx) erro logger := mlog.NewLoggerFromContext(ctx) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating update of Organization with ID: %s", id) + logger.Infof("Initiating update of Organization with ID: %s", id.String()) payload := p.(*o.UpdateOrganizationInput) logger.Infof("Request to update an organization with details: %#v", payload) _, err := handler.Command.UpdateOrganizationByID(ctx, id, payload) if err != nil { - logger.Errorf("Failed to update Organization with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to update Organization with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } organizations, err := handler.Query.GetOrganizationByID(ctx, id) if err != nil { - logger.Errorf("Failed to retrieve Organization with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to retrieve Organization with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully updated Organization with ID: %s", id) + logger.Infof("Successfully updated Organization with ID: %s", id.String()) return commonHTTP.OK(c, organizations) } @@ -80,15 +80,15 @@ func (handler *OrganizationHandler) GetOrganizationByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Initiating retrieval of Organization with ID: %s", id) + logger.Infof("Initiating retrieval of Organization with ID: %s", id.String()) organizations, err := handler.Query.GetOrganizationByID(ctx, id) if err != nil { - logger.Errorf("Failed to retrieve Organization with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to retrieve Organization with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully retrieved Organization with ID: %s", id) + logger.Infof("Successfully retrieved Organization with ID: %s", id.String()) return commonHTTP.OK(c, organizations) } @@ -145,10 +145,10 @@ func (handler *OrganizationHandler) DeleteOrganizationByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating removal of Organization with ID: %s", id) + logger.Infof("Initiating removal of Organization with ID: %s", id.String()) if os.Getenv("ENV_NAME") == "production" { - logger.Errorf("Failed to remove Organization with ID: %s in ", id) + logger.Errorf("Failed to remove Organization with ID: %s in ", id.String()) err := common.ValidateBusinessError(cn.ErrActionNotPermitted, reflect.TypeOf(o.Organization{}).Name()) @@ -156,11 +156,11 @@ func (handler *OrganizationHandler) DeleteOrganizationByID(c *fiber.Ctx) error { } if err := handler.Command.DeleteOrganizationByID(ctx, id); err != nil { - logger.Errorf("Failed to remove Organization with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to remove Organization with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully removed Organization with ID: %s", id) + logger.Infof("Successfully removed Organization with ID: %s", id.String()) return commonHTTP.NoContent(c) } From 40d1bbd7f54c85aaab279e36754274df93d12a34 Mon Sep 17 00:00:00 2001 From: Andre Russowsky Date: Fri, 18 Oct 2024 11:23:06 -0300 Subject: [PATCH 52/62] feat: require code :sparkles: --- components/ledger/internal/domain/portfolio/asset/asset.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ledger/internal/domain/portfolio/asset/asset.go b/components/ledger/internal/domain/portfolio/asset/asset.go index 1cdc6c2b..c4bc53cc 100644 --- a/components/ledger/internal/domain/portfolio/asset/asset.go +++ b/components/ledger/internal/domain/portfolio/asset/asset.go @@ -27,7 +27,7 @@ type AssetPostgreSQLModel struct { type CreateAssetInput struct { Name string `json:"name"` Type string `json:"type"` - Code string `json:"code"` + Code string `json:"code" validate:"required"` Status Status `json:"status"` Metadata map[string]any `json:"metadata"` } From de899e14585b58500043f6534697e4beb780fc85 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 11:27:53 -0300 Subject: [PATCH 53/62] fix (ledger): uuid logging format :bug: --- .../internal/app/command/delete-ledger.go | 2 +- .../internal/app/query/get-id-ledger.go | 2 +- .../ledger/internal/ports/http/ledger.go | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components/ledger/internal/app/command/delete-ledger.go b/components/ledger/internal/app/command/delete-ledger.go index 18edc866..d2e4bdcd 100644 --- a/components/ledger/internal/app/command/delete-ledger.go +++ b/components/ledger/internal/app/command/delete-ledger.go @@ -17,7 +17,7 @@ import ( // DeleteLedgerByID deletes a ledger from the repository func (uc *UseCase) DeleteLedgerByID(ctx context.Context, organizationID, id uuid.UUID) error { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Remove ledger for id: %s", id) + logger.Infof("Remove ledger for id: %s", id.String()) if err := uc.LedgerRepo.Delete(ctx, organizationID, id); err != nil { logger.Errorf("Error deleting ledger on repo by id: %v", err) diff --git a/components/ledger/internal/app/query/get-id-ledger.go b/components/ledger/internal/app/query/get-id-ledger.go index e723f804..c47bfa75 100644 --- a/components/ledger/internal/app/query/get-id-ledger.go +++ b/components/ledger/internal/app/query/get-id-ledger.go @@ -17,7 +17,7 @@ import ( // GetLedgerByID Get a ledger from the repository by given id. func (uc *UseCase) GetLedgerByID(ctx context.Context, organizationID, id uuid.UUID) (*l.Ledger, error) { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Retrieving ledger for id: %s", id) + logger.Infof("Retrieving ledger for id: %s", id.String()) ledger, err := uc.LedgerRepo.Find(ctx, organizationID, id) if err != nil { diff --git a/components/ledger/internal/ports/http/ledger.go b/components/ledger/internal/ports/http/ledger.go index 6aa4cdf7..bd58c169 100644 --- a/components/ledger/internal/ports/http/ledger.go +++ b/components/ledger/internal/ports/http/ledger.go @@ -53,17 +53,17 @@ func (handler *LedgerHandler) GetLedgerByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating retrieval of Ledger with ID: %s", id) + logger.Infof("Initiating retrieval of Ledger with ID: %s", id.String()) organizationID := c.Locals("organization_id").(uuid.UUID) ledger, err := handler.Query.GetLedgerByID(ctx, organizationID, id) if err != nil { - logger.Errorf("Failed to retrieve Ledger with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to retrieve Ledger with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully retrieved Ledger with ID: %s", id) + logger.Infof("Successfully retrieved Ledger with ID: %s", id.String()) return commonHTTP.OK(c, ledger) } @@ -121,7 +121,7 @@ func (handler *LedgerHandler) UpdateLedger(p any, c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating update of Ledger with ID: %s", id) + logger.Infof("Initiating update of Ledger with ID: %s", id.String()) organizationID := c.Locals("organization_id").(uuid.UUID) @@ -130,17 +130,17 @@ func (handler *LedgerHandler) UpdateLedger(p any, c *fiber.Ctx) error { _, err := handler.Command.UpdateLedgerByID(ctx, organizationID, id, payload) if err != nil { - logger.Errorf("Failed to update Ledger with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to update Ledger with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } ledger, err := handler.Query.GetLedgerByID(ctx, organizationID, id) if err != nil { - logger.Errorf("Failed to retrieve Ledger with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to retrieve Ledger with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully updated Ledger with ID: %s", id) + logger.Infof("Successfully updated Ledger with ID: %s", id.String()) return commonHTTP.OK(c, ledger) } @@ -152,12 +152,12 @@ func (handler *LedgerHandler) DeleteLedgerByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating removal of Ledeger with ID: %s", id) + logger.Infof("Initiating removal of Ledeger with ID: %s", id.String()) organizationID := c.Locals("organization_id").(uuid.UUID) if os.Getenv("ENV_NAME") == "production" { - logger.Errorf("Failed to remove Ledger with ID: %s in ", id) + logger.Errorf("Failed to remove Ledger with ID: %s in ", id.String()) err := common.ValidateBusinessError(cn.ErrActionNotPermitted, reflect.TypeOf(l.Ledger{}).Name()) @@ -165,11 +165,11 @@ func (handler *LedgerHandler) DeleteLedgerByID(c *fiber.Ctx) error { } if err := handler.Command.DeleteLedgerByID(ctx, organizationID, id); err != nil { - logger.Errorf("Failed to remove Ledeger with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to remove Ledeger with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully removed Ledeger with ID: %s", id) + logger.Infof("Successfully removed Ledeger with ID: %s", id.String()) return commonHTTP.NoContent(c) } From c866eaf9b4d6da4f897b8835bdc2d1e349ff867f Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 11:33:06 -0300 Subject: [PATCH 54/62] fix (asset): uuid logging format :bug: --- .../ledger/internal/ports/http/asset.go | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/components/ledger/internal/ports/http/asset.go b/components/ledger/internal/ports/http/asset.go index 5414a2fb..b777a41a 100644 --- a/components/ledger/internal/ports/http/asset.go +++ b/components/ledger/internal/ports/http/asset.go @@ -25,10 +25,10 @@ func (handler *AssetHandler) CreateAsset(a any, c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) organizationID := c.Locals("organization_id").(uuid.UUID) - logger.Infof("Initiating create of Asset with organization ID: %s", organizationID) + logger.Infof("Initiating create of Asset with organization ID: %s", organizationID.String()) ledgerID := c.Locals("ledger_id").(uuid.UUID) - logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID) + logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID.String()) payload := a.(*s.CreateAssetInput) logger.Infof("Request to create a Asset with details: %#v", payload) @@ -49,10 +49,10 @@ func (handler *AssetHandler) GetAllAssets(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) organizationID := c.Locals("organization_id").(uuid.UUID) - logger.Infof("Initiating create of Asset with organization ID: %s", organizationID) + logger.Infof("Initiating create of Asset with organization ID: %s", organizationID.String()) ledgerID := c.Locals("ledger_id").(uuid.UUID) - logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID) + logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID.String()) headerParams := commonHTTP.ValidateParameters(c.Queries()) @@ -104,15 +104,15 @@ func (handler *AssetHandler) GetAssetByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - logger.Infof("Initiating retrieval of Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) + logger.Infof("Initiating retrieval of Asset with Ledger ID: %s and Asset ID: %s", ledgerID.String(), id.String()) asset, err := handler.Query.GetAssetByID(ctx, organizationID, ledgerID, id) if err != nil { - logger.Errorf("Failed to retrieve Asset with Ledger ID: %s and Asset ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to retrieve Asset with Ledger ID: %s and Asset ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully retrieved Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) + logger.Infof("Successfully retrieved Asset with Ledger ID: %s and Asset ID: %s", ledgerID.String(), id.String()) return commonHTTP.OK(c, asset) } @@ -126,24 +126,24 @@ func (handler *AssetHandler) UpdateAsset(a any, c *fiber.Ctx) error { ledgerID := c.Locals("ledger_id").(uuid.UUID) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating update of Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) + logger.Infof("Initiating update of Asset with Ledger ID: %s and Asset ID: %s", ledgerID.String(), id.String()) payload := a.(*s.UpdateAssetInput) logger.Infof("Request to update an Asset with details: %#v", payload) _, err := handler.Command.UpdateAssetByID(ctx, organizationID, ledgerID, id, payload) if err != nil { - logger.Errorf("Failed to update Asset with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to update Asset with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } asset, err := handler.Query.GetAssetByID(ctx, organizationID, ledgerID, id) if err != nil { - logger.Errorf("Failed to get update Asset with ID: %s, Error: %s", id, err.Error()) + logger.Errorf("Failed to get update Asset with ID: %s, Error: %s", id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully updated Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) + logger.Infof("Successfully updated Asset with Ledger ID: %s and Asset ID: %s", ledgerID.String(), id.String()) return commonHTTP.OK(c, asset) } @@ -158,14 +158,14 @@ func (handler *AssetHandler) DeleteAssetByID(c *fiber.Ctx) error { ledgerID := c.Locals("ledger_id").(uuid.UUID) id := c.Locals("id").(uuid.UUID) - logger.Infof("Initiating removal of Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) + logger.Infof("Initiating removal of Asset with Ledger ID: %s and Asset ID: %s", ledgerID.String(), id.String()) if err := handler.Command.DeleteAssetByID(ctx, organizationID, ledgerID, id); err != nil { - logger.Errorf("Failed to remove Asset with Ledger ID: %s and Asset ID: %s, Error: %s", ledgerID, id, err.Error()) + logger.Errorf("Failed to remove Asset with Ledger ID: %s and Asset ID: %s, Error: %s", ledgerID.String(), id.String(), err.Error()) return commonHTTP.WithError(c, err) } - logger.Infof("Successfully removed Asset with Ledger ID: %s and Asset ID: %s", ledgerID, id) + logger.Infof("Successfully removed Asset with Ledger ID: %s and Asset ID: %s", ledgerID.String(), id.String()) return commonHTTP.NoContent(c) } From c9d39474d4af854b1cc8105868453b3017484628 Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Fri, 18 Oct 2024 14:33:13 +0000 Subject: [PATCH 55/62] chore(release): 1.19.0-beta.4 ## [1.19.0-beta.4](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.3...v1.19.0-beta.4) (2024-10-18) ### Bug Fixes * add log; :bug: ([3a71282](https://github.com/LerianStudio/midaz/commit/3a712820a16ede4cd50cdc1729c5abf0507950b0)) * add parentheses on find name or asset query; :bug: ([9b71d2e](https://github.com/LerianStudio/midaz/commit/9b71d2ee9bafba37b0eb9e1a0f328b5d10036d1e)) * add required in asset_code; :bug: ([d2481eb](https://github.com/LerianStudio/midaz/commit/d2481ebf4d3007df5337394c151360aca28ee69a)) * adjust to validate if exists code on assets; :bug: ([583890a](https://github.com/LerianStudio/midaz/commit/583890a6c1d178b95b41666a91600a60d3053123)) * create validation on code to certify that asset_code exist on assets before insert in accounts; :bug: ([2375963](https://github.com/LerianStudio/midaz/commit/2375963e26657972f22ac714c905775bdf0ed5d5)) * go sec and lint; :bug: ([4d22c8c](https://github.com/LerianStudio/midaz/commit/4d22c8c5be0f6498c5305ed01e1121efbe4e8987)) * remove copyloopvar and perfsprint; :bug: ([a181709](https://github.com/LerianStudio/midaz/commit/a1817091640de24bad22e43eaddccd86b21dcf82)) * remove goconst :bug: ([707be65](https://github.com/LerianStudio/midaz/commit/707be656984aaea2c839be70f6c7c17e84375866)) * remove unique constraint on database in code and reference on accounts; :bug: ([926ca9b](https://github.com/LerianStudio/midaz/commit/926ca9b758d7e69611afa903c035fa01218b108f)) --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bc3254e..cfe3c36a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## [1.19.0-beta.4](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.3...v1.19.0-beta.4) (2024-10-18) + + +### Bug Fixes + +* add log; :bug: ([3a71282](https://github.com/LerianStudio/midaz/commit/3a712820a16ede4cd50cdc1729c5abf0507950b0)) +* add parentheses on find name or asset query; :bug: ([9b71d2e](https://github.com/LerianStudio/midaz/commit/9b71d2ee9bafba37b0eb9e1a0f328b5d10036d1e)) +* add required in asset_code; :bug: ([d2481eb](https://github.com/LerianStudio/midaz/commit/d2481ebf4d3007df5337394c151360aca28ee69a)) +* adjust to validate if exists code on assets; :bug: ([583890a](https://github.com/LerianStudio/midaz/commit/583890a6c1d178b95b41666a91600a60d3053123)) +* create validation on code to certify that asset_code exist on assets before insert in accounts; :bug: ([2375963](https://github.com/LerianStudio/midaz/commit/2375963e26657972f22ac714c905775bdf0ed5d5)) +* go sec and lint; :bug: ([4d22c8c](https://github.com/LerianStudio/midaz/commit/4d22c8c5be0f6498c5305ed01e1121efbe4e8987)) +* remove copyloopvar and perfsprint; :bug: ([a181709](https://github.com/LerianStudio/midaz/commit/a1817091640de24bad22e43eaddccd86b21dcf82)) +* remove goconst :bug: ([707be65](https://github.com/LerianStudio/midaz/commit/707be656984aaea2c839be70f6c7c17e84375866)) +* remove unique constraint on database in code and reference on accounts; :bug: ([926ca9b](https://github.com/LerianStudio/midaz/commit/926ca9b758d7e69611afa903c035fa01218b108f)) + ## [1.19.0-beta.3](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.2...v1.19.0-beta.3) (2024-10-18) From 2936f9dbb29b200004f7e8ebfeff757a707f3466 Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 11:37:58 -0300 Subject: [PATCH 56/62] test: implements testing for UUID parser handler :rotating_light: --- common/net/http/withBody_test.go | 65 ++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/common/net/http/withBody_test.go b/common/net/http/withBody_test.go index 9dd9ee79..7a6de50d 100644 --- a/common/net/http/withBody_test.go +++ b/common/net/http/withBody_test.go @@ -3,6 +3,9 @@ package http import ( "encoding/json" "github.com/LerianStudio/midaz/common" + "github.com/gofiber/fiber/v2" + "github.com/stretchr/testify/require" + "net/http/httptest" "reflect" "testing" ) @@ -76,3 +79,65 @@ func TestFilterRequiredFieldWithNoFields(t *testing.T) { t.Errorf("Want %v, got %v", expected, result) } } + +func TestParseUUIDPathParameters_ValidUUID(t *testing.T) { + app := fiber.New() + + app.Get("/v1/organizations/:id", ParseUUIDPathParameters, func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) // Se o middleware passar, responde com 200 + }) + + req := httptest.NewRequest("GET", "/v1/organizations/123e4567-e89b-12d3-a456-426614174000", nil) + resp, err := app.Test(req, -1) + require.NoError(t, err) + + require.Equal(t, fiber.StatusOK, resp.StatusCode) +} + +func TestParseUUIDPathParameters_MultipleValidUUID(t *testing.T) { + app := fiber.New() + + app.Get("/v1/organizations/:organization_id/ledgers/:id", ParseUUIDPathParameters, func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + req := httptest.NewRequest( + "GET", + "/v1/organizations/123e4567-e89b-12d3-a456-426614174000/ledgers/c71ab589-cf46-4f2d-b6ef-b395c9a475da", + nil) + resp, err := app.Test(req, -1) + require.NoError(t, err) + + require.Equal(t, fiber.StatusOK, resp.StatusCode) +} + +func TestParseUUIDPathParameters_InvalidUUID(t *testing.T) { + app := fiber.New() + + app.Get("/v1/organizations/:id", ParseUUIDPathParameters, func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + req := httptest.NewRequest("GET", "/v1/organizations/invalid-uuid", nil) + resp, err := app.Test(req, -1) + require.NoError(t, err) + + require.Equal(t, fiber.StatusBadRequest, resp.StatusCode) +} + +func TestParseUUIDPathParameters_ValidAndInvalidUUID(t *testing.T) { + app := fiber.New() + + app.Get("/v1/organizations/:organization_id/ledgers/:id", ParseUUIDPathParameters, func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + req := httptest.NewRequest( + "GET", + "/v1/organizations/123e4567-e89b-12d3-a456-426614174000/ledgers/invalid-uuid", + nil) + resp, err := app.Test(req, -1) + require.NoError(t, err) + + require.Equal(t, fiber.StatusBadRequest, resp.StatusCode) +} From ae17b2ca1216bb0e3ce08d42c40cbe6efb993278 Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Fri, 18 Oct 2024 14:40:51 +0000 Subject: [PATCH 57/62] chore(release): 1.19.0-beta.5 ## [1.19.0-beta.5](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.4...v1.19.0-beta.5) (2024-10-18) ### Features * require code :sparkles: ([40d1bbd](https://github.com/LerianStudio/midaz/commit/40d1bbd7f54c85aaab279e36754274df93d12a34)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfe3c36a..4cb4c4d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.19.0-beta.5](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.4...v1.19.0-beta.5) (2024-10-18) + + +### Features + +* require code :sparkles: ([40d1bbd](https://github.com/LerianStudio/midaz/commit/40d1bbd7f54c85aaab279e36754274df93d12a34)) + ## [1.19.0-beta.4](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.3...v1.19.0-beta.4) (2024-10-18) From da0a22a38f57c6d8217e8511abb07592523c822f Mon Sep 17 00:00:00 2001 From: MartinezAvellan Date: Fri, 18 Oct 2024 17:06:17 +0200 Subject: [PATCH 58/62] fix: asset validate create before to ledger_id :bug: --- components/ledger/internal/app/command/create-asset.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/components/ledger/internal/app/command/create-asset.go b/components/ledger/internal/app/command/create-asset.go index 07044b07..8f6850ad 100644 --- a/components/ledger/internal/app/command/create-asset.go +++ b/components/ledger/internal/app/command/create-asset.go @@ -2,7 +2,6 @@ package command import ( "context" - cn "github.com/LerianStudio/midaz/common/constant" "reflect" "time" @@ -37,17 +36,12 @@ func (uc *UseCase) CreateAsset(ctx context.Context, organizationID, ledgerID uui } } - isAsset, err := uc.AssetRepo.FindByNameOrCode(ctx, organizationID, ledgerID, cii.Name, cii.Code) + _, err := uc.AssetRepo.FindByNameOrCode(ctx, organizationID, ledgerID, cii.Name, cii.Code) if err != nil { logger.Errorf("Error creating asset: %v", err) return nil, err } - if !isAsset { - return nil, common.ValidateBusinessError(cn.ErrAssetCodeNotFound, reflect.TypeOf(s.Asset{}).Name()) - } - - asset := &s.Asset{ Name: cii.Name, Type: cii.Type, From 40084c60ac0f390e00666f2be5341c0bcb77a179 Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Fri, 18 Oct 2024 15:17:19 +0000 Subject: [PATCH 59/62] chore(release): 1.19.0-beta.6 ## [1.19.0-beta.6](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.5...v1.19.0-beta.6) (2024-10-18) ### Bug Fixes * asset validate create before to ledger_id :bug: ([da0a22a](https://github.com/LerianStudio/midaz/commit/da0a22a38f57c6d8217e8511abb07592523c822f)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cb4c4d1..b2e429c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.19.0-beta.6](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.5...v1.19.0-beta.6) (2024-10-18) + + +### Bug Fixes + +* asset validate create before to ledger_id :bug: ([da0a22a](https://github.com/LerianStudio/midaz/commit/da0a22a38f57c6d8217e8511abb07592523c822f)) + ## [1.19.0-beta.5](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.4...v1.19.0-beta.5) (2024-10-18) From 381ba2178633863f17cffb327a7ab2276926ce0d Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 13:02:51 -0300 Subject: [PATCH 60/62] fix: uses UUID to find asset :bug: --- components/ledger/internal/app/command/create-account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ledger/internal/app/command/create-account.go b/components/ledger/internal/app/command/create-account.go index d79ed69d..94c19f1f 100644 --- a/components/ledger/internal/app/command/create-account.go +++ b/components/ledger/internal/app/command/create-account.go @@ -46,7 +46,7 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, return nil, common.ValidateBusinessError(cn.ErrInvalidCodeFormat, reflect.TypeOf(a.Account{}).Name()) } - isAsset, _ := uc.AssetRepo.FindByNameOrCode(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), "", cai.AssetCode) + isAsset, _ := uc.AssetRepo.FindByNameOrCode(ctx, organizationID, ledgerID, "", cai.AssetCode) if !isAsset { return nil, common.ValidateBusinessError(cn.ErrAssetCodeNotFound, reflect.TypeOf(a.Account{}).Name()) } From 05b89c52266d1e067ffc429d29405d49f50762dc Mon Sep 17 00:00:00 2001 From: Clara Tersi Date: Fri, 18 Oct 2024 13:21:51 -0300 Subject: [PATCH 61/62] fix: remove asset_code validation on account :bug: --- components/ledger/internal/app/command/create-account.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/ledger/internal/app/command/create-account.go b/components/ledger/internal/app/command/create-account.go index 94c19f1f..e7cefd25 100644 --- a/components/ledger/internal/app/command/create-account.go +++ b/components/ledger/internal/app/command/create-account.go @@ -42,10 +42,6 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, Scale: &balanceValue, } - if err := common.ValidateCurrency(cai.AssetCode); err != nil { - return nil, common.ValidateBusinessError(cn.ErrInvalidCodeFormat, reflect.TypeOf(a.Account{}).Name()) - } - isAsset, _ := uc.AssetRepo.FindByNameOrCode(ctx, organizationID, ledgerID, "", cai.AssetCode) if !isAsset { return nil, common.ValidateBusinessError(cn.ErrAssetCodeNotFound, reflect.TypeOf(a.Account{}).Name()) From d947df033fdacacdfe7821640f6942f5bd52e89f Mon Sep 17 00:00:00 2001 From: lerian-studio Date: Fri, 18 Oct 2024 17:14:45 +0000 Subject: [PATCH 62/62] chore(release): 1.19.0-beta.7 ## [1.19.0-beta.7](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.6...v1.19.0-beta.7) (2024-10-18) ### Features * adds UUID handler for routes with path parameters :sparkles: ([6153896](https://github.com/LerianStudio/midaz/commit/6153896bc83e0d3048a7223f89eafe6b6f2deae3)) * adds validation error for invalid path parameters :sparkles: ([270ecfd](https://github.com/LerianStudio/midaz/commit/270ecfdc7aa14040aefa29ab09710aa6274acce9)) * implements handler for parsing UUID path parameters :sparkles: ([6baa571](https://github.com/LerianStudio/midaz/commit/6baa571275c876ab48760f882e48a400bd892196)) ### Bug Fixes * better formatting for error message :bug: ([d7135ff](https://github.com/LerianStudio/midaz/commit/d7135ff90f50f154a95928829142a37226be7629)) * remove asset_code validation on account :bug: ([05b89c5](https://github.com/LerianStudio/midaz/commit/05b89c52266d1e067ffc429d29405d49f50762dc)) * uses parsed uuid while creating asset :bug: ([333bf49](https://github.com/LerianStudio/midaz/commit/333bf4921d3f2fd48156ead07ac8b1b29d88d5fa)) * uses parsed uuid while deleting ledger by id :bug: ([8dc3a97](https://github.com/LerianStudio/midaz/commit/8dc3a97f8c859a6948cad099cd61888c8c016bee)) * uses parsed uuid while deleting organization :bug: ([866170a](https://github.com/LerianStudio/midaz/commit/866170a1d2bb849fc1ed002a9aed99d7ee43eecb)) * uses parsed uuid while getting all organization ledgers :bug: ([2260a33](https://github.com/LerianStudio/midaz/commit/2260a331e381d452bcab942f9f06864c60444f52)) * uses parsed uuid while getting and updating a ledger :bug: ([ad1bcae](https://github.com/LerianStudio/midaz/commit/ad1bcae482d2939c8e828b169b566d3a13be95cd)) * uses parsed uuid while retrieving all assets from a ledger :bug: ([aadf885](https://github.com/LerianStudio/midaz/commit/aadf8852154726bd4aef2e3295221b5472236ed9)) * uses parsed uuid while retrieving and updating asset :bug: ([9c8b3a2](https://github.com/LerianStudio/midaz/commit/9c8b3a2f9747117e5149f3a515c8a5b582db4942)) * uses parsed uuid while retrieving organization :bug: ([e2d2848](https://github.com/LerianStudio/midaz/commit/e2d284808c9c1d95d3d1192be2e4ba3e613318dc)) * uses UUID to find asset :bug: ([381ba21](https://github.com/LerianStudio/midaz/commit/381ba2178633863f17cffb327a7ab2276926ce0d)) --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2e429c6..215ce685 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,27 @@ +## [1.19.0-beta.7](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.6...v1.19.0-beta.7) (2024-10-18) + + +### Features + +* adds UUID handler for routes with path parameters :sparkles: ([6153896](https://github.com/LerianStudio/midaz/commit/6153896bc83e0d3048a7223f89eafe6b6f2deae3)) +* adds validation error for invalid path parameters :sparkles: ([270ecfd](https://github.com/LerianStudio/midaz/commit/270ecfdc7aa14040aefa29ab09710aa6274acce9)) +* implements handler for parsing UUID path parameters :sparkles: ([6baa571](https://github.com/LerianStudio/midaz/commit/6baa571275c876ab48760f882e48a400bd892196)) + + +### Bug Fixes + +* better formatting for error message :bug: ([d7135ff](https://github.com/LerianStudio/midaz/commit/d7135ff90f50f154a95928829142a37226be7629)) +* remove asset_code validation on account :bug: ([05b89c5](https://github.com/LerianStudio/midaz/commit/05b89c52266d1e067ffc429d29405d49f50762dc)) +* uses parsed uuid while creating asset :bug: ([333bf49](https://github.com/LerianStudio/midaz/commit/333bf4921d3f2fd48156ead07ac8b1b29d88d5fa)) +* uses parsed uuid while deleting ledger by id :bug: ([8dc3a97](https://github.com/LerianStudio/midaz/commit/8dc3a97f8c859a6948cad099cd61888c8c016bee)) +* uses parsed uuid while deleting organization :bug: ([866170a](https://github.com/LerianStudio/midaz/commit/866170a1d2bb849fc1ed002a9aed99d7ee43eecb)) +* uses parsed uuid while getting all organization ledgers :bug: ([2260a33](https://github.com/LerianStudio/midaz/commit/2260a331e381d452bcab942f9f06864c60444f52)) +* uses parsed uuid while getting and updating a ledger :bug: ([ad1bcae](https://github.com/LerianStudio/midaz/commit/ad1bcae482d2939c8e828b169b566d3a13be95cd)) +* uses parsed uuid while retrieving all assets from a ledger :bug: ([aadf885](https://github.com/LerianStudio/midaz/commit/aadf8852154726bd4aef2e3295221b5472236ed9)) +* uses parsed uuid while retrieving and updating asset :bug: ([9c8b3a2](https://github.com/LerianStudio/midaz/commit/9c8b3a2f9747117e5149f3a515c8a5b582db4942)) +* uses parsed uuid while retrieving organization :bug: ([e2d2848](https://github.com/LerianStudio/midaz/commit/e2d284808c9c1d95d3d1192be2e4ba3e613318dc)) +* uses UUID to find asset :bug: ([381ba21](https://github.com/LerianStudio/midaz/commit/381ba2178633863f17cffb327a7ab2276926ce0d)) + ## [1.19.0-beta.6](https://github.com/LerianStudio/midaz/compare/v1.19.0-beta.5...v1.19.0-beta.6) (2024-10-18)