diff --git a/.golangci.yml b/.golangci.yml index 3295d0c0..8bf0c234 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,30 +2,19 @@ linters: enable: - bodyclose - gocognit - - goconst - depguard - dogsled - dupword # Detects duplicate words. - durationcheck - errchkjson - - exportloopref # Detects pointers to enclosing loop variables. - - gocritic # Metalinter; detects bugs, performance, and styling issues. - 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 - 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 @@ -34,12 +23,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/CHANGELOG.md b/CHANGELOG.md index ab948b51..215ce685 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,79 @@ +## [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) + + +### 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) + + +### 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) + + +### 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) + + +### 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) + + +### 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) 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/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 { diff --git a/common/net/http/withBody.go b/common/net/http/withBody.go index a738ffc9..dd5b66c3 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, "", strings.Join(invalidUUIDs, ", ")) + return WithError(c, err) + } + + return c.Next() +} + //nolint:ireturn func newValidator() (*validator.Validate, ut.Translator) { locale := en.New() 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) +} diff --git a/common/utils.go b/common/utils.go index dac548a0..20d90111 100644 --- a/common/utils.go +++ b/common/utils.go @@ -100,7 +100,9 @@ func ValidateCurrency(code string) error { } for _, r := range code { - if unicode.IsLetter(r) && !unicode.IsUpper(r) { + if !unicode.IsLetter(r) { + return cn.ErrInvalidCodeFormat + } else if !unicode.IsUpper(r) { return cn.ErrCodeUppercaseRequirement } } 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 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 { diff --git a/components/ledger/internal/app/command/create-account.go b/components/ledger/internal/app/command/create-account.go index e6169353..e7cefd25 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) @@ -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{ @@ -46,8 +42,13 @@ func (uc *UseCase) CreateAccount(ctx context.Context, organizationID, ledgerID, Scale: &balanceValue, } + isAsset, _ := uc.AssetRepo.FindByNameOrCode(ctx, organizationID, ledgerID, "", cai.AssetCode) + 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)) + 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 +58,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 +69,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 +83,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/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/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/app/command/delete-ledger.go b/components/ledger/internal/app/command/delete-ledger.go index b4b4acd5..d2e4bdcd 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) + logger.Infof("Remove ledger for id: %s", id.String()) - 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/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/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/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/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/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/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/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/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-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-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-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-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/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/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/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-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-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/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/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/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/app/query/get-id-ledger.go b/components/ledger/internal/app/query/get-id-ledger.go index dee65570..c47bfa75 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) + logger.Infof("Retrieving ledger for id: %s", id.String()) - 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/app/query/get-id-organization.go b/components/ledger/internal/app/query/get-id-organization.go index 35fddf11..2a938306 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) + logger.Infof("Retrieving organization for id: %s", id.String()) - 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/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/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/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"` 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"` } diff --git a/components/ledger/internal/ports/http/account.go b/components/ledger/internal/ports/http/account.go index 0e4d1311..6de214d4 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) @@ -46,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()) @@ -96,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) } @@ -121,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) } @@ -147,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) } diff --git a/components/ledger/internal/ports/http/asset.go b/components/ledger/internal/ports/http/asset.go index 0415d167..fa5be4f6 100644 --- a/components/ledger/internal/ports/http/asset.go +++ b/components/ledger/internal/ports/http/asset.go @@ -24,17 +24,18 @@ func (handler *AssetHandler) CreateAsset(a any, c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - logger.Infof("Initiating create of Asset with organization ID: %s", organizationID) + organizationID := c.Locals("organization_id").(uuid.UUID) + logger.Infof("Initiating create of Asset with organization ID: %s", organizationID.String()) - ledgerID := c.Params("ledger_id") - logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + 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) - 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 { + logger.Infof("Error to created Asset: %s", err.Error()) return commonHTTP.WithError(c, err) } @@ -48,11 +49,11 @@ func (handler *AssetHandler) GetAllAssets(c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - organizationID := c.Params("organization_id") - logger.Infof("Initiating create of Asset with organization ID: %s", organizationID) + organizationID := c.Locals("organization_id").(uuid.UUID) + logger.Infof("Initiating create of Asset with organization ID: %s", organizationID.String()) - ledgerID := c.Params("ledger_id") - logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID) + ledgerID := c.Locals("ledger_id").(uuid.UUID) + logger.Infof("Initiating create of Asset with ledger ID: %s", ledgerID.String()) headerParams := commonHTTP.ValidateParameters(c.Queries()) @@ -98,21 +99,21 @@ 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) - 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) } @@ -122,28 +123,28 @@ 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) + 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, 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()) + 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) } @@ -154,18 +155,18 @@ 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) + logger.Infof("Initiating removal of Asset with Ledger ID: %s and Asset ID: %s", ledgerID.String(), id.String()) - if err := handler.Command.DeleteAssetByID(ctx, uuid.MustParse(organizationID), uuid.MustParse(ledgerID), uuid.MustParse(id)); err != nil { - logger.Errorf("Failed to remove Asset with Ledger ID: %s and Asset ID: %s, Error: %s", ledgerID, id, err.Error()) + 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.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) } diff --git a/components/ledger/internal/ports/http/ledger.go b/components/ledger/internal/ports/http/ledger.go index 3c046896..bd58c169 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,18 +52,18 @@ func (handler *LedgerHandler) GetLedgerByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") - logger.Infof("Initiating retrieval of Ledger with ID: %s", id) + id := c.Locals("id").(uuid.UUID) + logger.Infof("Initiating retrieval of Ledger with ID: %s", id.String()) - organizationID := c.Params("organization_id") + 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) } @@ -71,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()) @@ -118,27 +120,27 @@ func (handler *LedgerHandler) UpdateLedger(p any, c *fiber.Ctx) error { ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") - logger.Infof("Initiating update of Ledger with ID: %s", id) + id := c.Locals("id").(uuid.UUID) + logger.Infof("Initiating update of Ledger with ID: %s", id.String()) - 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) _, 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) } @@ -149,13 +151,13 @@ func (handler *LedgerHandler) DeleteLedgerByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") - logger.Infof("Initiating removal of Ledeger with ID: %s", id) + id := c.Locals("id").(uuid.UUID) + logger.Infof("Initiating removal of Ledeger with ID: %s", id.String()) - 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) + logger.Errorf("Failed to remove Ledger with ID: %s in ", id.String()) err := common.ValidateBusinessError(cn.ErrActionNotPermitted, reflect.TypeOf(l.Ledger{}).Name()) @@ -163,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) } diff --git a/components/ledger/internal/ports/http/organization.go b/components/ledger/internal/ports/http/organization.go index 637d3e85..3a8931f9 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,25 +49,25 @@ func (handler *OrganizationHandler) UpdateOrganization(p any, c *fiber.Ctx) erro ctx := c.UserContext() logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") - logger.Infof("Initiating update of Organization with ID: %s", id) + id := c.Locals("id").(uuid.UUID) + 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) } @@ -74,19 +76,19 @@ 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) - 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) } @@ -142,11 +144,11 @@ func (handler *OrganizationHandler) DeleteOrganizationByID(c *fiber.Ctx) error { logger := mlog.NewLoggerFromContext(ctx) - id := c.Params("id") - logger.Infof("Initiating removal of Organization with ID: %s", id) + id := c.Locals("id").(uuid.UUID) + 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()) @@ -154,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) } diff --git a/components/ledger/internal/ports/http/portfolio.go b/components/ledger/internal/ports/http/portfolio.go index 99ff0a4e..6e0c039e 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" ) @@ -47,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()) @@ -95,21 +96,21 @@ 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) - 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 { - 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) } @@ -119,28 +120,28 @@ 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) + 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) } @@ -151,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) } diff --git a/components/ledger/internal/ports/http/product.go b/components/ledger/internal/ports/http/product.go index 582b2d9a..02eeac3c 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) @@ -45,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()) @@ -94,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) } @@ -115,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) } @@ -146,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) } 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) 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), diff --git a/components/mdz/.golangci.yml b/components/mdz/.golangci.yml new file mode 100644 index 00000000..0066f070 --- /dev/null +++ b/components/mdz/.golangci.yml @@ -0,0 +1,145 @@ +linters: + enable: + - 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 + - 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 + 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 new file mode 100644 index 00000000..e64d6d84 --- /dev/null +++ b/components/mdz/Makefile @@ -0,0 +1,43 @@ +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 --fix ./... --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: 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-perfsprint-deps +get-perfsprint-deps: + go get github.com/catenacyber/perfsprint@latest + +.PHONY : perfsprint +perfsprint: get-perfsprint-deps + perfsprint ./... + +.PHONY : build +build: + go version + go build -o ./bin/$(NAME) ./main.go 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 77fb2453..d7ea1c0e 100644 --- a/components/mdz/main.go +++ b/components/mdz/main.go @@ -1,9 +1,28 @@ 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..a352d473 --- /dev/null +++ b/components/mdz/pkg/cmd/root/help.go @@ -0,0 +1,241 @@ +package root + +import ( + "bytes" + "fmt" + "regexp" + "strings" + + "github.com/fatih/color" + "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" { + 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 + ) + + for _, c := range command.Commands() { + if c.Short == "" || c.Hidden { + continue + } + + s := rpad(c.Name(), c.NamePadding()) + c.Short + + if c.Annotations["Category"] == "skip" { + continue + } + + if !isRootCmd(c.Parent()) { + subcmdCommands = append(subcmdCommands, s) + } else { + baseCommands = append(baseCommands, s) + } + } + + 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 + } + + helpEntries = append(helpEntries, helpEntry{"", color.New(color.Bold).Sprint(f.factory.CLIVersion)}) + if longText != "" { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(color.Bold).Sprint("DESCRIPTION"), + Body: color.New(color.FgHiWhite).Sprint(longText), + }) + } + + helpEntries = append(helpEntries, helpEntry{ + 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(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(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(color.Bold).Sprint("AVAILABLE SUBCOMMANDS"), + Body: color.New(color.FgHiWhite).Sprint(strings.Join(subcmdCommands, "\n")), + }) + } + + flagUsages := command.LocalFlags().FlagUsages() + if flagUsages != "" { + if isRootCmd(command) { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(color.Bold).Sprint("GLOBAL OPTIONS"), + Body: color.New(color.FgHiWhite).Sprint(dedent(flagUsages)), + }) + } else { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(color.Bold).Sprint("LOCAL OPTIONS"), + Body: color.New(color.FgHiWhite).Sprint(dedent(flagUsages)), + }) + } + } + + inheritedFlagUsages := command.InheritedFlags().FlagUsages() + if inheritedFlagUsages != "" { + helpEntries = append(helpEntries, helpEntry{ + Title: color.New(color.Bold).Sprint("GLOBAL OPTIONS"), + Body: color.New(color.FgHiWhite).Sprint(dedent(inheritedFlagUsages)), + }) + } + + helpEntries = append(helpEntries, helpEntry{ + 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 != "" { + fmt.Fprintln(out, e.Title) + fmt.Fprintln(out, Indent(strings.Trim(e.Body, "\r\n"), " ")) + } else { + 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 { + 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..7141edce --- /dev/null +++ b/components/mdz/pkg/cmd/root/root.go @@ -0,0 +1,58 @@ +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/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/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..715c1599 --- /dev/null +++ b/components/mdz/pkg/cmd/version/version.go @@ -0,0 +1,39 @@ +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/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) + }) + } +} 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..4ecec23a --- /dev/null +++ b/components/mdz/pkg/output/output.go @@ -0,0 +1,43 @@ +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") 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= 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