diff --git a/.gitignore b/.gitignore index 6d87665..50d001c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ _data/ .env.local .json .vscode - +.DS_Store data/ __debug_bin \ No newline at end of file diff --git a/README-PTBR.md b/README-PTBR.md new file mode 100644 index 0000000..91b8af5 --- /dev/null +++ b/README-PTBR.md @@ -0,0 +1,45 @@ + +[![Go Reference](https://pkg.go.dev/badge/github.com/abu-lang/goabu.svg)](https://pkg.go.dev/github.com/bancodobrasil/featws-api) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/bancodobrasil/featws-api/blob/develop/LICENSE) + +# Featws API [![About_en](https://github.com/yammadev/flag-icons/blob/master/png/BR.png?raw=true)](https://github.com/bancodobrasil/featws-api/blob/develop/README.md) + + +## Como executar + +Para executar este projeto, você precisa ter certos pré-requisitos configurados em sua máquina. Esses pré-requisitos incluem: + +- [Golang](https://go.dev/doc/install) +- [Swaggo](https://github.com/swaggo/swag/blob/master/README_pt.md#come%C3%A7ando) +- [Docker](https://www.docker.com/) + + +Para executar o projeto, siga estes passos: + +- Abra o terminal no diretório do projeto e execute o comando `go mod tidy` para garantir que todas as dependências necessárias estejam instaladas. + +- Em seguida, execute o comando `swag init` para inicializar o Swagger e gerar a documentação da API necessária. + +- Abra o Docker da sua máquina, ou algum semelhante, para garantir que ele está funcionado. Logo, abra o terminal no repositório do projeto e rode `docker compose up`. + +- Após os containers serem iniciados e estarem rodando, execute o comando `make run` no terminal do projeto para iniciar o projeto. + +O projeto será executado em `localhost:9007`. Para acessar a documentação do Swagger, [clique aqui](http://localhost:9007/swagger/index.html#/). + +Seguindo estes passos, o projeto estará em execução e você poderá acessar a documentação da API através do Swagger. + +## GoDoc + +Para acessar a documentação do GoDoc, primeiro instale o GoDoc na sua máquina. Abra um terminal e digite: + +```` +go get golang.org/x/tools/cmd/godoc +```` + +Em seguida rode no terminal do repositório o comando a seguir: + +```` +godoc -http=:6060 +```` + +O GoDoc será executado em `localhost:6060`. Para acessar a documentação do GoDoc, basta [clicar aqui](http://localhost:6060/pkg/). \ No newline at end of file diff --git a/README.md b/README.md index 1021f87..e0aea57 100644 --- a/README.md +++ b/README.md @@ -1 +1,42 @@ -# featws-backoffice-api \ No newline at end of file +[![Go Reference](https://pkg.go.dev/badge/github.com/abu-lang/goabu.svg)](https://pkg.go.dev/github.com/bancodobrasil/featws-api) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/bancodobrasil/featws-api/blob/develop/LICENSE) + +# Featws API [![About_en](https://github.com/yammadev/flag-icons/blob/master/png/BR.png?raw=true)](https://github.com/bancodobrasil/featws-api/blob/develop/README-PTBR.md) +## How to run + +In order to run this project, you need to have certain prerequisites set up on your machine. These prerequisites include: + + - [Golang](https://go.dev/doc/install) + - [Swaggo](https://github.com/swaggo/swag/blob/master/README_pt.md#come%C3%A7ando) +- [Docker](https://www.docker.com/) + + +To run the project, follow these steps: + +- Open the terminal in the project directory and run the command `go mod tidy` to ensure that all required dependencies are installed. + +- Then, run the command `swag init` to initialize Swagger and generate the necessary API documentation. + +- Open Docker on your machine or a similar application to ensure that it is working properly. Then, open the terminal in the project repository and run `docker compose up`. + +- Once the containers are started and running, run the command `make run` in the project terminal to start the project. + +The project will run on `localhost:9007`. To access the Swagger documentation [click here](http://localhost:9007/swagger/index.html#/). + +By following these steps, the project will be up and running, and you will be able to access the API documentation through Swagger. + +## GoDoc + +To access the GoDoc documentation, first install GoDoc on your machine. Open a terminal and type: + +```` +go get golang.org/x/tools/cmd/godoc +```` + +Then run the following command in the repository terminal: + +```` +godoc -http=:6060 +```` + +GoDoc will run on `localhost:6060`. To access the GoDoc documentation, just [click here](http://localhost:6060/pkg/). \ No newline at end of file diff --git a/config/config.go b/config/config.go index dd2caf5..9f35d7c 100644 --- a/config/config.go +++ b/config/config.go @@ -7,7 +7,23 @@ import ( "github.com/spf13/viper" ) -// Config ... +// Config type contains various configuration parameters for a Go application, including database +// and GitLab API credentials, authentication mode, and external host information. +// +// Property: +// - AllowOrigins: This property specifies the allowed origins for CORS requests. It is a string value that can contain multiple origins separated by commas. +// - Port: The port number on which the server will listen for incoming requests. +// - MysqlURI: The URI for connecting to the MySQL database used by the API. +// - Migrate: it's used to specify whether to run database migrations or not. If the value is set to "true", the application will run database migrations on startup. If the value is set to "false", the application will not run database migrations. +// - GitlabToken: This's a token used for authentication with GitLab API. It allows the application to access GitLab resources on behalf of a user or a bot account. +// - GitlabURL: The URL of the GitLab instance that the API will interact with. +// - GitlabNamespace: The namespace or group name in GitLab where the project is located. +// - GitlabPrefix: The GitlabPrefix property is a string that represents the prefix to be used for all GitLab API requests. It is used to specify the namespace or group where the project's located. For example, if the GitlabPrefix is set to "mygroup/myproject", all API requests will be made. +// - GitlabDefaultBranch: This property represents the default branch name for a GitLab repository. When creating a new repository, GitLab will use this branch as the default branch. +// - GitlabCIScript - GitlabCIScript is a property in the Config struct that represents the GitLab CI script that will be used for building and testing the project. It is specified in the configuration file using the key "FEATWS_API_GITLAB_CI_SCRIPT". +// - ExternalHost - This property represents the external host name or IP address of the server where the application is running. It is used to configure the application to listen on a specific network interface or to generate URLs that can be accessed from outside the server. +// - OpenAMURL: The URL of the OpenAM server used for authentication. +// - AuthMode - This property specifies the authentication mode used by the API. It can have values like "jwt", "oauth2", "basic", etc. type Config struct { AllowOrigins string `mapstructure:"ALLOW_ORIGINS"` Port string `mapstructure:"PORT"` @@ -26,7 +42,7 @@ type Config struct { var config = &Config{} -// LoadConfig ... +// LoadConfig loads configuration settings from a file and sets default values if they are no present. func LoadConfig() (err error) { viper.AddConfigPath("./") viper.SetConfigFile(".env") @@ -62,7 +78,7 @@ func LoadConfig() (err error) { return } -// GetConfig ... +// GetConfig returns a pointer to a Config object. func GetConfig() *Config { return config } diff --git a/controllers/health.go b/controllers/health.go index 4f02da1..1e3bfd5 100644 --- a/controllers/health.go +++ b/controllers/health.go @@ -21,7 +21,7 @@ type HealthController struct { health healthcheck.Handler } -// NewHealthController ... +// NewHealthController returns a new instance of the HealthController struct with a newHandler. func NewHealthController() *HealthController { return &HealthController{ health: newHandler(), @@ -30,6 +30,8 @@ func NewHealthController() *HealthController { var health = healthcheck.NewHandler() +// newHandler creates a new healthcheck handler and adds liveness and readiness checks for goroutine +// count, Gitlab URL, and database connection. func newHandler() healthcheck.Handler { cfg := config.GetConfig() health.AddLivenessCheck("goroutine-threshold", goroutine.Count(100)) @@ -58,7 +60,8 @@ func newHandler() healthcheck.Handler { return health } -// Get was the function that allow follow the url +// Get returns a check function that performs an HTTP GET request to a specified URL with a +// specified timeout and returns an error if the response status code is not 200. func Get(url string, timeout time.Duration) checks.Check { client := http.Client{ Timeout: timeout, @@ -80,12 +83,20 @@ func Get(url string, timeout time.Duration) checks.Check { } } -// HealthLiveHandler ... +// HealthLiveHandler is returning a Gin middleware function that wraps the `LiveEndpoint` method of the +// `health` handler of the `HealthController` struct. The `LiveEndpoint` method is used to check if the +// application is alive and responding to requests. The `gin.WrapH` function is used to convert the +// `http.HandlerFunc` returned by `LiveEndpoint` into a `gin.HandlerFunc` that can be used as +// middleware in a Gin router. func (c *HealthController) HealthLiveHandler() gin.HandlerFunc { return gin.WrapH(http.HandlerFunc(c.health.LiveEndpoint)) } -// HealthReadyHandler ... +// HealthReadyHandler is returning a Gin middleware function that wraps the `ReadyEndpoint` method of the +// `health` handler of the `HealthController` struct. The `ReadyEndpoint` method is used to check if +// the application is ready to receive requests. The `gin.WrapH` function is used to convert the +// `http.HandlerFunc` returned by `ReadyEndpoint` into a `gin.HandlerFunc` that can be used as +// middleware in a Gin router. func (c *HealthController) HealthReadyHandler() gin.HandlerFunc { return gin.WrapH(http.HandlerFunc(c.health.ReadyEndpoint)) } diff --git a/controllers/home.go b/controllers/home.go index 411c88d..5717327 100644 --- a/controllers/home.go +++ b/controllers/home.go @@ -6,7 +6,7 @@ import ( "github.com/gin-gonic/gin" ) -// HomeHandler ... +// HomeHandler function returns a JSON response with a message indicating that the FeatWS API is working. func HomeHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "FeatWS API Works!!!", diff --git a/controllers/home_test.go b/controllers/home_test.go index 19bd1d2..ed8f1a6 100644 --- a/controllers/home_test.go +++ b/controllers/home_test.go @@ -34,6 +34,8 @@ import ( // assert.Equal(t, mockUserResp, string(responseData)) // } + +// TestUnitHomeHandler is a unit test for the HomeHandler function in a Go web application. func TestUnitHomeHandler(t *testing.T) { gin.SetMode(gin.TestMode) @@ -42,5 +44,4 @@ func TestUnitHomeHandler(t *testing.T) { controllers.HomeHandler(c) assert.Equal(t, http.StatusOK, w.Code) - } diff --git a/controllers/v1/rulesheets.go b/controllers/v1/rulesheets.go index aee7627..dae0523 100644 --- a/controllers/v1/rulesheets.go +++ b/controllers/v1/rulesheets.go @@ -15,7 +15,18 @@ import ( "github.com/gin-gonic/gin" ) -// Rulesheets ... +// Rulesheets defines a set of methods for handling CRUD operations on rulesheets in a Gin web framework. +// +// Property: +// - CreateRulesheet: A function that handles the creation of a new rulesheet. It should receive data from the client and store it in a db or other storage system. +// - GetRulesheets: is a function that handles the HTTP GET request to retrieve a list of all rulesheets. It returns a gin.HandlerFunc which is a function that handles the request and sends the response. +// - GetRulesheet: is a function that handles the HTTP GET request to retrieve a specific rulesheet from a database or other data source. It takes in a gin.Context object as a parameter and returns a gin.HandlerFunc that can be used as a middleware to handle the request. The function should typically extract the ID +// - UpdateRulesheet: is a function that handles the updating of a specific rulesheet. It takes in a gin context object and returns a gin handler function. This handler function should retrieve the updated rulesheet data from the request body, validate it, and update the corresponding rulesheet in the database. The handler +// - DeleteRulesheet: is a function that handles the deletion of a specific +// +// rulesheet. It is a gin.HandlerFunc, which means it is a function that takes in a gin.Context object +// as its parameter and returns nothing. The function should retrieve the ID of the rulesheet to be +// deleted from the request parameters or type Rulesheets interface { CreateRulesheet() gin.HandlerFunc GetRulesheets() gin.HandlerFunc @@ -24,11 +35,13 @@ type Rulesheets interface { DeleteRulesheet() gin.HandlerFunc } +// The type "rulesheets" contains a service called "services.Rulesheets". The "service" property is a variable of type "services.Rulesheets". It is likely +// that this variable is used to access or manipulate data related to rulesheets in some way within the code. type rulesheets struct { service services.Rulesheets } -// NewRulesheets ... +// NewRulesheets creates a new instance of the Rulesheets struct with a given service. func NewRulesheets(service services.Rulesheets) Rulesheets { return &rulesheets{ service: service, @@ -36,21 +49,39 @@ func NewRulesheets(service services.Rulesheets) Rulesheets { } // CreateRulesheet godoc -// @Summary Create Rulesheet -// @Description Create Rulesheet description -// @Tags Rulesheet -// @Accept json +// @Summary Criação de Folha de Regra +// @Description Nessa operação cria uma folha de regra no banco de dados do FeatWS. Para realizar a criação é necessário completar a folha de regra, com no mínimo: +// @Description - **nome** no parâmetro *name*; +// @Description - **slug** no parâmetro *slug*; +// @Description - **descrição** no parâmetro *description*. +// @Description +// @Description ``` +// @Description { +// @Description "description": "teste no Swagger da API do FeatWS", +// @Description "name": "teste Swagger API", +// @Description "slug": "teste_Swagger_API" +// @Description } +// @Description ``` +// @Description Ambos esses parâmetros devem ser uma string, ou seja, deve estar entre "aspas". Não é possível ter uma folha de regra com o mesmo nome de outra. +// @Description Para criar uma folha de regra basta clicar em **Try it out** , complete a folha de regra com os dados desejados, em seguida, clique em **Execute**. +// @Tags Rulesheet +// @Accept json // @Produce json -// @Param Rulesheet body payloads.Rulesheet true "Rulesheet body" +// @Param Rulesheet body payloads.Rulesheet true "Rulesheet body" // @Success 200 {object} payloads.Rulesheet // @Header 200 {string} Authorization "token access" // @Failure 400 {object} responses.Error "Bad Format" // @Failure 500 {object} responses.Error "Internal Server Error" // @Failure default {object} responses.Error -// @Response 404 "Not Found" +// @Response 404 "Not Found" // @Security Authentication Api Key // @Security Authentication Bearer Token // @Router /rulesheets [post] +// The above code is defining a function that creates a new rulesheet. It receives a gin context and +// returns a gin handler function. The function first validates the request body and required fields +// using the validator library. It then creates a new rulesheet DTO using the payload received in the +// request. Finally, it calls the service to create the rulesheet and returns a JSON response with the +// created rulesheet data. func (rc *rulesheets) CreateRulesheet() gin.HandlerFunc { return func(c *gin.Context) { @@ -102,15 +133,22 @@ func (rc *rulesheets) CreateRulesheet() gin.HandlerFunc { } -// GetRulesheets godoc -// @Summary List Rulesheets -// @Description List Rulesheet description -// @Tags Rulesheet +// GetRulesheets godoc +// @Summary Listar as Folhas de Regra +// @Description É possível listar as folhas de regra de algumas maneiras como veremos a seguir: +// @Description +// @Description - **Sem nenhum parâmetro:** Ao realizar a chamada do endpoint sem a passagem de parâmetros, todas as folhas de regra existentes serão retornadas, contendo informações como nome, ID, e caso estejam disponíveis, descrição e slug. +// @Description - **Usando o *count*:** Ao habilitar o *count* para *True* será retornado do endpoint o número de Folhas de Regras existentes. +// @Description - **Usando o *limit*:** Ao utilizar o parâmetro *limit* deve-se especificar o número máximo de respostas desejadas que serão retornadas pela array. +// @Description - **Usando o *page*:** Ao utilizar o parâmetro *page*, serão retornadas as folhas de regra correspondentes a essa página, onde as folhas são ordenadas em ordem crescente pelo seu ID. +// @Description +// @Description Para listar as folhas de regra basta clicar em **Try it out** , complete com o formado desejados, em seguida, clique em **Execute**. +// @Tags Rulesheet // @Accept json // @Produce json -// @Param count query boolean false "Total of results" -// @Param limit query integer false "Max length of the array returned" -// @Param page query integer false "Page number that is multiplied by 'limit' to calculate the offset" +// @Param count query boolean false "Total of results" +// @Param limit query integer false "Max length of the array returned" +// @Param page query integer false "Page number that is multiplied by 'limit' to calculate the offset" // @Success 200 {array} payloads.Rulesheet // @Header 200 {string} Authorization "token access" // @Failure 400 {object} responses.Error "Bad Format" @@ -120,6 +158,11 @@ func (rc *rulesheets) CreateRulesheet() gin.HandlerFunc { // @Security Authentication Api Key // @Security Authentication Bearer Token // @Router /rulesheets/ [get] +// GetRulesheets returns a `gin.HandlerFunc`, this function handles HTTP requests to retrieve rulesheets +// from a database. It first extracts any query parameters from the request URL and uses them to set options +// for the database query. If the `count` parameter is present, it returns the count of rulesheets that match +// the query. Otherwise, it retrieves the rulesheets from the database and returns them as a JSON response. +// The response is formatted using a `responses.Rulesheet` struct. func (rc *rulesheets) GetRulesheets() gin.HandlerFunc { return func(c *gin.Context) { @@ -130,6 +173,7 @@ func (rc *rulesheets) GetRulesheets() gin.HandlerFunc { query := c.Request.URL.Query() filter := make(map[string]interface{}) // TODO: Implement filters correctly + // for param, value := range query { // if len(value) == 1 { // filter[param] = value[0] @@ -209,8 +253,8 @@ func (rc *rulesheets) GetRulesheets() gin.HandlerFunc { } // GetRulesheet godoc -// @Summary Get Rulesheet by ID -// @Description Get Rulesheet by ID description +// @Summary Obter Folha de Regra por ID +// @Description Para se obter a folha de regra por ID, basta clicar em **Try it out** e colocar o ID desejado em *id*. Em seguida, clique em **Execute** e caso o ID exista retornará a folha de regra com o número de ID desejado. // @Tags Rulesheet // @Accept json // @Produce json @@ -224,6 +268,12 @@ func (rc *rulesheets) GetRulesheets() gin.HandlerFunc { // @Security Authentication Api Key // @Security Authentication Bearer Token // @Router /rulesheets/{id} [get] +// GetRulesheet is defining a function that returns a Gin middleware function +// that retrieves a rulesheet entity from a service based on the ID parameter passed in the +// request. If the entity is found, it is returned as a JSON response with a 200 status code. If the +// entity is not found, a 404 status code is returned. If there is an error during the retrieval +// process, a 500 status code is returned with an error message. The function uses a context with a +// timeout of 10 seconds to ensure that the request does not take too long to complete. func (rc *rulesheets) GetRulesheet() gin.HandlerFunc { return func(c *gin.Context) { @@ -261,8 +311,8 @@ func (rc *rulesheets) GetRulesheet() gin.HandlerFunc { } // UpdateRulesheet godoc -// @Summary Update Rulesheet by ID -// @Description Update Rulesheet by ID description +// @Summary Atualizar Folha de Regra por ID +// @Description Para atualizar ou editar uma folha de regra, é necessário enviar o ID da folha desejada no campo *id*, juntamente com os parâmetros da regra no corpo da solicitação no parâmetro *rulesheet*. Para realizar essa atualização clique no botão **Try it out** e preencher os campos com os dados desejados, em seguida, clicar em **Execute** para enviar a solicitação de atualização. // @Tags Rulesheet // @Accept json // @Produce json @@ -277,6 +327,11 @@ func (rc *rulesheets) GetRulesheet() gin.HandlerFunc { // @Security Authentication Api Key // @Security Authentication Bearer Token // @Router /rulesheets/{id} [put] +// UpdateRulesheet is defining a function that handles the update of a rulesheet entity. It receives a +// request with a JSON payload containing the updated information for the entity, validates the +// payload, and updates the entity in the database using a service. If the update is successful, it +// returns a JSON response with the updated entity information. If the entity is not found, it returns +// a 404 status code. func (rc *rulesheets) UpdateRulesheet() gin.HandlerFunc { return func(c *gin.Context) { @@ -360,8 +415,8 @@ func (rc *rulesheets) UpdateRulesheet() gin.HandlerFunc { } // DeleteRulesheet godoc -// @Summary Delete Rulesheet by ID -// @Description Delete Rulesheet by ID description +// @Summary Deletar Folha de Regra por ID +// @Description Para excluir uma folha de regra, é necessário clicar no botão **Try it out** e preencher o campo *id* com o ID da folha de regra que se deseja excluir. Em seguida, clique em **Execute** para enviar a solicitação de exclusão. // @Tags Rulesheet // @Accept json // @Produce json @@ -375,6 +430,12 @@ func (rc *rulesheets) UpdateRulesheet() gin.HandlerFunc { // @Security Authentication Api Key // @Security Authentication Bearer Token // @Router /rulesheets/{id} [delete] +// DeleteRulesheet is defining a function that handles HTTP requests to delete a rulesheet. It first +// extracts the ID of the rulesheet to be deleted from the request parameters. It then uses a service +// to attempt to delete the rulesheet with the given ID. If the deletion is successful, it returns a +// 204 No Content response. If the rulesheet is not found, it returns a 404 Not Found response. If +// there is an error during the deletion process, it returns a 500 Internal Server Error response with +// an error message. func (rc *rulesheets) DeleteRulesheet() gin.HandlerFunc { return func(c *gin.Context) { diff --git a/controllers/v1/rulesheets_test.go b/controllers/v1/rulesheets_test.go index 885ad94..078bc4d 100644 --- a/controllers/v1/rulesheets_test.go +++ b/controllers/v1/rulesheets_test.go @@ -20,7 +20,13 @@ import ( "github.com/stretchr/testify/mock" ) +// TestRulesheet_GetRulesheetByID is a test function that tests the functionality of +// retrieving a rulesheet by ID using Gin framework and mock services. func TestRulesheet_GetRulesheetByID(t *testing.T) { + // It's testing the behavior of a function that retrieves a rulesheet by ID. The test case is checking if + // the function returns a 404 status code when the rulesheet with the given ID is not found. It creates a new + // HTTP request with a mock context and a mock service that returns nil for the rulesheet with ID "1". + // The test case then calls the function and checks if the HTTP response code is equal to 404. t.Run("Not Found Rulesheet Flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -38,6 +44,7 @@ func TestRulesheet_GetRulesheetByID(t *testing.T) { assert.Equal(t, http.StatusNotFound, w.Code) }) + // It is testing the behavior of a function that retrieves a rulesheet without an ID. t.Run("Test Without ID Flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -52,6 +59,10 @@ func TestRulesheet_GetRulesheetByID(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) + // It tests the "GetRulesheet" function of the "Rulesheets" API endpoint. The test simulates a request + // to the endpoint with a parameter "id" set to 1. The mock service is used to simulate the behavior + // of the actual service. In this case, the mock service returns an error when the "Get" function is called + // with the parameter "1". The test then checks if the HTTP response code is equal to 500 using the "assert" package. t.Run("Wrong ID Flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -68,6 +79,7 @@ func TestRulesheet_GetRulesheetByID(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, w.Code) }) + // It is testing the "GetRulesheet" function of the "Rulesheets" struct in the "v1" package. t.Run("Entity Different Nil Flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -92,7 +104,12 @@ func TestRulesheet_GetRulesheetByID(t *testing.T) { } +// TestRulesheet_GetAllRulesheets tests the GetAllRulesheets function in the Rulesheets API endpoint, covering various +// scenarios such as error handling and normal flow with and without count query. func TestRulesheet_GetAllRulesheets(t *testing.T) { + // It tests the error handling of a limit query parameter that cannot be parsed. It creates a new HTTP + // request with a malformed limit query parameter and sends it to a mock Rulesheets service using the Gin. + // Thetest then checks that the HTTP response code is equal to 500 using the assert package. t.Run("Error on parse limit Query Flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -109,6 +126,8 @@ func TestRulesheet_GetAllRulesheets(t *testing.T) { }) + // It tests the error handling of a function that retrieves rulesheets from a server. The test creates + // a mock server and sends a request with an invalid page query parameter. The test expects the server to return a 500. t.Run("Error on parse page Query Flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -125,6 +144,10 @@ func TestRulesheet_GetAllRulesheets(t *testing.T) { }) + // It tests the normal flow of a function that retrieves rulesheets with pagination. It creates a test + // context and sets the request URL with query parameters for pagination. It then creates a mock service + // for rulesheets and sets the expected behavior for the Find method of the service. Finally, it calls the + // GetRulesheets function of the Rulesheets API with the test context and asserts that the response status code is HTTP 200 OK. t.Run("Normal flow with count query", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -146,6 +169,10 @@ func TestRulesheet_GetAllRulesheets(t *testing.T) { assert.Equal(t, http.StatusOK, w.Code) }) + // This test is testing the normal flow of getting rulesheets without count query and array of rulesheets. + // It creates a test context and sets the request URL with limit and page parameters. It then creates a mock + // service for rulesheets and sets the expected response entities. The test then calls the GetRulesheets function + // and asserts that the HTTP status code returned is 200 OK. t.Run("Normal flow without count query and array of rulesheets", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -178,6 +205,10 @@ func TestRulesheet_GetAllRulesheets(t *testing.T) { assert.Equal(t, http.StatusOK, w.Code) }) + // It tests the error flow of a function that retrieves rulesheets from a service. The test creates a + // mock service and sets expectations for the service's Find method to return an error. It then sends + // a GET request to the function with query parameters for limit and page. Finally, it asserts that the + // response code is equal to http.StatusInternalServerError. t.Run("Error flow without count query", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -199,6 +230,10 @@ func TestRulesheet_GetAllRulesheets(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, w.Code) }) + // It tests the normal flow of a function that retrieves rulesheets with a count query. It creates a + // test context and sets the request URL with query parameters for limit, page, and count. It then + // creates a mock service for rulesheets and sets expectations for the Find and Count methods. Finally, + // it calls the GetRulesheets function and asserts that the HTTP status code returned is 200. t.Run("Normal flow with count query", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -218,6 +253,10 @@ func TestRulesheet_GetAllRulesheets(t *testing.T) { assert.Equal(t, http.StatusOK, w.Code) }) + // It tests the error flow of a function that retrieves rulesheets with a count query parameter. The test + // creates a mock service for rulesheets and sets expectations for the Find and Count methods. It then sends + // a GET request to the function with a URL containing the count query parameter. The test asserts that the response + // code is HTTP 500. t.Run("Error flow with count query", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -239,7 +278,11 @@ func TestRulesheet_GetAllRulesheets(t *testing.T) { } +// TestRulesheet_CreateRulesheet is a test function for creating a rulesheet in a Go application, with different scenarios for +// normal flow and error handling. func TestRulesheet_CreateRulesheet(t *testing.T) { + // It tests the normal flow of creating a rulesheet using a mock service. It creates a new HTTP request with a JSON + // payload, sets up a mock service to handle the request, and asserts that the response code is HTTP status code 201. t.Run("Normal flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -271,6 +314,11 @@ func TestRulesheet_CreateRulesheet(t *testing.T) { assert.Equal(t, http.StatusCreated, w.Code) }) + // It tests the behavior of a function that creates a new rulesheet by mocking the services layer. Specifically, it tests that + // the function returns a 400 Bad Request HTTP status code when the request body is invalid. The test + // creates a new HTTP request context, sets up a mock service, and calls the function being tested. + // Finally, it uses the assert package to check that the HTTP status code returned by the function + // matches the expected value. t.Run("Error on validate request body", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -293,6 +341,11 @@ func TestRulesheet_CreateRulesheet(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) + // It's testing the behavior of a function that creates a new rulesheet. The test is checking if the function + // returns a status code of 400 (Bad Request) when the required fields in the payload are not provided. It creates a + // mock service for the rulesheet and sets an expectation that the service's Create method will be + // called with a specific argument. The test then calls the function and checks if the response status + // code matches the expected value. t.Run("Error on validate required fields", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -321,73 +374,76 @@ func TestRulesheet_CreateRulesheet(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) - t.Run("Error on define rulesheet entity", func(t *testing.T) { - gin.SetMode(gin.TestMode) + // t.Run("Error on define rulesheet entity", func(t *testing.T) { + // gin.SetMode(gin.TestMode) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) + // w := httptest.NewRecorder() + // c, _ := gin.CreateTestContext(w) - c.Request = &http.Request{ - Header: make(http.Header), - } + // c.Request = &http.Request{ + // Header: make(http.Header), + // } - rules := make(map[string]interface{}) - rules["test"] = 12 - payload := &payloads.Rulesheet{ - ID: uint(1), - Name: "test", - Rules: &rules, - } + // rules := make(map[string]interface{}) + // rules["test"] = 12 + // payload := &payloads.Rulesheet{ + // ID: uint(1), + // Name: "test", + // Rules: &rules, + // } - bytedPayload, _ := json.Marshal(payload) + // bytedPayload, _ := json.Marshal(payload) - c.Request.Body = ioutil.NopCloser(bytes.NewReader(bytedPayload)) + // c.Request.Body = ioutil.NopCloser(bytes.NewReader(bytedPayload)) - srv := new(mock_services.Rulesheets) + // srv := new(mock_services.Rulesheets) - createdRulesheet := &dtos.Rulesheet{ - ID: uint(1), - Name: "Test", - } + // createdRulesheet := &dtos.Rulesheet{ + // ID: uint(1), + // Name: "test", + // } - srv.On("Create", mock.Anything, createdRulesheet).Return(nil) - v1.NewRulesheets(srv).CreateRulesheet()(c) - assert.Equal(t, http.StatusInternalServerError, w.Code) - }) + // srv.On("Create", mock.Anything, createdRulesheet).Return(nil) + // v1.NewRulesheets(srv).CreateRulesheet()(c) + // assert.Equal(t, http.StatusInternalServerError, w.Code) + // }) - t.Run("Error on define rulesheet entity", func(t *testing.T) { - gin.SetMode(gin.TestMode) + // t.Run("Error on define rulesheet entity", func(t *testing.T) { + // gin.SetMode(gin.TestMode) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) + // w := httptest.NewRecorder() + // c, _ := gin.CreateTestContext(w) - c.Request = &http.Request{ - Header: make(http.Header), - } + // c.Request = &http.Request{ + // Header: make(http.Header), + // } - payload := &payloads.Rulesheet{ - ID: uint(1), - Name: "Test", - } + // payload := &payloads.Rulesheet{ + // ID: uint(1), + // Name: "Test", + // } - bytedPayload, _ := json.Marshal(payload) + // bytedPayload, _ := json.Marshal(payload) - c.Request.Body = ioutil.NopCloser(bytes.NewReader(bytedPayload)) + // c.Request.Body = ioutil.NopCloser(bytes.NewReader(bytedPayload)) - srv := new(mock_services.Rulesheets) + // srv := new(mock_services.Rulesheets) - createdRulesheet := &dtos.Rulesheet{ - ID: uint(1), - Name: "Test", - } + // createdRulesheet := &dtos.Rulesheet{ + // ID: uint(1), + // Name: "Test", + // } - srv.On("Create", mock.Anything, createdRulesheet).Return(errors.New("error")) - v1.NewRulesheets(srv).CreateRulesheet()(c) - assert.Equal(t, http.StatusInternalServerError, w.Code) - }) + // srv.On("Create", mock.Anything, createdRulesheet).Return(errors.New("error")) + // v1.NewRulesheets(srv).CreateRulesheet()(c) + // assert.Equal(t, http.StatusOK, w.Code) + // }) } +// TestRulesheet_UpdateRulesheet is a test function that tests the update functionality of a rulesheet API endpoint +// using the Gin framework. func TestRulesheet_UpdateRulesheet(t *testing.T) { + // It tests the normal flow of the UpdateRulesheet function in the v1 package of a rulesheet API. t.Run("Normal flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -428,6 +484,10 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusOK, w.Code) }) + // It tests the error flow of the UpdateRulesheet function in the v1 package of a rulesheet API. It creates a + // mock service for the rulesheet API and sets expectations for the Get and Update methods of the service. It then + // creates a test context and sets up a request with a payload. Finally, it calls the UpdateRulesheet + // function and asserts that the response code is http.StatusBadRequest. t.Run("Error on check if the rulesheet exists flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -466,6 +526,10 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) + // It's testing the error flow of the UpdateRulesheet function in the v1 package of a rulesheet API. + // The test creates a mock service for the rulesheet API and sets expectations for the Get and Update + // methods of the service. It then creates a test context and sets up the necessary request parameters + // and payload. Finally, it calls the UpdateRulesheet function and asserts that the response code is http.StatusNotFound. t.Run("Error on check if the rulesheet exists flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -506,6 +570,8 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusNotFound, w.Code) }) + // It's testing the error scenario when binding the payload flow in the UpdateRulesheet function of the v1 + // package's Rulesheets struct. t.Run("Error on binding the payload flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -537,6 +603,10 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) + // It is testing the "UpdateRulesheet" function of the "Rulesheets" API endpoint. The test is checking if + // the API returns a status code of 400 (Bad Request) when a required field is missing in the request payload. + // The test creates a mock service for the "Rulesheets" endpoint and sets up the necessary request context and + // payload. It then calls the "UpdateRulesheet" function and checks if the response status code is 400. t.Run("Error on validate required fields flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -574,6 +644,10 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) + // This code tests the error flow of updating a rulesheet with a slug that is already defined. It creates + // a mock service for rulesheets and sets expectations for the Get and Update methods. It then creates a + // test context and sets up aequest with a payload containing a rulesheet with a slug that is already defined. + // It calls the UpdateRulesheet function and asserts that the response code is http.StatusBadRequest. t.Run("Error on slug already defined flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -615,6 +689,11 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) + // It tests the error flow of updating a rulesheet entity in a RESTful API. It creates a mock HTTP request context with a payload + // containing the ID and name of the rulesheet to be updated. It then creates a mock service for + // rulesheets and sets expectations for the Get and Update methods to return a rulesheet and an error, + // respectively. Finally, it calls the UpdateRulesheet function of the v1 package with the mock + // context and asserts that the HTTP response code is equal to 500 (Internal Server Error). t.Run("Error on update entity flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -655,6 +734,7 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, w.Code) }) + // It tests the error status not found flow of the UpdateRulesheet function in the v1 package of a Rulesheets service. t.Run("Error status not found flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -690,52 +770,55 @@ func TestRulesheet_UpdateRulesheet(t *testing.T) { assert.Equal(t, http.StatusNotFound, w.Code) }) - t.Run("Error on define entity Flow", func(t *testing.T) { - gin.SetMode(gin.TestMode) + // t.Run("Error on define entity Flow", func(t *testing.T) { + // gin.SetMode(gin.TestMode) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) + // w := httptest.NewRecorder() + // c, _ := gin.CreateTestContext(w) - c.Request = &http.Request{ - Header: make(http.Header), - } + // c.Request = &http.Request{ + // Header: make(http.Header), + // } - c.Params = gin.Params{gin.Param{Key: "id", Value: "1"}} + // c.Params = gin.Params{gin.Param{Key: "id", Value: "1"}} - rules := make(map[string]interface{}) - rules["rules"] = 0 + // rules := make(map[string]interface{}) + // rules["rules"] = 0 - payload := &payloads.Rulesheet{ - ID: uint(1), - Name: "Test", - Rules: &rules, - } + // payload := &payloads.Rulesheet{ + // ID: uint(1), + // Name: "Test", + // Rules: &rules, + // } - bytedPayload, _ := json.Marshal(payload) + // bytedPayload, _ := json.Marshal(payload) - c.Request.Body = ioutil.NopCloser(bytes.NewReader(bytedPayload)) + // c.Request.Body = ioutil.NopCloser(bytes.NewReader(bytedPayload)) - srv := new(mock_services.Rulesheets) + // srv := new(mock_services.Rulesheets) - oldRulesheet := &dtos.Rulesheet{ - ID: uint(1), - Name: "Test", - } + // oldRulesheet := &dtos.Rulesheet{ + // ID: uint(1), + // Name: "Test", + // } - newRulesheet := &dtos.Rulesheet{ - ID: uint(1), - Name: "Test", - } + // newRulesheet := &dtos.Rulesheet{ + // ID: uint(1), + // Name: "Test", + // } - srv.On("Get", mock.Anything, "1").Return(oldRulesheet, nil) + // srv.On("Get", mock.Anything, "1").Return(oldRulesheet, nil) - srv.On("Update", mock.Anything, *oldRulesheet).Return(newRulesheet, nil) - v1.NewRulesheets(srv).UpdateRulesheet()(c) - assert.Equal(t, http.StatusInternalServerError, w.Code) - }) + // srv.On("Update", mock.Anything, *oldRulesheet).Return(newRulesheet, nil) + // v1.NewRulesheets(srv).UpdateRulesheet()(c) + // assert.Equal(t, http.StatusInternalServerError, w.Code) + // }) } +// estRulesheet_DeleteRulesheet is a test function that tests the DeleteRulesheet function in the Rulesheets API endpoint, +// covering different scenarios and expected HTTP status codes. func TestRulesheet_DeleteRulesheet(t *testing.T) { + // It tests is the normal flow of the DeleteRulesheet function in the v1 package of a Rulesheets service. t.Run("Normal flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -755,6 +838,11 @@ func TestRulesheet_DeleteRulesheet(t *testing.T) { assert.Equal(t, http.StatusNoContent, w.Code) }) + // It's testing the DeleteRulesheet() function of the v1 package's Rulesheets struct. The test is checking if the + // function returns a 404 status code when the Rulesheets service's Delete() function returns false + // and no error. The test creates a mock Rulesheets service and sets the expected behavior of the + // Delete() function. It then creates a new HTTP request context with a parameter "id" set to "1" and + // calls the DeleteRulesheet() function with this context. Finally, it checks if the HTTP response t.Run("Error on delete rulesheet flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -774,6 +862,8 @@ func TestRulesheet_DeleteRulesheet(t *testing.T) { assert.Equal(t, http.StatusNotFound, w.Code) }) + // The test checks if the function returns a 400 Bad Request HTTP status code when an ID is not passed as a parameter. + // It uses a mock service object to simulate the behavior of the actual service. t.Run("Error on id not passed flow", func(t *testing.T) { gin.SetMode(gin.TestMode) @@ -791,6 +881,10 @@ func TestRulesheet_DeleteRulesheet(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) }) + // This test creates a new HTTP request context with a parameter `id` set to `1`. It then creates a mock `Rulesheets` + // service and sets an expectation that the `Delete` method of the service will be called with the argument `"1"`. The + // method is expected to return `false` and an error. The test then calls the `DeleteRulesheet` method + // with the created context and asserts that t.Run("Error on delete rulesheet", func(t *testing.T) { gin.SetMode(gin.TestMode) diff --git a/controllers/v1/v1.go b/controllers/v1/v1.go index 6464baf..1419512 100644 --- a/controllers/v1/v1.go +++ b/controllers/v1/v1.go @@ -7,6 +7,8 @@ import ( var validate = validator.New() +// validatePayload validates a payload using a validator library and returns any validation errors as a +// custom error response. func validatePayload(payload interface{}) *responses.Error { if validationErr := validate.Struct(payload); validationErr != nil { err2, ok := validationErr.(validator.ValidationErrors) diff --git a/database/connection.go b/database/connection.go index 114a441..9b46573 100644 --- a/database/connection.go +++ b/database/connection.go @@ -12,17 +12,18 @@ import ( var db *gorm.DB -// GetConn ... +// GetConn returns a pointer to a GORM db connection. func GetConn() *gorm.DB { return db } -// GetModel ... +// GetModel returns a GORM db object for a given model. func GetModel(value interface{}) *gorm.DB { return db.Model(value) } -// ConnectDB ... +// ConnectDB connects to a MySQL database using a configuration file and logs a message if +// successful. func ConnectDB() { cfg := config.GetConfig() diff --git a/docker-compose.yml b/docker-compose.yml index 9151989..bc9fc7f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,9 @@ services: env_file: - .env db: - image: mysql:8-debian + image: mysql:8.0.26 restart: always + platform: linux/x86_64 ports: - 3306:3306 volumes: diff --git a/docs/docs.go b/docs/docs.go index 7e5b347..9c6ddc7 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,5 +1,5 @@ -// Package docs GENERATED BY SWAG; DO NOT EDIT -// This file was generated by swaggo/swag +// Code generated by swaggo/swag. DO NOT EDIT. + package docs import "github.com/swaggo/swag" @@ -35,7 +35,7 @@ const docTemplate = `{ "Authentication Bearer Token": [] } ], - "description": "Create Rulesheet description", + "description": "Nessa operação cria uma folha de regra no banco de dados do FeatWS. Para realizar a criação é necessário completar a folha de regra, com no mínimo:\n- **nome** no parâmetro *name*;\n- **slug** no parâmetro *slug*;\n- **descrição** no parâmetro *description*.\n\n` + "`" + `` + "`" + `` + "`" + `\n{\n\"description\": \"teste no Swagger da API do FeatWS\",\n\"name\": \"teste Swagger API\",\n\"slug\": \"teste_Swagger_API\"\n}\n` + "`" + `` + "`" + `` + "`" + `\nAmbos esses parâmetros devem ser uma string, ou seja, deve estar entre \"aspas\". Não é possível ter uma folha de regra com o mesmo nome de outra.\nPara criar uma folha de regra basta clicar em **Try it out** , complete a folha de regra com os dados desejados, em seguida, clique em **Execute**.", "consumes": [ "application/json" ], @@ -45,7 +45,7 @@ const docTemplate = `{ "tags": [ "Rulesheet" ], - "summary": "Create Rulesheet", + "summary": "Criação de Folha de Regra", "parameters": [ { "description": "Rulesheet body", @@ -53,7 +53,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } } ], @@ -61,7 +61,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" }, "headers": { "Authorization": { @@ -104,7 +104,7 @@ const docTemplate = `{ "Authentication Bearer Token": [] } ], - "description": "List Rulesheet description", + "description": "É possível listar as folhas de regra de algumas maneiras como veremos a seguir:\n\n- **Sem nenhum parâmetro:** Ao realizar a chamada do endpoint sem a passagem de parâmetros, todas as folhas de regra existentes serão retornadas, contendo informações como nome, ID, e caso estejam disponíveis, descrição e slug.\n- **Usando o *count*:** Ao habilitar o *count* para *True* será retornado do endpoint o número de Folhas de Regras existentes.\n- **Usando o *limit*:** Ao utilizar o parâmetro *limit* deve-se especificar o número máximo de respostas desejadas que serão retornadas pela array.\n- **Usando o *page*:** Ao utilizar o parâmetro *page*, serão retornadas as folhas de regra correspondentes a essa página, onde as folhas são ordenadas em ordem crescente pelo seu ID.\n\nPara listar as folhas de regra basta clicar em **Try it out** , complete com o formado desejados, em seguida, clique em **Execute**.", "consumes": [ "application/json" ], @@ -114,7 +114,7 @@ const docTemplate = `{ "tags": [ "Rulesheet" ], - "summary": "List Rulesheets", + "summary": "Listar as Folhas de Regra", "parameters": [ { "type": "boolean", @@ -141,7 +141,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } }, "headers": { @@ -185,7 +185,7 @@ const docTemplate = `{ "Authentication Bearer Token": [] } ], - "description": "Get Rulesheet by ID description", + "description": "Para se obter a folha de regra por ID, basta clicar em **Try it out** e colocar o ID desejado em *id*. Em seguida, clique em **Execute** e caso o ID exista retornará a folha de regra com o número de ID desejado.", "consumes": [ "application/json" ], @@ -195,7 +195,7 @@ const docTemplate = `{ "tags": [ "Rulesheet" ], - "summary": "Get Rulesheet by ID", + "summary": "Obter Folha de Regra por ID", "parameters": [ { "type": "string", @@ -211,7 +211,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } }, "headers": { @@ -253,7 +253,7 @@ const docTemplate = `{ "Authentication Bearer Token": [] } ], - "description": "Update Rulesheet by ID description", + "description": "Para atualizar ou editar uma folha de regra, é necessário enviar o ID da folha desejada no campo *id*, juntamente com os parâmetros da regra no corpo da solicitação no parâmetro *rulesheet*. Para realizar essa atualização clique no botão **Try it out** e preencher os campos com os dados desejados, em seguida, clicar em **Execute** para enviar a solicitação de atualização.", "consumes": [ "application/json" ], @@ -263,7 +263,7 @@ const docTemplate = `{ "tags": [ "Rulesheet" ], - "summary": "Update Rulesheet by ID", + "summary": "Atualizar Folha de Regra por ID", "parameters": [ { "type": "string", @@ -278,7 +278,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } } ], @@ -288,7 +288,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } }, "headers": { @@ -330,7 +330,7 @@ const docTemplate = `{ "Authentication Bearer Token": [] } ], - "description": "Delete Rulesheet by ID description", + "description": "Para excluir uma folha de regra, é necessário clicar no botão **Try it out** e preencher o campo *id* com o ID da folha de regra que se deseja excluir. Em seguida, clique em **Execute** para enviar a solicitação de exclusão.", "consumes": [ "application/json" ], @@ -340,7 +340,7 @@ const docTemplate = `{ "tags": [ "Rulesheet" ], - "summary": "Delete Rulesheet by ID", + "summary": "Deletar Folha de Regra por ID", "parameters": [ { "type": "string", @@ -389,19 +389,7 @@ const docTemplate = `{ } }, "definitions": { - "v1.Error": { - "type": "object", - "properties": { - "error": {}, - "validation_errors": { - "type": "array", - "items": { - "$ref": "#/definitions/v1.ValidationError" - } - } - } - }, - "v1.Rulesheet": { + "github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet": { "type": "object", "required": [ "name" @@ -445,6 +433,18 @@ const docTemplate = `{ } } }, + "v1.Error": { + "type": "object", + "properties": { + "error": {}, + "validation_errors": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.ValidationError" + } + } + } + }, "v1.ValidationError": { "type": "object", "properties": { @@ -484,7 +484,7 @@ var SwaggerInfo = &swag.Spec{ BasePath: "/api/v1", Schemes: []string{}, Title: "FeatWS API", - Description: "API Project to provide operations to manage FeatWS knowledge repositories rules", + Description: "Este projeto consiste em uma API cujo objetivo é fornecer operações para gerenciamento de repositórios e folhas de regra do sistema FeatWS. Através da API, é possível interagir entre a interface de usuário (UI) e o banco de dados, permitindo diversas interações, como as seguintes:\n- [Post] Criação da Folha de Regra;\n- [Get] Listar das Folhas de Regra;\n- [Get] Obter folha de regra por ID;\n- [Put] Atualizar uma folha de regra por ID;\n- [Delete] Deletar uma folha de regra por ID.\n\nAntes de realizar as requisições no Swagger, é necessário autorizar o acesso clicando no botão **Authorize**, ao lado, e inserindo a senha correspondente. Após inserir o campo **value** e clicar no botão **Authorize**, o Swagger estará disponível para ser utilizado.\n", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, } diff --git a/docs/swagger.json b/docs/swagger.json index 5e1bb00..a20d68c 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "description": "API Project to provide operations to manage FeatWS knowledge repositories rules", + "description": "Este projeto consiste em uma API cujo objetivo é fornecer operações para gerenciamento de repositórios e folhas de regra do sistema FeatWS. Através da API, é possível interagir entre a interface de usuário (UI) e o banco de dados, permitindo diversas interações, como as seguintes:\n- [Post] Criação da Folha de Regra;\n- [Get] Listar das Folhas de Regra;\n- [Get] Obter folha de regra por ID;\n- [Put] Atualizar uma folha de regra por ID;\n- [Delete] Deletar uma folha de regra por ID.\n\nAntes de realizar as requisições no Swagger, é necessário autorizar o acesso clicando no botão **Authorize**, ao lado, e inserindo a senha correspondente. Após inserir o campo **value** e clicar no botão **Authorize**, o Swagger estará disponível para ser utilizado.\n", "title": "FeatWS API", "termsOfService": "http://swagger.io/terms/", "contact": { @@ -28,7 +28,7 @@ "Authentication Bearer Token": [] } ], - "description": "Create Rulesheet description", + "description": "Nessa operação cria uma folha de regra no banco de dados do FeatWS. Para realizar a criação é necessário completar a folha de regra, com no mínimo:\n- **nome** no parâmetro *name*;\n- **slug** no parâmetro *slug*;\n- **descrição** no parâmetro *description*.\n\n```\n{\n\"description\": \"teste no Swagger da API do FeatWS\",\n\"name\": \"teste Swagger API\",\n\"slug\": \"teste_Swagger_API\"\n}\n```\nAmbos esses parâmetros devem ser uma string, ou seja, deve estar entre \"aspas\". Não é possível ter uma folha de regra com o mesmo nome de outra.\nPara criar uma folha de regra basta clicar em **Try it out** , complete a folha de regra com os dados desejados, em seguida, clique em **Execute**.", "consumes": [ "application/json" ], @@ -38,7 +38,7 @@ "tags": [ "Rulesheet" ], - "summary": "Create Rulesheet", + "summary": "Criação de Folha de Regra", "parameters": [ { "description": "Rulesheet body", @@ -46,7 +46,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } } ], @@ -54,7 +54,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" }, "headers": { "Authorization": { @@ -97,7 +97,7 @@ "Authentication Bearer Token": [] } ], - "description": "List Rulesheet description", + "description": "É possível listar as folhas de regra de algumas maneiras como veremos a seguir:\n\n- **Sem nenhum parâmetro:** Ao realizar a chamada do endpoint sem a passagem de parâmetros, todas as folhas de regra existentes serão retornadas, contendo informações como nome, ID, e caso estejam disponíveis, descrição e slug.\n- **Usando o *count*:** Ao habilitar o *count* para *True* será retornado do endpoint o número de Folhas de Regras existentes.\n- **Usando o *limit*:** Ao utilizar o parâmetro *limit* deve-se especificar o número máximo de respostas desejadas que serão retornadas pela array.\n- **Usando o *page*:** Ao utilizar o parâmetro *page*, serão retornadas as folhas de regra correspondentes a essa página, onde as folhas são ordenadas em ordem crescente pelo seu ID.\n\nPara listar as folhas de regra basta clicar em **Try it out** , complete com o formado desejados, em seguida, clique em **Execute**.", "consumes": [ "application/json" ], @@ -107,7 +107,7 @@ "tags": [ "Rulesheet" ], - "summary": "List Rulesheets", + "summary": "Listar as Folhas de Regra", "parameters": [ { "type": "boolean", @@ -134,7 +134,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } }, "headers": { @@ -178,7 +178,7 @@ "Authentication Bearer Token": [] } ], - "description": "Get Rulesheet by ID description", + "description": "Para se obter a folha de regra por ID, basta clicar em **Try it out** e colocar o ID desejado em *id*. Em seguida, clique em **Execute** e caso o ID exista retornará a folha de regra com o número de ID desejado.", "consumes": [ "application/json" ], @@ -188,7 +188,7 @@ "tags": [ "Rulesheet" ], - "summary": "Get Rulesheet by ID", + "summary": "Obter Folha de Regra por ID", "parameters": [ { "type": "string", @@ -204,7 +204,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } }, "headers": { @@ -246,7 +246,7 @@ "Authentication Bearer Token": [] } ], - "description": "Update Rulesheet by ID description", + "description": "Para atualizar ou editar uma folha de regra, é necessário enviar o ID da folha desejada no campo *id*, juntamente com os parâmetros da regra no corpo da solicitação no parâmetro *rulesheet*. Para realizar essa atualização clique no botão **Try it out** e preencher os campos com os dados desejados, em seguida, clicar em **Execute** para enviar a solicitação de atualização.", "consumes": [ "application/json" ], @@ -256,7 +256,7 @@ "tags": [ "Rulesheet" ], - "summary": "Update Rulesheet by ID", + "summary": "Atualizar Folha de Regra por ID", "parameters": [ { "type": "string", @@ -271,7 +271,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } } ], @@ -281,7 +281,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/v1.Rulesheet" + "$ref": "#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet" } }, "headers": { @@ -323,7 +323,7 @@ "Authentication Bearer Token": [] } ], - "description": "Delete Rulesheet by ID description", + "description": "Para excluir uma folha de regra, é necessário clicar no botão **Try it out** e preencher o campo *id* com o ID da folha de regra que se deseja excluir. Em seguida, clique em **Execute** para enviar a solicitação de exclusão.", "consumes": [ "application/json" ], @@ -333,7 +333,7 @@ "tags": [ "Rulesheet" ], - "summary": "Delete Rulesheet by ID", + "summary": "Deletar Folha de Regra por ID", "parameters": [ { "type": "string", @@ -382,19 +382,7 @@ } }, "definitions": { - "v1.Error": { - "type": "object", - "properties": { - "error": {}, - "validation_errors": { - "type": "array", - "items": { - "$ref": "#/definitions/v1.ValidationError" - } - } - } - }, - "v1.Rulesheet": { + "github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet": { "type": "object", "required": [ "name" @@ -438,6 +426,18 @@ } } }, + "v1.Error": { + "type": "object", + "properties": { + "error": {}, + "validation_errors": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.ValidationError" + } + } + } + }, "v1.ValidationError": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index c34e2a0..2d502f2 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,14 +1,6 @@ basePath: /api/v1 definitions: - v1.Error: - properties: - error: {} - validation_errors: - items: - $ref: '#/definitions/v1.ValidationError' - type: array - type: object - v1.Rulesheet: + github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet: properties: description: type: string @@ -38,6 +30,14 @@ definitions: required: - name type: object + v1.Error: + properties: + error: {} + validation_errors: + items: + $ref: '#/definitions/v1.ValidationError' + type: array + type: object v1.ValidationError: properties: error: @@ -53,8 +53,15 @@ info: email: support@swagger.io name: API Support url: http://www.swagger.io/support - description: API Project to provide operations to manage FeatWS knowledge repositories - rules + description: | + Este projeto consiste em uma API cujo objetivo é fornecer operações para gerenciamento de repositórios e folhas de regra do sistema FeatWS. Através da API, é possível interagir entre a interface de usuário (UI) e o banco de dados, permitindo diversas interações, como as seguintes: + - [Post] Criação da Folha de Regra; + - [Get] Listar das Folhas de Regra; + - [Get] Obter folha de regra por ID; + - [Put] Atualizar uma folha de regra por ID; + - [Delete] Deletar uma folha de regra por ID. + + Antes de realizar as requisições no Swagger, é necessário autorizar o acesso clicando no botão **Authorize**, ao lado, e inserindo a senha correspondente. Após inserir o campo **value** e clicar no botão **Authorize**, o Swagger estará disponível para ser utilizado. license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html @@ -66,14 +73,28 @@ paths: post: consumes: - application/json - description: Create Rulesheet description + description: |- + Nessa operação cria uma folha de regra no banco de dados do FeatWS. Para realizar a criação é necessário completar a folha de regra, com no mínimo: + - **nome** no parâmetro *name*; + - **slug** no parâmetro *slug*; + - **descrição** no parâmetro *description*. + + ``` + { + "description": "teste no Swagger da API do FeatWS", + "name": "teste Swagger API", + "slug": "teste_Swagger_API" + } + ``` + Ambos esses parâmetros devem ser uma string, ou seja, deve estar entre "aspas". Não é possível ter uma folha de regra com o mesmo nome de outra. + Para criar uma folha de regra basta clicar em **Try it out** , complete a folha de regra com os dados desejados, em seguida, clique em **Execute**. parameters: - description: Rulesheet body in: body name: Rulesheet required: true schema: - $ref: '#/definitions/v1.Rulesheet' + $ref: '#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet' produces: - application/json responses: @@ -84,7 +105,7 @@ paths: description: token access type: string schema: - $ref: '#/definitions/v1.Rulesheet' + $ref: '#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet' "400": description: Bad Format schema: @@ -102,14 +123,22 @@ paths: security: - Authentication Api Key: [] - Authentication Bearer Token: [] - summary: Create Rulesheet + summary: Criação de Folha de Regra tags: - Rulesheet /rulesheets/: get: consumes: - application/json - description: List Rulesheet description + description: |- + É possível listar as folhas de regra de algumas maneiras como veremos a seguir: + + - **Sem nenhum parâmetro:** Ao realizar a chamada do endpoint sem a passagem de parâmetros, todas as folhas de regra existentes serão retornadas, contendo informações como nome, ID, e caso estejam disponíveis, descrição e slug. + - **Usando o *count*:** Ao habilitar o *count* para *True* será retornado do endpoint o número de Folhas de Regras existentes. + - **Usando o *limit*:** Ao utilizar o parâmetro *limit* deve-se especificar o número máximo de respostas desejadas que serão retornadas pela array. + - **Usando o *page*:** Ao utilizar o parâmetro *page*, serão retornadas as folhas de regra correspondentes a essa página, onde as folhas são ordenadas em ordem crescente pelo seu ID. + + Para listar as folhas de regra basta clicar em **Try it out** , complete com o formado desejados, em seguida, clique em **Execute**. parameters: - description: Total of results in: query @@ -134,7 +163,7 @@ paths: type: string schema: items: - $ref: '#/definitions/v1.Rulesheet' + $ref: '#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet' type: array "400": description: Bad Format @@ -153,14 +182,16 @@ paths: security: - Authentication Api Key: [] - Authentication Bearer Token: [] - summary: List Rulesheets + summary: Listar as Folhas de Regra tags: - Rulesheet /rulesheets/{id}: delete: consumes: - application/json - description: Delete Rulesheet by ID description + description: Para excluir uma folha de regra, é necessário clicar no botão **Try + it out** e preencher o campo *id* com o ID da folha de regra que se deseja + excluir. Em seguida, clique em **Execute** para enviar a solicitação de exclusão. parameters: - description: Rulesheet ID in: path @@ -195,13 +226,15 @@ paths: security: - Authentication Api Key: [] - Authentication Bearer Token: [] - summary: Delete Rulesheet by ID + summary: Deletar Folha de Regra por ID tags: - Rulesheet get: consumes: - application/json - description: Get Rulesheet by ID description + description: Para se obter a folha de regra por ID, basta clicar em **Try it + out** e colocar o ID desejado em *id*. Em seguida, clique em **Execute** e + caso o ID exista retornará a folha de regra com o número de ID desejado. parameters: - description: Rulesheet ID in: path @@ -219,7 +252,7 @@ paths: type: string schema: items: - $ref: '#/definitions/v1.Rulesheet' + $ref: '#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet' type: array "400": description: Bad Format @@ -238,13 +271,17 @@ paths: security: - Authentication Api Key: [] - Authentication Bearer Token: [] - summary: Get Rulesheet by ID + summary: Obter Folha de Regra por ID tags: - Rulesheet put: consumes: - application/json - description: Update Rulesheet by ID description + description: Para atualizar ou editar uma folha de regra, é necessário enviar + o ID da folha desejada no campo *id*, juntamente com os parâmetros da regra + no corpo da solicitação no parâmetro *rulesheet*. Para realizar essa atualização + clique no botão **Try it out** e preencher os campos com os dados desejados, + em seguida, clicar em **Execute** para enviar a solicitação de atualização. parameters: - description: Rulesheet ID in: path @@ -256,7 +293,7 @@ paths: name: rulesheet required: true schema: - $ref: '#/definitions/v1.Rulesheet' + $ref: '#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet' produces: - application/json responses: @@ -268,7 +305,7 @@ paths: type: string schema: items: - $ref: '#/definitions/v1.Rulesheet' + $ref: '#/definitions/github_com_bancodobrasil_featws-api_payloads_v1.Rulesheet' type: array "400": description: Bad Format @@ -287,7 +324,7 @@ paths: security: - Authentication Api Key: [] - Authentication Bearer Token: [] - summary: Update Rulesheet by ID + summary: Atualizar Folha de Regra por ID tags: - Rulesheet securityDefinitions: diff --git a/dtos/rulesheets.go b/dtos/rulesheets.go index 8b82b2e..b808b7f 100644 --- a/dtos/rulesheets.go +++ b/dtos/rulesheets.go @@ -2,19 +2,35 @@ package dtos import ( "encoding/json" - "fmt" v1 "github.com/bancodobrasil/featws-api/payloads/v1" ) -// Rule ... +// Rule type is a struct with three fields: "Condition", "Value", and "Type", all of which are optional and have specific JSON tags. +// +// Property: +// +// - Condition: is a string that represents the condition that needs to be met for the rule to be applied. It could be a comparison operator like ">", "<", ">=","<=", "=", or a logical operator like "AND", "OR", "NOT". +// - Value: is an interface type, which means it can hold any type of value. It's used to store the value of a rule, which can be a string, number, boolean, or any other data type depending on the specific rule being defined. +// - Type: is a string that specifies the type of the value. It can be used to indicate whether the value is a string, number, boolean, or any other data type. This property is optional and can be omitted. type Rule struct { Condition string `json:"condition,omitempty"` Value interface{} `json:"value,omitempty"` Type string `json:"type,omitempty"` } -// Rulesheet ... +// Rulesheet type represents a set of rules and parameters for a system, including features and a version number. +// +// Property: +// - ID: is an unsigned integer that represents the unique identifier of a Rulesheet. +// - Name: is a string property of the Rulesheet struct. It represents the name of the rulesheet. +// - Description: is a string that provides a brief explanation or summary of what the Rulesheet is about. It can be used to give context to the Rulesheet and help users understand its purpose. +// - Slug: is a string that represents a unique identifier for the Rulesheet. It is typically used in URLs to identify and access a specific Rulesheet. +// - HasStringRule - HasStringRule is a boolean property that indicates whether or not the rulesheet contains a string rule. A string rule is a rule that involves comparing or manipulating strings. +// - Version - The version of the rulesheet. It could be a string or a number that represents the version number of the rulesheet. This is useful for tracking changes and updates to the rulesheet over time. +// - Features - Features is a pointer to a slice of maps, where each map represents a feature of the rulesheet. Each map contains key-value pairs where the key is a string representing the name of the feature and the value is an interface{} representing the value of the feature. +// - Parameters: a pointer to a slice of maps, where each map represents a parameter that can be used in the rules defined in the `Rules` property. Each mapcontains key-value pairs where the key is a string representing the name of the parameter and the value is an interface{} +// - Rules: property is a pointer to a map of string keys and interface values. This map represents the set of rules that are associated with the rulesheet. Each key in the map represents a unique rule identifier, and the corresponding value is an interface that can be usedto store any type of data. The use of `interface` allows for flexibility in the type of data that can be stored in the map. type Rulesheet struct { ID uint Name string @@ -27,7 +43,8 @@ type Rulesheet struct { Rules *map[string]interface{} } -// NewRulesheetV1 ... +// NewRulesheetV1 takes in a payload of rulesheet and returns a DTO with the rules converted to a +// specific format. func NewRulesheetV1(payload v1.Rulesheet) (dto Rulesheet, err error) { dto = Rulesheet{ @@ -73,6 +90,7 @@ func NewRulesheetV1(payload v1.Rulesheet) (dto Rulesheet, err error) { return } +// The function takes in an interface and recursively builds a rule based on its type. func buildRule(v interface{}) (interface{}, error) { switch value := v.(type) { case []interface{}: @@ -114,8 +132,10 @@ func buildRule(v interface{}) (interface{}, error) { } return regra, nil + default: - //fmt.Errorf("DEFAULT [%v] {%t}", value, value) - return value, fmt.Errorf("DEFAULT [%v] {%t}", value, value) + // fmt.Errorf("DEFAULT [%v] {%t}", value, value) + // return value, fmt.Errorf("DEFAULT [%v] {%t}", value, value) + return value, nil } } diff --git a/featws-ruller b/featws-ruller new file mode 100755 index 0000000..6dd1a5f Binary files /dev/null and b/featws-ruller differ diff --git a/main.go b/main.go index 779bd7d..42d5638 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,7 @@ import ( ginlogrus "github.com/toorop/gin-logrus" ) +// This function sets up the logging configuration for a Go program. func setupLog() { log.SetFormatter(&log.TextFormatter{FullTimestamp: true}) @@ -29,9 +30,22 @@ func setupLog() { log.SetLevel(log.DebugLevel) } +// The following lines provide instructions for generating Swagger documentation. + +// ------------------------------ + // @title FeatWS API // @version 1.0 -// @description API Project to provide operations to manage FeatWS knowledge repositories rules +// @Description Este projeto consiste em uma API cujo objetivo é fornecer operações para gerenciamento de repositórios e folhas de regra do sistema FeatWS. Através da API, é possível interagir entre a interface de usuário (UI) e o banco de dados, permitindo diversas interações, como as seguintes: +// @Description - [Post] Criação da Folha de Regra; +// @Description - [Get] Listar das Folhas de Regra; +// @Description - [Get] Obter folha de regra por ID; +// @Description - [Put] Atualizar uma folha de regra por ID; +// @Description - [Delete] Deletar uma folha de regra por ID. +// @Description +// @Description Antes de realizar as requisições no Swagger, é necessário autorizar o acesso clicando no botão **Authorize**, ao lado, e inserindo a senha correspondente. Após inserir o campo **value** e clicar no botão **Authorize**, o Swagger estará disponível para ser utilizado. +// @Description + // @termsOfService http://swagger.io/terms/ // @contact.name API Support @@ -54,7 +68,11 @@ func setupLog() { // @x-extension-openapi {"example": "value on a json format"} -// Run start the resolver server with resolverFunc +// end Swagger +// ------------------------------ + +// This is the main function of a Go program that sets up the configuration, database connection, and +// API routes using the Gin framework. func main() { setupLog() @@ -71,10 +89,12 @@ func main() { return } + // Connection with the DataBase containing the Rules and Rulesheets database.ConnectDB() isCmd := false + // Perform the database migration if cfg.Migrate != "" { isCmd = true log.Debug("Migrating database...") @@ -105,11 +125,13 @@ func main() { } } + // Successful migration if isCmd == true { log.Debug("Finished Successfully") os.Exit(0) } + // This code block is setting up monitoring and logging for the Go API using the Gin framework. monitor, err := ginMonitor.New("v1.0.0", ginMonitor.DefaultErrorMessageKey, ginMonitor.DefaultBuckets) if err != nil { log.Panic(err) @@ -124,6 +146,7 @@ func main() { router.Use(ginlogrus.Logger(log.StandardLogger()), gin.Recovery()) router.Use(monitor.Prometheus()) router.GET("metrics", gin.WrapH(promhttp.Handler())) + // Setup Routers of health resources, swagger and home endpoint routes.SetupRoutes(router) configCors := cors.DefaultConfig() diff --git a/models/rulesheet.go b/models/rulesheet.go index 9423a39..c66eaba 100644 --- a/models/rulesheet.go +++ b/models/rulesheet.go @@ -7,7 +7,16 @@ import ( "gorm.io/gorm" ) -// Rulesheet ... +// Rulesheet represents a model with fields for name, description, slug, boolean flag, and timestamps. +// +// Property: +// - `gorm.Model`: This is a struct that provides some common fields for db models such as `ID`, `CreatedAt`, `UpdatedAt`, and `DeletedAt`. +// - Name: is a string that represents the name of a rulesheet. The maximum length of 255 characters and is indexed as unique, two rulesheets can't have the same name. +// - Description: provides additional information or details about the Rulesheet. It can be used to describe the purpose or function of the Rulesheet, or any other relevant information that may be useful to users or developers. +// - Slug: a unique identifier for the Rulesheet. It is typically a short, human-readable string that is used in URLs. +// - HasStringRule: a boolean property that indicates whether the Rulesheet has a string rule or not. It is likely used in the logic of the application to determine how to handle the Rulesheet object. +// - CreatedAt: represents the timestamp of when the Rulesheet was created. It is of type *time.Time, which is a pointer to a time. This property is automatically set by the GORM library when a new Rules. +// - UpdatedAt: represents the timestamp of the last time the `Rulesheet` was updated in the database. This property is useful for tracking when a `Rulesheet` was last modified and can be used in various ways within the application logic. type Rulesheet struct { gorm.Model Name string `gorm:"type:varchar(255);uniqueIndex"` @@ -18,7 +27,7 @@ type Rulesheet struct { UpdatedAt *time.Time } -// NewRulesheetV1 ... +// NewRulesheetV1 creates a new Rulesheet entity from a DTO in Go. func NewRulesheetV1(dto dtos.Rulesheet) (entity Rulesheet, err error) { entity = Rulesheet{ diff --git a/payloads/v1/rulesheet.go b/payloads/v1/rulesheet.go index a59c2d0..4baf30e 100644 --- a/payloads/v1/rulesheet.go +++ b/payloads/v1/rulesheet.go @@ -5,6 +5,19 @@ package v1 // Context map[string]interface{} `json:"context"` // Load []string `json:"load"` // } + +// Rulesheet defines a set of properties for a rulesheet object in Go, including its ID, name, description, slug, version, features, parameters, and rules. +// +// Property: +// - ID: is an unsigned integer that represents the unique identifier of a Rulesheet. +// - Name: The name of the rulesheet. +// - Description - The `Rulesheet` struct is a data structure in Go programming language that represents a set of rules for a system or application. It contains various properties such as `ID`, `Name`, `Description`, `Slug`, `Version`, `Features`, `Parameters`, and `Rules`. +// - Slug: is a string property in the Rulesheet struct that represents a unique identifier for the rulesheet. It is typically used in URLs to identify and access a specific rulesheet. +// - Version: Represents the version number of the rulesheet. +// - HasStringRule - The HasStringRule property is a boolean value that indicates whether the rulesheet contains a string rule or not. If it is true, it means that the rulesheet has at least one rule that involves a string value. If it is false, it means that all the rules in the rulesheet involve +// - Features: It is a pointer to a slice of maps that represent the features of the rulesheet. Each map contains key-value pairs, where the key represents the feature name as a string, and the value is an interface that allows for flexibility in defining different types of feature values. +// - Parameters: It is a pointer to a slice of maps, where each map represents a parameter used in the rules defined within the "Rules" property. Each map consists of key-value pairs, with the key being a string representing the parameter name, and the value being an interface. This design allows for flexibility in defining various types of parameter values. +// - Rules: a pointer to a map of string keys and interface values. This is likely where the actual rules for the rulesheet are stored. The keys in the map would likely correspond to some sort of rule identifier or name, and the values would contain the logic or conditions for. type Rulesheet struct { ID uint `json:"id,omitempty"` Name string `json:"name,omitempty" validate:"required"` diff --git a/repository/repository.go b/repository/repository.go index e1d4f1a..7f8581e 100644 --- a/repository/repository.go +++ b/repository/repository.go @@ -12,13 +12,34 @@ import ( "gorm.io/gorm" ) -// FindOptions ... +// FindOptions type defines options for limiting and paging search results. +// +// Property: +// +// - Limit: an integer that specifies the maximum number of results to be returned by a search or query. It's often used in conjunction with the Page property to implement pagination. +// - Page: an integer that represents the current page number in a paginated result set. It's often used in combination with the Limit property to determine which subset of data to return. type FindOptions struct { Limit int Page int } -// Repository ... +// Repository defines a set of methods for interacting with a database using GORM in Go. +// +// Property: +// +// - GetDB: returns a pointer to a gorm.DB instance that allows performing database operations. +// - Create: creates a new entity of type T in the database. +// - CreateInTransaction: creates a new entity in the database within a transaction. It takes a context.Context and a *gorm.DB as parameters, along with a pointer to the entity to be created. It returns an error if the creation fails. +// - Find: retrieves a list of entities from the repository based on specified criteria in the FindOptions parameter. It returns a slice of pointers to the type T and an error if any occurred during the operation. +// - FindInTransaction: finds multiple entities in a transactional context. It takes a context.Context object, a *gorm.DB object representing the transaction, an interface object representing the entity to be found, and a *FindOptions object representing the options for the find operation. It returns a slice of pointers to the found entities. +// - Count: returns the number of entities in the repository. +// - CountInTransaction: : counts the number of entities in the database within a transaction. It takes a context.Context and a *gorm.DB as parameters, along with an entity interface representing the type of entity to count. It returns the count as an int64 and an error if any occurred. +// - Get: retrieves a single entity of type T from the repository based on the provided ID. It returns the retrieved entity and an error if any occurred during the retrieval process. +// - GetInTransaction: retrieves a single entity of type T from the database within a transaction. It takes a context.Context and a *gorm.DB as parameters and returns a pointer to the retrieved entity of type T and an error if any. +// - Update: updates an existing entity in the repository. It takes a context.Context object and an entity of type T as input and returns the updated entity of type T and an error. If the update is successful, the updated entity is returned; otherwise, an error is returned. +// - UpdateInTransaction: updates an entity of type T in a transactional context. It takes a context.Context and a *gorm.DB as parameters, along with the entity to be updated. It returns the updated entity of type *T and an error if any occurred during the update process. +// - Delete: deletes an entity from the repository based on its ID. It takes a context.Context object and the ID of the entity to be deleted as input parameters. It returns a boolean value indicating whether the entity was successfully deleted or not, along with an error object if any. +// - DeleteInTransaction:deletes an entity with the given ID from the database within a transaction. It takes a context.Context object, a *gorm.DB object representing the transaction, and the ID of the entity to be deleted. It returns a boolean indicating whether the entity was successfully deleted and an error. type Repository[T any] interface { GetDB() *gorm.DB Create(ctx context.Context, entity *T) error @@ -35,11 +56,19 @@ type Repository[T any] interface { DeleteInTransaction(ctx context.Context, db *gorm.DB, id string) (deleted bool, err error) } -// Repository ... +// Repository creates a generic repository struct that contains a pointer to a GORM database. +// +// Property: +// - db: it's a pointer to a gorm.DB object, which is a database ORM library for Go. It is used to interact with a database and perform CRUD operations on the data. type repository[T any] struct { db *gorm.DB } +// const is a block defining a set of constants that represent the different types of database +// operations that can be performed by the repository. These constants are used as labels for tracing +// and logging purposes, allowing for easier identification of the specific operation being performed. +// For example, when a `Create` operation is performed, the `create` constant is used to label the +// corresponding log or trace entry. const ( create = "repo-create" find = "repo-find" @@ -49,24 +78,33 @@ const ( delete = "repo-delete" ) -// Create ... +// Create it's a function thats creating a new entity of type T in the database. It first creates a new session +// using the `newSession` function, which returns a new `gorm.DB` instance with a new context. Then, it +// calls the `CreateInTransaction` function with the new context, the new session, and a pointer to the +// entity to be created. Finally, it returns the result of the `CreateInTransaction` function, which is +// an error if the creation fails. func (r *repository[T]) Create(ctx context.Context, entity *T) error { db := r.newSession(ctx) return r.CreateInTransaction(ctx, db, entity) } -// CreateInTransaction ... +// CreateInTransaction is a method of the repository struct that creates a new entity of type T in the +// database within a transaction. It takes a context.Context object, a *gorm.DB object representing the +// transaction, and a pointer to the entity to be created as input parameters. func (r *repository[T]) CreateInTransaction(ctx context.Context, db *gorm.DB, entity *T) error { // add the span of database query on the root span of the context span := utils.GenerateSpanTracer(ctx, create) defer span() + // This code block creates a new entity of type T in the database using the Create method of the gorm.DB object. + // The Create method returns a *gorm.DB that provides information about the operation's result, including any errors encountered. result := db.Create(&entity) if result.Error != nil { log.WithContext(ctx).Errorf("error on insert the result into model: %v", result.Error) return result.Error } + //The code verifies the success of an entity's database insertion by checking the number of affected rows. if result.RowsAffected != 1 { err := errors.New("error on insert not inserted") log.WithContext(ctx).Error(err.Error()) @@ -76,19 +114,30 @@ func (r *repository[T]) CreateInTransaction(ctx context.Context, db *gorm.DB, en return nil } -// Find ... +// Find is a method of the `repository` struct that finds a list of entities from the +// repository based on specified criteria in the `FindOptions` parameter. It takes a `context.Context` +// object, an `interface{}` object representing the entity to be found, and a pointer to a +// `FindOptions` object representing the options for the find operation as input parameters. It returns +// a slice of pointers to the type `T` and an error if any occurred during the operation. func (r *repository[T]) Find(ctx context.Context, entity interface{}, options *FindOptions) (list []*T, err error) { db := r.newSession(ctx) return r.FindInTransaction(ctx, db, entity, options) } -// FindInTransaction ... +// FindInTransaction is a method of a generic repository that finds a list of entities in a database +// transaction using GORM. It takes in a context, a GORM database instance, an entity interface, and +// optional find options. It starts a new span on the context for tracing purposes, applies any +// specified find options to the database query, executes the query using GORM's Find method, and +// returns the resulting list of entities or an error if there was one. func (r *repository[T]) FindInTransaction(ctx context.Context, db *gorm.DB, entity interface{}, options *FindOptions) (list []*T, err error) { // add the span of database query on the root span of the context tracer := telemetry.GetTracer(ctx) ctx, span := tracer.Start(ctx, "repo-find", trace.WithSpanKind(trace.SpanKindInternal)) defer span.End() + // The code snippet above checks if the options parameter is not nil. If it's not nil, it assigns a + // default limit of 10 and verifies if the Limit field of options is not 0. If Limit is not 0, it assigns + // the value of options.Limit to the limit variable. Finally, it applies the limit to the database query using db.Limit(limit). if options != nil { limit := 10 if options.Limit != 0 { @@ -100,6 +149,8 @@ func (r *repository[T]) FindInTransaction(ctx context.Context, db *gorm.DB, enti } } + // The code below queries the database using the Find method, searching for parameters corresponding + // to entity, and the results are returned in list. result := db.Find(&list, entity) err = result.Error @@ -111,13 +162,19 @@ func (r *repository[T]) FindInTransaction(ctx context.Context, db *gorm.DB, enti return } -// Count ... +// Count is a method that counts the number of entities in a db table. It takes a context and an entity as input parameters and returns the +// count of entities and an error if any. It creates a new database session and calls the +// CountInTransaction method passing the context, db session, and entity as parameters to count +// the number of entities in the table. func (r *repository[T]) Count(ctx context.Context, entity interface{}) (count int64, err error) { db := r.newSession(ctx) return r.CountInTransaction(ctx, db, entity) } -// CountInTransaction ... +// CountInTransaction is a method that counts the number of records in a db table that match a given +// entity. It takes a context, a db connection, and an entity as input parameters. It uses the OpenTelemetry +// library to create a span for the db query and logs any errors that occur during the query. The method +// returns the count of matching records and any errors encountered during the query. func (r *repository[T]) CountInTransaction(ctx context.Context, db *gorm.DB, entity interface{}) (count int64, err error) { // add the span of database query on the root span of the context tracer := telemetry.GetTracer(ctx) @@ -126,6 +183,8 @@ func (r *repository[T]) CountInTransaction(ctx context.Context, db *gorm.DB, ent count = 0 + // The code is used to query a database using the Where method with a specific entity as a filter. It's + // used to determine the number of records that match the provided entity, and the result is stored in the count variable. result := db.Where(entity).Count(&count) err = result.Error @@ -137,19 +196,25 @@ func (r *repository[T]) CountInTransaction(ctx context.Context, db *gorm.DB, ent return } -// Get ... +// Get method is a function that takes a context and an ID as input parameters and returns a pointer to an +// entity of type T and an error. func (r *repository[T]) Get(ctx context.Context, id string) (entity *T, err error) { db := r.newSession(ctx) return r.GetInTransaction(ctx, db, id) } -// Get ... +// GetInTransaction is a method that retrieves a single entity of type T from a database based on the provided +// ID within a transaction. The GORM library is used to execute the query in the database transaction and return +// the retrieved entity along with any errors encountered during the query. OpenTelemetry is used to add a span +// to the root span of the context, enabling tracing of the database query. func (r *repository[T]) GetInTransaction(ctx context.Context, db *gorm.DB, id string) (entity *T, err error) { // add the span of database query on the root span of the context tracer := telemetry.GetTracer(ctx) ctx, span := tracer.Start(ctx, "repo-get", trace.WithSpanKind(trace.SpanKindInternal)) defer span.End() + // Using the "db" object to query the database and retrieve the first record that matches the given "id". + // The result of the query is stored in the "entity" variable. result := db.First(&entity, id) err = result.Error @@ -161,19 +226,25 @@ func (r *repository[T]) GetInTransaction(ctx context.Context, db *gorm.DB, id st return } -// Update ... +// Update is a method for a generic repository type `T`. This method takes a context and an entity `T` as input parameters and returns a pointer to the updated +// entity of type `T` and an error. func (r *repository[T]) Update(ctx context.Context, entity T) (updated *T, err error) { db := r.newSession(ctx) return r.UpdateInTransaction(ctx, db, entity) } -// UpdateInTransaction ... +// UpdateInTransaction is a generic repository type `T`. This method takes in a context, a GORM db instance, and an entity of type `T`. +// It updates the entity in the db using the `Save` method of GORM and returns the updated entity along with any +// error encountered during the update. It also adds a span to the root span of the context for tracing purposes. func (r *repository[T]) UpdateInTransaction(ctx context.Context, db *gorm.DB, entity T) (updated *T, err error) { // add the span of database query on the root span of the context tracer := telemetry.GetTracer(ctx) ctx, span := tracer.Start(ctx, "repo-update", trace.WithSpanKind(trace.SpanKindInternal)) defer span.End() + // This is a entity to a db using the GORM library called "db". The "Save" method is being called on the "Model" + // object with a reference to the entity being saved passed as a pointer. The result of the save + // operation is being stored in the "result" variable. result := db.Model(entity).Save(&entity) err = result.Error @@ -187,13 +258,19 @@ func (r *repository[T]) UpdateInTransaction(ctx context.Context, db *gorm.DB, en return } -// Delete ... +// Delete is a method for deleting a record from a db using a given ID. It creates a new db session using the context provided, and then calls the +// `DeleteInTransaction` method with the same context and the session to perform the actual deletion. +// The method returns a boolean value indicating whether the deletion was successful or not, and an +// error if any occurred during the process. func (r *repository[T]) Delete(ctx context.Context, id string) (deleted bool, err error) { db := r.newSession(ctx) return r.DeleteInTransaction(ctx, db, id) } -// DeleteInTransaction ... +// DeleteInTransaction is method takes a context, a GORM database instance, and an ID as input parameters. It starts a new +// span on the root span of the context using OpenTelemetry tracing. It then calls the `Get` method of +// the repository to retrieve the entity with the given ID. If the entity is not found, it returns +// `deleted=true`. If the entity is found, it deletes it using the GORM `Delete` method. func (r *repository[T]) DeleteInTransaction(ctx context.Context, db *gorm.DB, id string) (deleted bool, err error) { // add the span of database query on the root span of the context tracer := telemetry.GetTracer(ctx) @@ -225,10 +302,15 @@ func (r *repository[T]) DeleteInTransaction(ctx context.Context, db *gorm.DB, id return } +// newSession is a method that returns a new GORM db session with a context that is passed +// as an argument. The session is created using the `Session` method of the `gorm.DB` type and a new +// instance of the generic type `T` is used as the model for the session. func (r *repository[T]) newSession(ctx context.Context) *gorm.DB { return r.GetDB().Session(&gorm.Session{}).Model(new(T)).WithContext(ctx) } +// GetDB is a method that returns a pointer to a `gorm.DB` object, which is a db handle used +// to interact with a db. The `r.db` field is assumed to be a `gorm.DB` object that was previously set on the repository instance. func (r *repository[T]) GetDB() *gorm.DB { return r.db } diff --git a/repository/rulesheets.go b/repository/rulesheets.go index f55552e..c38452e 100644 --- a/repository/rulesheets.go +++ b/repository/rulesheets.go @@ -6,18 +6,22 @@ import ( "gorm.io/gorm" ) -// Rulesheets ... +// Rulesheets is defining an interface that has a single method signature `Repository[models.Rulesheet]` that is defined in repository.go. type Rulesheets interface { Repository[models.Rulesheet] } +// rulesheets contains an array of "Rulesheet" objects within a "repository" field. +// +// Property: +// - repository: is a field of the `rulesheets` struct which is an array of `models.Rulesheet`. It's used to store multiple rulesheets in a single instance of the `rulesheets` struct. type rulesheets struct { repository[models.Rulesheet] } var instanceRulesheets Rulesheets -// GetRulesheets ... +// GetRulesheets returns an instance of the Rulesheets struct, creating it if it doesn't already exist. func GetRulesheets() Rulesheets { if instanceRulesheets == nil { i, err := newRulesheets() @@ -29,12 +33,13 @@ func GetRulesheets() Rulesheets { return instanceRulesheets } +// newRulesheets creates a new instance of Rulesheets and returns it along with any errors encountered. func newRulesheets() (Rulesheets, error) { db := database.GetConn() return NewRulesheetsWithDB(db) } -// NewRulesheetsWithDB ... +// NewRulesheetsWithDB creates a new instance of Rulesheets with a given db connection and performs db migration. func NewRulesheetsWithDB(db *gorm.DB) (Rulesheets, error) { err := db.AutoMigrate(&models.Rulesheet{}) if err != nil { diff --git a/responses/v1/error.go b/responses/v1/error.go index ffc5f9f..f5d603c 100644 --- a/responses/v1/error.go +++ b/responses/v1/error.go @@ -1,12 +1,24 @@ package v1 -// Error ... +// Error contains an error message and optional validation errors. +// +// Property: +// +// - Error: an interface type that can hold any value, such as error messages or objects, to describe the occurred error. It allows for providing detailed information about the error to users or developers. +// +// - ValidationErrors: is a slice of ValidationError structs that holds validation errors encountered during request processing. The omitempty tag indicates that it will only appear in the JSON response if there are actual validation errors. type Error struct { Error interface{} `json:"error"` ValidationErrors []ValidationError `json:"validation_errors,omitempty"` } -// ValidationError ... +// ValidationError represents an error that occurred during validation, including the field, +// tag, and error message. +// +// Property: +// - Field: is a string property that represents the name of the field that has a validation error. +// - Tag: a string property representing the violated validation rule. For instance, if a required field is missing, the Tag property would be "required". +// - Error: a string property that describes the error message related to the validation error. It provides details about what went wrong during the validation process. type ValidationError struct { Field string `json:"field"` Tag string `json:"tag"` diff --git a/responses/v1/find.go b/responses/v1/find.go index 68c2e49..5e557c9 100644 --- a/responses/v1/find.go +++ b/responses/v1/find.go @@ -1,6 +1,9 @@ package v1 // FindResult is the result of a find request. +// +// Property: +// - Count: is a field of the FindResult struct that represents the number of occurrences found during a search operation. It is of type int64, which means it can hold integervalues up to 64 bits in size. The `json:"count,omitempty"` tag is used to specify the field name in JSON. type FindResult struct { Count int64 `json:"count,omitempty"` } diff --git a/responses/v1/rulesheet.go b/responses/v1/rulesheet.go index 46aba51..1a834c6 100644 --- a/responses/v1/rulesheet.go +++ b/responses/v1/rulesheet.go @@ -2,7 +2,20 @@ package v1 import "github.com/bancodobrasil/featws-api/dtos" -// Rulesheet ... +// Rulesheet type is a struct that contains various fields related to a set of rules, including its +// ID, name, description, slug, version, features, parameters, and rules. +// +// Property: +// +// - FindResult: This is an embedded struct that contains fields related to the result of a search operation. +// - ID: is an unsigned integer that represents the unique identifier of a Rulesheet. +// - Name: The name of the rulesheet. +// - Description - The `Rulesheet` struct is a data structure in Go programming language that represents a set of rules for a system or application. It contains various properties such as `ID`, `Name`, `Description`, `Slug`, `Version`, `Features`, `Parameters`, and `Rules`. +// - Slug: is a string property in the Rulesheet struct that represents a unique identifier for the rulesheet. It is typically used in URLs to identify and access a specific rulesheet. +// - Version: Represents the version number of the rulesheet. +// - Features: It is a pointer to a slice of maps that represent the features of the rulesheet. Each map contains key-value pairs, where the key represents the feature name as a string, and the value is an interface that allows for flexibility in defining different types of feature values. +// - Parameters: It is a pointer to a slice of maps, where each map represents a parameter used in the rules defined within the "Rules" property. Each map consists of key-value pairs, with the key being a string representing the parameter name, and the value being an interface. This design allows for flexibility in defining various types of parameter values. +// - Rules: a pointer to a map of string keys and interface values. This is likely where the actual rules for the rulesheet are stored. The keys in the map would likely correspond to some sort of rule identifier or name, and the values would contain the logic or conditions for. type Rulesheet struct { FindResult ID uint `json:"id,omitempty"` @@ -15,7 +28,7 @@ type Rulesheet struct { Rules *map[string]interface{} `json:"rules,omitempty"` } -// NewRulesheet ... +// NewRulesheet creates a new Rulesheet object by copying data from a DTO object. func NewRulesheet(dto *dtos.Rulesheet) Rulesheet { return Rulesheet{ ID: dto.ID, diff --git a/routes/api/v1/rulesheet.go b/routes/api/v1/rulesheet.go index 5d1943e..360f884 100644 --- a/routes/api/v1/rulesheet.go +++ b/routes/api/v1/rulesheet.go @@ -8,18 +8,28 @@ import ( "github.com/gin-gonic/gin" ) +// rulesheetsRouter sets up the routing for CRUD operations on rulesheets using Gin framework func rulesheetsRouter(router *gin.RouterGroup) { cfg := config.GetConfig() + // Repository enables the code to access the data repository and perform CRUD operations on the rulesheets. repository := repository.GetRulesheets() + // The project connects to GitLab to access the rulesheets and perform CRUD operations gitlabService := services.NewGitlab(cfg) + // The service variable is creating a new instance of the Rulesheets service from the services package, + // it takes the parameters: repository and gitlabService. These parameters allow the service to access + // the data repository and the GitLab service service := services.NewRulesheets(repository, gitlabService) + // The controller is creating a new instance of the "Rulesheets" controller from the "v1" + // package and passing an instance of the service as a parameter. This allows the controller + // to have access to the business logic and functionalities provided by the service. controller := v1.NewRulesheets(service) + // These are the API endpoints router.POST("/", controller.CreateRulesheet()) router.GET("/", controller.GetRulesheets()) router.GET("/:id", controller.GetRulesheet()) diff --git a/routes/api/v1/v1.go b/routes/api/v1/v1.go index c7ed550..8f1b33b 100644 --- a/routes/api/v1/v1.go +++ b/routes/api/v1/v1.go @@ -8,6 +8,7 @@ import ( // Router define routes the API V1 func Router(router *gin.RouterGroup) { + // This code is defining the routes for the API v1. router.Use(goauthgin.Authenticate()) rulesheetsRouter(router.Group("/rulesheets")) //rpcRouter(router.Group("/")) diff --git a/routes/health/health.go b/routes/health/health.go index a7f0d93..b2f1ad3 100644 --- a/routes/health/health.go +++ b/routes/health/health.go @@ -5,7 +5,7 @@ import ( "github.com/gin-gonic/gin" ) -// Router ... +// Router sets up two routes for health checks using the Gin framework in Go. func Router(router *gin.RouterGroup) { healthController := controllers.NewHealthController() diff --git a/routes/home.go b/routes/home.go index dfa5af3..b7421db 100644 --- a/routes/home.go +++ b/routes/home.go @@ -5,6 +5,7 @@ import ( "github.com/gin-gonic/gin" ) +// homeRouter sets up a GET route for the home page using the Gin web framework in Go. func homeRouter(router *gin.RouterGroup) { router.GET("/", controllers.HomeHandler) } diff --git a/ruller b/ruller new file mode 100755 index 0000000..6dd1a5f Binary files /dev/null and b/ruller differ diff --git a/services/gitlab.go b/services/gitlab.go index 7681820..70ceb52 100644 --- a/services/gitlab.go +++ b/services/gitlab.go @@ -17,18 +17,27 @@ import ( log "github.com/sirupsen/logrus" ) -// Gitlab ... +// Gitlab interface defines methods for saving, filling, and connecting to a Gitlab client. +// +// Property: +// - Save: A method that takes a pointer to a Rulesheet DTO (Data Transfer Object) and a commit message as input parameters and returns an error. This method is responsible for saving the Rulesheet to Gitlab repository with the provided commit message. +// - Fill: The method is a function that takes a pointer to a `Rulesheet` DTO and fills it with data from a GitLab repository. It returns an error if there's any issue while filling the `Rulesheet`. +// - Connect: Connect is a method that returns a pointer to a gitlab.Client and an error. It's used to establish a connection to the GitLab server. type Gitlab interface { Save(rulesheet *dtos.Rulesheet, commitMessage string) error Fill(rulesheet *dtos.Rulesheet) error Connect() (*gitlab.Client, error) } +// gitlabService struct holds a pointer to a config.Config object. +// +// Property: +// - cfg: The `cfg` property is a pointer to a `config.Config` struct, which likely contains configuration settings for a GitLab service. type gitlabService struct { cfg *config.Config } -// NewGitlab ... +// NewGitlab creates a new instance of the Gitlab service using the provided configuration. func NewGitlab(cfg *config.Config) Gitlab { return &gitlabService{ cfg: cfg, @@ -55,7 +64,7 @@ func (gs *gitlabService) Save(rulesheet *dtos.Rulesheet, commitMessage string) e return err } - proj, resp, err := git.Projects.GetProject(fmt.Sprintf("%s/%s%s", ns.Path, gs.cfg.GitlabPrefix, rulesheet.Name), &gitlab.GetProjectOptions{}) + proj, resp, err := git.Projects.GetProject(fmt.Sprintf("%s/%s%s", ns.FullPath, gs.cfg.GitlabPrefix, rulesheet.Slug), &gitlab.GetProjectOptions{}) if err != nil { if resp.StatusCode != http.StatusNotFound { log.Errorf("Failed to fetch project: %v", err) @@ -63,7 +72,7 @@ func (gs *gitlabService) Save(rulesheet *dtos.Rulesheet, commitMessage string) e } proj, _, err = git.Projects.CreateProject(&gitlab.CreateProjectOptions{ - Name: gitlab.String(fmt.Sprintf("%s%s", cfg.GitlabPrefix, rulesheet.Name)), + Name: gitlab.String(fmt.Sprintf("%s%s", cfg.GitlabPrefix, rulesheet.Slug)), NamespaceID: &ns.ID, }) if err != nil { @@ -239,6 +248,7 @@ func (gs *gitlabService) Save(rulesheet *dtos.Rulesheet, commitMessage string) e // return nil // } +// createOrUpdateGitlabFileCommitAction this function creates or updates a GitLab file commit action with the specified content. func createOrUpdateGitlabFileCommitAction(git *gitlab.Client, proj *gitlab.Project, ref string, filename string, content string) (*gitlab.CommitActionOptions, error) { action, err := defineCreateOrUpdateGitlabFileAction(git, proj, ref, filename) if err != nil { @@ -252,6 +262,8 @@ func createOrUpdateGitlabFileCommitAction(git *gitlab.Client, proj *gitlab.Proje }, nil } +// defineCreateOrUpdateGitlabFileAction this function determines whether to create or update a GitLab file based on whether it already +// exists or not. func defineCreateOrUpdateGitlabFileAction(git *gitlab.Client, proj *gitlab.Project, ref string, fileName string) (*gitlab.FileActionValue, error) { _, resp, err := git.RepositoryFiles.GetFile(proj.ID, fileName, &gitlab.GetFileOptions{ Ref: gitlab.String(ref), @@ -268,6 +280,11 @@ func defineCreateOrUpdateGitlabFileAction(git *gitlab.Client, proj *gitlab.Proje return gitlab.FileAction(gitlab.FileUpdate), nil } +// Fill is a method in a GitLab service that fills a `Rulesheet` struct with data from GitLab. It first +// checks if a GitLab token is provided, and if not, it returns nil. It then connects to GitLab using the +// provided token and fetches the namespace and project associated with the provided GitLab namespace and +// prefix. It fetches the version, features, parameters, and rules data from the project's default branch +// and populates the corresponding fields in the `Rulesheet` struct. func (gs *gitlabService) Fill(rulesheet *dtos.Rulesheet) (err error) { if gs.cfg.GitlabToken == "" { return nil @@ -285,7 +302,7 @@ func (gs *gitlabService) Fill(rulesheet *dtos.Rulesheet) (err error) { return } - proj, _, err := git.Projects.GetProject(fmt.Sprintf("%s/%s%s", ns.Path, gs.cfg.GitlabPrefix, rulesheet.Name), &gitlab.GetProjectOptions{}) + proj, _, err := git.Projects.GetProject(fmt.Sprintf("%s/%s%s", ns.FullPath, gs.cfg.GitlabPrefix, rulesheet.Slug), &gitlab.GetProjectOptions{}) if err != nil { log.Errorf("Failed to fetch project: %v", err) return @@ -379,6 +396,9 @@ func (gs *gitlabService) Fill(rulesheet *dtos.Rulesheet) (err error) { return } +// Connect this method creates a new GitLab client using the GitLab API token and URL provided in the `gs.cfg` +// configuration object. If the client creation is successful, it returns the GitLab client object, +// otherwise it returns an error. func (gs *gitlabService) Connect() (*gitlab.Client, error) { git, err := gitlab.NewClient(gs.cfg.GitlabToken, gitlab.WithBaseURL(gs.cfg.GitlabURL)) @@ -389,6 +409,7 @@ func (gs *gitlabService) Connect() (*gitlab.Client, error) { return git, nil } +// gitlabLoadJSON loads a JSON file from a GitLab project and decodes it into a given Go struct. func gitlabLoadJSON(git *gitlab.Client, proj *gitlab.Project, ref string, fileName string, result interface{}) error { rawDecodedText, err := gitlabLoadString(git, proj, ref, fileName) if err != nil { @@ -403,6 +424,11 @@ func gitlabLoadJSON(git *gitlab.Client, proj *gitlab.Project, ref string, fileNa return nil } +// gitlabLoadString that takes in a `gitlab.Client` object, a `gitlab.Project` object, a `ref` string, +// and a `fileName` string as parameters. The function uses the `gitlab` package to fetch a file from a +// GitLab repository using the provided `git` and `proj` objects, with the specified `ref` and `fileName`. +// If the file is not found, an empty byte slice is returned. If the file is found, it is decoded from base64 +// and returned as a byte slice. func gitlabLoadString(git *gitlab.Client, proj *gitlab.Project, ref string, fileName string) ([]byte, error) { file, resp, err := git.RepositoryFiles.GetFile(proj.ID, fileName, &gitlab.GetFileOptions{ Ref: gitlab.String(ref), diff --git a/services/gitlab_test.go b/services/gitlab_test.go index 17f12be..09fdd47 100644 --- a/services/gitlab_test.go +++ b/services/gitlab_test.go @@ -15,6 +15,7 @@ import ( "github.com/xanzy/go-gitlab" ) +// The function returns a pointer to a configuration object with predefined values for a Gitlab server. func SetupConfig(url *httptest.Server) *config.Config { cfg := config.Config{ GitlabURL: url.URL, @@ -26,16 +27,18 @@ func SetupConfig(url *httptest.Server) *config.Config { return &cfg } +// The function returns a pointer to a Rulesheet struct with predefined values. func SetupRulesheet() *dtos.Rulesheet { rulesheet := dtos.Rulesheet{ ID: 1, + Slug: "test", Name: "Test", Description: "Test", } return &rulesheet } -// Functions for test Save function +// This is a test function for saving and creating a project using Gitlab API. func TestSaveAndCreateProject(t *testing.T) { dto := SetupRulesheet() @@ -75,6 +78,7 @@ func TestSaveAndCreateProject(t *testing.T) { } +// This is a test function for saving and updating a project using Gitlab API. func TestSaveAndUpdateProject(t *testing.T) { dto := SetupRulesheet() @@ -84,12 +88,12 @@ func TestSaveAndUpdateProject(t *testing.T) { //Retrieving namespace if r.URL.Path == "/api/v4/namespaces/"+namespace { - w.Write([]byte(`{"id":1,"name":"teste", "path":"test"}`)) + w.Write([]byte(`{"id":1,"name":"teste", "full_path":"test"}`)) return } // Get project - if r.URL.Path == "/api/v4/projects/test%2Fprefix-Test" { + if r.URL.Path == "/api/v4/projects/test%2Fprefix-test" { w.Write([]byte(`{"id":1,"description:null","name":"test"}`)) return } @@ -126,6 +130,7 @@ func TestSaveAndUpdateProject(t *testing.T) { } +// This is a test function that tests the creation of test files in GitLab using Go. func TestSaveTestFilesCreation(t *testing.T) { dto := SetupRulesheet() @@ -176,6 +181,7 @@ func TestSaveTestFilesCreation(t *testing.T) { } } +// This is a test function that checks if a GitLab API call saves test files with features correctly. func TestSaveTestFilesCreationWithFeatures(t *testing.T) { dto := SetupRulesheet() @@ -308,6 +314,7 @@ func TestSaveTestFilesCreationWithParameters(t *testing.T) { } } +// This is test function that tests the creation of test files with a rule interface using Gitlab API. func TestSaveTestFilesCreationWithRuleInterface(t *testing.T) { dto := SetupRulesheet() @@ -376,6 +383,8 @@ func TestSaveTestFilesCreationWithRuleInterface(t *testing.T) { } } +// This is a test function that tests the saving of test files creation with a rule string in a GitLab +// repository. func TestSaveTestFilesCreationWithRuleString(t *testing.T) { dto := SetupRulesheet() @@ -432,6 +441,7 @@ func TestSaveTestFilesCreationWithRuleString(t *testing.T) { } } +// This test function that tests the saving of test files with a string rule in a GitLab repository. func TestSaveTestFilesCreationWithStringRule(t *testing.T) { dto := SetupRulesheet() @@ -490,6 +500,7 @@ func TestSaveTestFilesCreationWithStringRule(t *testing.T) { } } +// This function tests the creation of test files with default rules in Gitlab. func TestSaveTestFilesCreationWithDefaultRule(t *testing.T) { dto := SetupRulesheet() @@ -567,6 +578,8 @@ func TestSaveTestFilesCreationWithDefaultRule(t *testing.T) { } } +// This test function that tests the Save method of a Gitlab service by setting up a mock server +// and asserting that the correct data is sent in the HTTP requests. func TestSaveTestFilesUpdate(t *testing.T) { dto := SetupRulesheet() @@ -574,7 +587,7 @@ func TestSaveTestFilesUpdate(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/api/v4/namespaces/"+namespace { - w.Write([]byte(`{"id":1,"name":"teste", "path":"testpath"}`)) + w.Write([]byte(`{"id":1,"name":"teste", "full_path":"testpath"}`)) return } if r.Method == "POST" && r.URL.Path == "/api/v4/projects" { @@ -629,18 +642,19 @@ func TestSaveTestFilesUpdate(t *testing.T) { } } -// Functions to test fill function +// This is a test function that tests the functionality of filling a data transfer object with data +// from GitLab API. func TestFill(t *testing.T) { namespace := "test" s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/api/v4/namespaces/"+namespace { - w.Write([]byte(`{"id":1,"name":"teste", "path":"testpath"}`)) + w.Write([]byte(`{"id":1,"name":"teste", "full_path":"testpath"}`)) return } - if r.Method == "GET" && r.URL.Path == "/api/v4/projects/testpath/prefix-Test" { + if r.Method == "GET" && r.URL.Path == "/api/v4/projects/testpath/prefix-test" { w.Write([]byte(`{"id":1,"description":"testeDesc","name":"teste"}`)) return } @@ -757,11 +771,11 @@ func TestFillJSON(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/api/v4/namespaces/"+namespace { - w.Write([]byte(`{"id":1,"name":"teste", "path":"testpath"}`)) + w.Write([]byte(`{"id":1,"name":"teste", "full_path":"testpath"}`)) return } - if r.Method == "GET" && r.URL.Path == "/api/v4/projects/testpath/prefix-Test" { + if r.Method == "GET" && r.URL.Path == "/api/v4/projects/testpath/prefix-test" { w.Write([]byte(`{"id":1,"description":"testeDesc","name":"teste"}`)) return } @@ -872,7 +886,7 @@ func TestFillJSON(t *testing.T) { } } -// Functions to test fill function +// This is a unit test function that tests the FillRulesSlices function. func TestFillRulesSlices(t *testing.T) { dto := SetupRulesheet() @@ -880,11 +894,11 @@ func TestFillRulesSlices(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/api/v4/namespaces/"+namespace { - w.Write([]byte(`{"id":1,"name":"teste", "path":"testpath"}`)) + w.Write([]byte(`{"id":1,"name":"teste", "full_path":"testpath"}`)) return } - if r.Method == "GET" && r.URL.Path == "/api/v4/projects/testpath/prefix-Test" { + if r.Method == "GET" && r.URL.Path == "/api/v4/projects/testpath/prefix-test" { w.Write([]byte(`{"id":1,"description":"testeDesc","name":"teste"}`)) return } @@ -961,7 +975,8 @@ func TestFillRulesSlices(t *testing.T) { } } -// Testing Errors +// This is a test function that checks if an error is returned when attempting to save a Gitlab +// token that is nil. func TestSaveGitlabTokenNil(t *testing.T) { dto := SetupRulesheet() @@ -978,6 +993,7 @@ func TestSaveGitlabTokenNil(t *testing.T) { } +// This is a function that tests for an error when fetching a namespace in Gitlab. func TestSaveErrorOnFetchNameSpace(t *testing.T) { dto := SetupRulesheet() @@ -1006,6 +1022,7 @@ func TestSaveErrorOnFetchNameSpace(t *testing.T) { } +// This is a test function that checks if an error is returned when attempting to fetch a project. func TestSaveErrorOnFetchProject(t *testing.T) { dto := SetupRulesheet() @@ -1038,6 +1055,7 @@ func TestSaveErrorOnFetchProject(t *testing.T) { } +// This is a function that tests for an error when creating a project using Gitlab API. func TestSaveErrorOnCreateProject(t *testing.T) { dto := SetupRulesheet() @@ -1076,6 +1094,7 @@ func TestSaveErrorOnCreateProject(t *testing.T) { } +// This is a Go function that tests for an error when resolving a version in a Gitlab project. func TestSaveErrorOnResolveVersion(t *testing.T) { dto := SetupRulesheet() @@ -1119,6 +1138,8 @@ func TestSaveErrorOnResolveVersion(t *testing.T) { } +// This's a test function for saving a rulesheet to GitLab and checking for errors related to parsing +// the version. func TestSaveErrorOnParseVersion(t *testing.T) { dto := SetupRulesheet() diff --git a/services/rulesheets.go b/services/rulesheets.go index bbbf09e..d1f6166 100644 --- a/services/rulesheets.go +++ b/services/rulesheets.go @@ -11,13 +11,24 @@ import ( log "github.com/sirupsen/logrus" ) -// FindOptions ... +// FindOptions type defines options for limiting and paging search results. +// +// Property +// - Limit: property is an integer that specifies the maximum number of results to be returned by a search or query. It is often used in conjunction with the `Page` property to implement pagination. For example, if `Limit` is set to 10 and there are 50 results, the +// - Page: property is an integer that represents the current page number in a paginated result set. It is often used in combination with the `Limit` property to determine which subset of data to return. For example, if `Limit` is set to 10 and `Page` is set type FindOptions struct { Limit int Page int } -// Rulesheets ... +// Rulesheets defines an interface for CRUD operations on rulesheets. +// Property: +// - Create: Create is a method that creates a new rulesheet in the database. It takes a context and a pointer to a dtos.Rulesheet object as input and returns an error if the operation fails. +// - Find: method is used to retrieve a list of Rulesheets based on a filter and options. The filter parameter is used to specify the criteria for selecting Rulesheets, while the options parameter is used to specify additional options such as sorting and pagination. The method returns a slice of Rulesheet DTOs and +// - Count: method is used to count the number of documents that match a given filter in the database collection. It takes a context.Context object and an entity interface{} as input parameters and returns the count of documents as an int64 and an error object. The entity parameter is used to specify the type of +// - Get: method is used to retrieve a single Rulesheet entity by its unique identifier (id). It takes in a context.Context object and the id of the Rulesheet to be retrieved as parameters, and returns a pointer to the dtos.Rulesheet object and an error object. If the Rulesheet +// - Update: is a method defined in the Rulesheets interface that takes a context.Context and a dtos.Rulesheet entity as input parameters and returns a pointer to a dtos.Rulesheet and an error. This method is used to update an existing rulesheet entity in the data store. +// - Delete: method is used to delete a rulesheet from the database. It takes a context.Context and a string id as input parameters and returns a boolean value and an error. The boolean value indicates whether the deletion was successful or not. The error value indicates any error that occurred during the deletion process. type Rulesheets interface { Create(context.Context, *dtos.Rulesheet) error Find(ctx context.Context, filter interface{}, options *FindOptions) ([]*dtos.Rulesheet, error) @@ -27,12 +38,17 @@ type Rulesheets interface { Delete(ctx context.Context, id string) (bool, error) } +// rulesheets contains a Gitlab service and a repository for rulesheets. +// +// Property: +// - gitlabService: It seems that `gitlabService` is a variable of type `Gitlab`, which could be a struct or an interface. It is likely used to interact with GitLab API or services related to GitLab. However, without more context or code, it's difficult to determine its exact purpose. +// - repository: property is of type `repository.Rulesheets`. It is likely a reference to a repository object that contains information about rulesheets, such as their names, contents, and metadata. This object may be used to perform various operations on the rulesheets, such as retrieving, updating, type rulesheets struct { gitlabService Gitlab repository repository.Rulesheets } -// NewRulesheets ... +// NewRulesheets creates a new instance of a rulesheets struct with a given repository and Gitlab service. func NewRulesheets(repository repository.Rulesheets, gitlabService Gitlab) Rulesheets { return rulesheets{ repository: repository, @@ -40,7 +56,13 @@ func NewRulesheets(repository repository.Rulesheets, gitlabService Gitlab) Rules } } -// CreateRulesheet ... +// CreateRulesheet is responsible for creating a new rulesheet. It takes in a `context.Context` object +// and a `*dtos.Rulesheet` object as parameters. It first converts the `*dtos.Rulesheet` object to a +// `models.Rulesheet` object using the `models.NewRulesheetV1` function. It then generates a slug for +// the rulesheet if it doesn't already have one. It creates the rulesheet in the repository using the +// `rs.repository.Create` function and saves it to GitLab using the `rs.gitlabService.Save` function. +// Finally, it fills the `*dtos.Rulesheet` object with GitLab information using the`rs.gitlabService.Fill` +// function. If any errors occur during the process, it logs the error and returns it. func (rs rulesheets) Create(ctx context.Context, rulesheetDTO *dtos.Rulesheet) (err error) { rulesheet, _ := models.NewRulesheetV1(*rulesheetDTO) @@ -72,7 +94,10 @@ func (rs rulesheets) Create(ctx context.Context, rulesheetDTO *dtos.Rulesheet) ( return } -// FetchRulesheets ... +// Find is responsible for finding rulesheets based on a filter and returning them as an array +// of `dtos.Rulesheet` objects. It takes in a `context.Context` object, a filter interface, and a +// `FindOptions` object as parameters. The `FindOptions` object is used to specify the limit and page +// number for pagination. func (rs rulesheets) Find(ctx context.Context, filter interface{}, options *FindOptions) (result []*dtos.Rulesheet, err error) { var opts *repository.FindOptions = nil @@ -99,7 +124,13 @@ func (rs rulesheets) Find(ctx context.Context, filter interface{}, options *Find return } -// Count ... +// Count is a method of the `rulesheets` struct that implements the `Rulesheets` interface. It +// takes a `context.Context` object and an `entity` interface{} as input parameters and returns the +// count of documents as an `int64` and an error object. The `entity` parameter is used to specify the +// type of entity to count in the database collection. The function calls the `Count` method of the +// `repository` property of the `rulesheets` struct, passing in the `ctx` and `entity` parameters. If +// an error occurs during the count operation, the function logs the error and returns it. Otherwise, +// it returns the count of documents. func (rs rulesheets) Count(ctx context.Context, entity interface{}) (count int64, err error) { count, err = rs.repository.Count(ctx, entity) @@ -111,7 +142,14 @@ func (rs rulesheets) Count(ctx context.Context, entity interface{}) (count int64 return } -// FetchRulesheet ... +// Get function is a method of the `rulesheets` struct that implements the `Rulesheets` +// interface. It takes a `context.Context` object and a `string` id as input parameters and returns a +// pointer to a `dtos.Rulesheet` object and an error object. The function retrieves a single rulesheet +// entity by its unique identifier (id) from the repository using the `rs.repository.Get` function. It +// then converts the `models.Rulesheet` object to a `dtos.Rulesheet` object using the `newRulesheetDTO` +// function. Finally, it fills the `*dtos.Rulesheet` object with GitLab information using the +// `rs.gitlabService.Fill` function. If any errors occur during the process, it logs the error and +// returns it. func (rs rulesheets) Get(ctx context.Context, id string) (result *dtos.Rulesheet, err error) { entity, err := rs.repository.Get(ctx, id) @@ -133,7 +171,9 @@ func (rs rulesheets) Get(ctx context.Context, id string) (result *dtos.Rulesheet return } -// UpdateRulesheet ... +// UpdateRulesheet function is a method of the `rulesheets` struct that implements the `Rulesheets` +// interface. It takes a `context.Context` object and a `dtos.Rulesheet` object as input parameters and +// returns a pointer to a `dtos.Rulesheet` object and an error object. func (rs rulesheets) Update(ctx context.Context, rulesheetDTO dtos.Rulesheet) (result *dtos.Rulesheet, err error) { entity, _ := models.NewRulesheetV1(rulesheetDTO) @@ -155,6 +195,9 @@ func (rs rulesheets) Update(ctx context.Context, rulesheetDTO dtos.Rulesheet) (r return } +// Delete function is a method of the `rulesheets` struct that implements the `Rulesheets` +// interface. It takes a `context.Context` object and a `string` id as input parameters and returns a +// boolean value and an error object. The function is responsible for deleting a rulesheet from the db. func (rs rulesheets) Delete(ctx context.Context, id string) (bool, error) { db := rs.repository.GetDB() @@ -194,6 +237,7 @@ func (rs rulesheets) Delete(ctx context.Context, id string) (bool, error) { return true, tx.Commit().Error } +// The function creates a new DTO for a rulesheet entity func newRulesheetDTO(entity *models.Rulesheet) *dtos.Rulesheet { return &dtos.Rulesheet{ ID: entity.ID, diff --git a/services/rulesheets_test.go b/services/rulesheets_test.go index 04e5a02..1162d1b 100644 --- a/services/rulesheets_test.go +++ b/services/rulesheets_test.go @@ -20,6 +20,7 @@ import ( "gorm.io/gorm" ) +// This's a unit test that checks if an error is returned when a Gitlab service fails to fill a rulesheet entity. func TestGetWithErrorOnFill(t *testing.T) { ctx := context.Background() @@ -46,6 +47,8 @@ func TestGetWithErrorOnFill(t *testing.T) { } } +// This test function tests the successful retrieval of a rulesheet entity from a +// repository and its filling with data from a Gitlab service. func TestGetSucess(t *testing.T) { ctx := context.Background() @@ -67,6 +70,8 @@ func TestGetSucess(t *testing.T) { } } +// This's a Get function of a Rulesheets service, which tests for an error on +// model creation. func TestGetWithErrorOnCreateModel(t *testing.T) { ctx := context.Background() @@ -89,6 +94,7 @@ func TestGetWithErrorOnCreateModel(t *testing.T) { } } +// The function tests the Create method of the Rulesheets service with an error on fill. func TestCreateWithErrorOnFill(t *testing.T) { ctx := context.Background() @@ -111,6 +117,8 @@ func TestCreateWithErrorOnFill(t *testing.T) { } } +// TestCreateSuccess is a function that tests the successful creation of a rulesheet entity and its +// corresponding GitLab repository. func TestCreateSuccess(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -133,6 +141,7 @@ func TestCreateSuccess(t *testing.T) { } +// This tests the Create method of a Rulesheets service with an expected error. func TestCreateWithError(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -155,6 +164,7 @@ func TestCreateWithError(t *testing.T) { } } +// This checks if an error is returned when attempting to save a new rulesheet entity. func TestCreateWithErroOnSave(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -177,6 +187,7 @@ func TestCreateWithErroOnSave(t *testing.T) { } } +// This test Update method of a Rulesheets service, checking if an error is returned when there is an error on saving the data to Gitlab. func TestUpdateWithErrorOnSave(t *testing.T) { ctx := context.Background() @@ -199,6 +210,7 @@ func TestUpdateWithErrorOnSave(t *testing.T) { } } +// This is a tests the successful finding of a rulesheet entity using mocked repository and service objects. func TestFindSuccess(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -220,6 +232,7 @@ func TestFindSuccess(t *testing.T) { } } +// This tests the error handling of the Find method in a Rulesheets service. func TestFindWithError(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -242,6 +255,7 @@ func TestFindWithError(t *testing.T) { } +// This tests the Count method of a Rulesheets service. func TestCountSuccess(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -260,6 +274,7 @@ func TestCountSuccess(t *testing.T) { } } +// This tests the error handling of the Count method in a Rulesheets service. func TestCountWithError(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -278,6 +293,7 @@ func TestCountWithError(t *testing.T) { } } +// This tests the successful update of a rulesheet entity using mocked repository and Gitlab services. func TestUpdateSuccess(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -299,6 +315,7 @@ func TestUpdateSuccess(t *testing.T) { } } +// The function tests the update method of a Rulesheets service with an error scenario. func TestUpdateWithError(t *testing.T) { ctx := context.Background() dto := &dtos.Rulesheet{ @@ -349,6 +366,8 @@ func TestUpdateWithError(t *testing.T) { // } +// This is a test for testing the successful deletion of a rulesheet entity using GORM +// and a mock database connection. func TestDeleteSuccess(t *testing.T) { // Init fake db connection conn, mocks, err := sqlmock.New() @@ -393,6 +412,8 @@ func TestDeleteSuccess(t *testing.T) { } } +// This is a test function for the Delete method of a Rulesheets service, which tests for an error +// during the update of a Rulesheet entity. func TestDeleteWithError(t *testing.T) { // Init fake db connection conn, mocks, err := sqlmock.New() @@ -437,6 +458,8 @@ func TestDeleteWithError(t *testing.T) { } } +// This is a test function for the Delete method of a Rulesheets service, which tests the rollback +// behavior when an error occurs during a database Get operation. func TestDeleteWithRollBackOnGet(t *testing.T) { // Init fake db connection conn, mocks, err := sqlmock.New() @@ -478,6 +501,8 @@ func TestDeleteWithRollBackOnGet(t *testing.T) { } } +// This is a test function for the Delete method in the Rulesheets service, which tests the +// rollback behavior in case of an error during the delete operation. func TestDeleteWithRollBackOnDeleteInTransaction(t *testing.T) { // Init fake db connection conn, mocks, err := sqlmock.New() diff --git a/utils/telemetry.go b/utils/telemetry.go index 056fc4b..7467d75 100644 --- a/utils/telemetry.go +++ b/utils/telemetry.go @@ -4,14 +4,20 @@ import ( "context" telemetry "github.com/bancodobrasil/gin-telemetry" + "github.com/spf13/viper" "go.opentelemetry.io/otel/trace" ) -// GenerateSpanTracer ... +// GenerateSpanTracer generates a span tracer for telemetry purposes, but only if middleware is enable. func GenerateSpanTracer(ctx context.Context, name string) func() { - tracer := telemetry.GetTracer(ctx) - _, span := tracer.Start(ctx, name, trace.WithSpanKind(trace.SpanKindInternal)) - return func() { - span.End() + MiddlewareDisabled := viper.GetViper().GetBool("TELEMETRY_DISABLED") + if !MiddlewareDisabled { + tracer := telemetry.GetTracer(ctx) + _, span := tracer.Start(ctx, name, trace.WithSpanKind(trace.SpanKindInternal)) + return func() { + span.End() + } } + + return func() {} }