From f90f0504bcdce2dad67aeb9a7c4b221014435fd3 Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Tue, 9 Mar 2021 08:34:22 -0300 Subject: [PATCH] feat: Add swagger spec for webhooks endpoint (#23) --- Makefile | 5 +- README.md | 45 +++-- cmd/postmand/main.go | 12 +- docs/docs.go | 377 ++++++++++++++++++++++++++++++++++++++++ docs/swagger.json | 314 +++++++++++++++++++++++++++++++++ docs/swagger.yaml | 206 ++++++++++++++++++++++ entity.go | 4 +- entity_test.go | 5 - go.mod | 3 + go.sum | 68 +++++++- http/handler/error.go | 2 +- http/handler/webhook.go | 54 +++++- 12 files changed, 1053 insertions(+), 42 deletions(-) create mode 100644 docs/docs.go create mode 100644 docs/swagger.json create mode 100644 docs/swagger.yaml diff --git a/Makefile b/Makefile index 6e9f4e7..82038e9 100644 --- a/Makefile +++ b/Makefile @@ -32,4 +32,7 @@ run-server: run-worker: go run cmd/postmand/main.go worker -.PHONY: lint test mock download-golang-migrate-binary db-migrate db-test-migrate run-server run-worker +swag-init: + swag init -g cmd/postmand/main.go --parseDependency + +.PHONY: lint test mock download-golang-migrate-binary db-migrate db-test-migrate run-server run-worker swag-init diff --git a/README.md b/README.md index def63df..857983f 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,23 @@ make run-migrate # create database schema make run-server # run the server ``` +### Run the worker + +The worker is responsible to delivery content to the webhooks. + +#### Docker + +```bash +docker run --env POSTMAND_DATABASE_URL='postgres://user:pass@host.docker.internal:5432/postmand?sslmode=disable' allisson/postmand worker +``` + +#### Local + +```bash +make run-worker +go run cmd/postmand/main.go worker +``` + ### Create a new webhook The fields delivery_attempt_timeout/retry_min_backoff/retry_max_backoff are in seconds. @@ -116,29 +133,6 @@ curl --location --request POST 'http://localhost:8000/v1/deliveries' \ } ``` -### Run the worker - -The worker is responsible to delivery content to the webhooks. - -#### Docker - -```bash -docker run --env POSTMAND_DATABASE_URL='postgres://user:pass@host.docker.internal:5432/postmand?sslmode=disable' allisson/postmand worker -{"level":"info","ts":1615236411.115703,"caller":"service/worker.go:74","msg":"worker-started"} -{"level":"info","ts":1615236411.1158803,"caller":"http/server.go:60","msg":"http-server-listen-and-server"} -{"level":"info","ts":1615236411.687701,"caller":"service/worker.go:42","msg":"worker-delivery-attempt-created","id":"d72719d6-5a79-4df7-a2c2-2029ab0e1848","webhook_id":"a6e9a525-ac5a-488c-b118-bd7327ce6d8d","delivery_id":"bc76122c-e56b-45c7-8dc3-b80a861191d5","response_status_code":200,"execution_duration":547,"success":true} -``` - -#### Local - -```bash -make run-worker -go run cmd/postmand/main.go worker -{"level":"info","ts":1615236411.115703,"caller":"service/worker.go:74","msg":"worker-started"} -{"level":"info","ts":1615236411.1158803,"caller":"http/server.go:60","msg":"http-server-listen-and-server"} -{"level":"info","ts":1615236411.687701,"caller":"service/worker.go:42","msg":"worker-delivery-attempt-created","id":"d72719d6-5a79-4df7-a2c2-2029ab0e1848","webhook_id":"a6e9a525-ac5a-488c-b118-bd7327ce6d8d","delivery_id":"bc76122c-e56b-45c7-8dc3-b80a861191d5","response_status_code":200,"execution_duration":547,"success":true} -``` - ### Get deliveries ```bash @@ -231,6 +225,10 @@ curl --location --request GET 'http://localhost:8000/v1/delivery-attempts/d72719 } ``` +### Swagger docs + +The swagger spec is available at http://localhost:8000/swagger/index.html. + ### Health check The health check server is running on port defined by envvar POSTMAND_HEALTH_CHECK_HTTP_PORT (defaults to 8001). @@ -254,4 +252,3 @@ All environment variables is defined on file local.env. ``` docker build -f Dockerfile -t postmand . ``` - diff --git a/cmd/postmand/main.go b/cmd/postmand/main.go index c66345c..01fd23a 100644 --- a/cmd/postmand/main.go +++ b/cmd/postmand/main.go @@ -6,6 +6,7 @@ import ( "time" "github.com/allisson/go-env" + _ "github.com/allisson/postmand/docs" "github.com/allisson/postmand/http" "github.com/allisson/postmand/http/handler" "github.com/allisson/postmand/repository" @@ -13,6 +14,7 @@ import ( "github.com/go-chi/chi/v5" "github.com/jmoiron/sqlx" _ "github.com/joho/godotenv/autoload" + httpSwagger "github.com/swaggo/http-swagger" "github.com/urfave/cli/v2" "go.uber.org/zap" ) @@ -27,6 +29,10 @@ func healthcheckServer(db *sqlx.DB, logger *zap.Logger) { server.Run() } +// @title Postmand API +// @version 1.0 +// @description Simple webhook delivery system powered by Golang and PostgreSQL. +// @BasePath /v1 func main() { // Setup logger logger, err := zap.NewProduction() @@ -108,6 +114,7 @@ func main() { deliveryHandler := handler.NewDelivery(deliveryService, logger) deliveryAttemptHandler := handler.NewDeliveryAttempt(deliveryAttemptService, logger) + httpPort := env.GetInt("POSTMAND_HTTP_PORT", 8000) mux := http.NewRouter(logger) mux.Route("/v1/webhooks", func(r chi.Router) { r.Get("/", webhookHandler.List) @@ -126,8 +133,11 @@ func main() { r.Get("/", deliveryAttemptHandler.List) r.Get("/{delivery_attempt_id}", deliveryAttemptHandler.Get) }) + mux.Get("/swagger/*", httpSwagger.Handler( + httpSwagger.URL("/swagger/doc.json"), //The url pointing to API definition" + )) - server := http.NewServer(mux, env.GetInt("POSTMAND_HTTP_PORT", 8000), logger) + server := http.NewServer(mux, httpPort, logger) server.Run() return nil diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..0b53998 --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,377 @@ +// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// This file was generated by swaggo/swag + +package docs + +import ( + "bytes" + "encoding/json" + "strings" + + "github.com/alecthomas/template" + "github.com/swaggo/swag" +) + +var doc = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{.Description}}", + "title": "{{.Title}}", + "contact": {}, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/webhooks": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "List webhooks", + "parameters": [ + { + "type": "integer", + "description": "The limit indicates the maximum number of items to return", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "The offset indicates the starting position of the query in relation to the complete set of unpaginated items", + "name": "offset", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/WebhookList" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Add an webhook", + "parameters": [ + { + "description": "Add webhook", + "name": "webhook", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Webhook" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/Webhook" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/webhooks/{webhook_id}": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Show a webhook", + "parameters": [ + { + "type": "string", + "description": "Webhook ID", + "name": "webhook_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Webhook" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Update an webhook", + "parameters": [ + { + "type": "string", + "description": "Webhook ID", + "name": "webhook_id", + "in": "path", + "required": true + }, + { + "description": "Update webhook", + "name": "webhook", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Webhook" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Webhook" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "delete": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Delete an webhook", + "parameters": [ + { + "type": "string", + "description": "Webhook ID", + "name": "webhook_id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Error": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "details": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "Webhook": { + "type": "object", + "properties": { + "active": { + "type": "boolean" + }, + "content_type": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "delivery_attempt_timeout": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "max_delivery_attempts": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "retry_max_backoff": { + "type": "integer" + }, + "retry_min_backoff": { + "type": "integer" + }, + "secret_token": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "url": { + "type": "string" + }, + "valid_status_codes": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "WebhookList": { + "type": "object", + "properties": { + "limit": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "webhooks": { + "type": "array", + "items": { + "$ref": "#/definitions/Webhook" + } + } + } + } + } +}` + +type swaggerInfo struct { + Version string + Host string + BasePath string + Schemes []string + Title string + Description string +} + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = swaggerInfo{ + Version: "1.0", + Host: "", + BasePath: "/v1", + Schemes: []string{}, + Title: "Postmand API", + Description: "Simple webhook delivery system powered by Golang and PostgreSQL.", +} + +type s struct{} + +func (s *s) ReadDoc() string { + sInfo := SwaggerInfo + sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1) + + t, err := template.New("swagger_info").Funcs(template.FuncMap{ + "marshal": func(v interface{}) string { + a, _ := json.Marshal(v) + return string(a) + }, + }).Parse(doc) + if err != nil { + return doc + } + + var tpl bytes.Buffer + if err := t.Execute(&tpl, sInfo); err != nil { + return doc + } + + return tpl.String() +} + +func init() { + swag.Register(swag.Name, &s{}) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..9e2f94d --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,314 @@ +{ + "swagger": "2.0", + "info": { + "description": "Simple webhook delivery system powered by Golang and PostgreSQL.", + "title": "Postmand API", + "contact": {}, + "version": "1.0" + }, + "basePath": "/v1", + "paths": { + "/webhooks": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "List webhooks", + "parameters": [ + { + "type": "integer", + "description": "The limit indicates the maximum number of items to return", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "The offset indicates the starting position of the query in relation to the complete set of unpaginated items", + "name": "offset", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/WebhookList" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Add an webhook", + "parameters": [ + { + "description": "Add webhook", + "name": "webhook", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Webhook" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/Webhook" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/webhooks/{webhook_id}": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Show a webhook", + "parameters": [ + { + "type": "string", + "description": "Webhook ID", + "name": "webhook_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Webhook" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Update an webhook", + "parameters": [ + { + "type": "string", + "description": "Webhook ID", + "name": "webhook_id", + "in": "path", + "required": true + }, + { + "description": "Update webhook", + "name": "webhook", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Webhook" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Webhook" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "delete": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "webhooks" + ], + "summary": "Delete an webhook", + "parameters": [ + { + "type": "string", + "description": "Webhook ID", + "name": "webhook_id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Error": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "details": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "Webhook": { + "type": "object", + "properties": { + "active": { + "type": "boolean" + }, + "content_type": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "delivery_attempt_timeout": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "max_delivery_attempts": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "retry_max_backoff": { + "type": "integer" + }, + "retry_min_backoff": { + "type": "integer" + }, + "secret_token": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "url": { + "type": "string" + }, + "valid_status_codes": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "WebhookList": { + "type": "object", + "properties": { + "limit": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "webhooks": { + "type": "array", + "items": { + "$ref": "#/definitions/Webhook" + } + } + } + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..83a356c --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,206 @@ +basePath: /v1 +definitions: + Error: + properties: + code: + type: integer + details: + type: string + message: + type: string + type: object + Webhook: + properties: + active: + type: boolean + content_type: + type: string + created_at: + type: string + delivery_attempt_timeout: + type: integer + id: + type: string + max_delivery_attempts: + type: integer + name: + type: string + retry_max_backoff: + type: integer + retry_min_backoff: + type: integer + secret_token: + type: string + updated_at: + type: string + url: + type: string + valid_status_codes: + items: + type: integer + type: array + type: object + WebhookList: + properties: + limit: + type: integer + offset: + type: integer + webhooks: + items: + $ref: '#/definitions/Webhook' + type: array + type: object +info: + contact: {} + description: Simple webhook delivery system powered by Golang and PostgreSQL. + title: Postmand API + version: "1.0" +paths: + /webhooks: + get: + consumes: + - application/json + parameters: + - description: The limit indicates the maximum number of items to return + in: query + name: limit + type: integer + - description: The offset indicates the starting position of the query in relation + to the complete set of unpaginated items + in: query + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/WebhookList' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/Error' + summary: List webhooks + tags: + - webhooks + post: + consumes: + - application/json + parameters: + - description: Add webhook + in: body + name: webhook + required: true + schema: + $ref: '#/definitions/Webhook' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/Webhook' + "400": + description: Bad Request + schema: + $ref: '#/definitions/Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/Error' + summary: Add an webhook + tags: + - webhooks + /webhooks/{webhook_id}: + delete: + consumes: + - application/json + parameters: + - description: Webhook ID + in: path + name: webhook_id + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + $ref: '#/definitions/Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/Error' + summary: Delete an webhook + tags: + - webhooks + get: + consumes: + - application/json + parameters: + - description: Webhook ID + in: path + name: webhook_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/Webhook' + "404": + description: Not Found + schema: + $ref: '#/definitions/Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/Error' + summary: Show a webhook + tags: + - webhooks + put: + consumes: + - application/json + parameters: + - description: Webhook ID + in: path + name: webhook_id + required: true + type: string + - description: Update webhook + in: body + name: webhook + required: true + schema: + $ref: '#/definitions/Webhook' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/Webhook' + "400": + description: Bad Request + schema: + $ref: '#/definitions/Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/Error' + summary: Update an webhook + tags: + - webhooks +swagger: "2.0" diff --git a/entity.go b/entity.go index f840d1e..c434aac 100644 --- a/entity.go +++ b/entity.go @@ -36,14 +36,14 @@ type Webhook struct { RetryMaxBackoff int `json:"retry_max_backoff" db:"retry_max_backoff"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` -} +} //@name Webhook // Validate implements ozzo validation Validatable interface func (w Webhook) Validate() error { return validation.ValidateStruct(&w, validation.Field(&w.Name, validation.Required, validation.Length(3, 255)), validation.Field(&w.URL, validation.Required, is.URL), - validation.Field(&w.ContentType, validation.Required, validation.In("application/x-www-form-urlencoded", "application/json")), + validation.Field(&w.ContentType, validation.Required), validation.Field(&w.ValidStatusCodes, validation.Required), validation.Field(&w.MaxDeliveryAttempts, validation.Required, validation.Min(1)), validation.Field(&w.DeliveryAttemptTimeout, validation.Required, validation.Min(1)), diff --git a/entity_test.go b/entity_test.go index 080a423..c7a4f81 100644 --- a/entity_test.go +++ b/entity_test.go @@ -33,11 +33,6 @@ func TestWebhook(t *testing.T) { Webhook{ID: uuid.New(), Name: strings.Repeat("A", 300), URL: "https://httpbin.org/post", ContentType: "application/json", ValidStatusCodes: pq.Int32Array{200, 201}, MaxDeliveryAttempts: 1, DeliveryAttemptTimeout: 1, RetryMinBackoff: 1, RetryMaxBackoff: 1}, `{"name":"the length must be between 3 and 255"}`, }, - { - "Content type invalid option", - Webhook{ID: uuid.New(), Name: "AAA", URL: "https://httpbin.org/post", ContentType: "text/html", ValidStatusCodes: pq.Int32Array{200, 201}, MaxDeliveryAttempts: 1, DeliveryAttemptTimeout: 1, RetryMinBackoff: 1, RetryMaxBackoff: 1}, - `{"content_type":"must be a valid value"}`, - }, } for _, tt := range tests { t.Run(tt.kind, func(t *testing.T) { diff --git a/go.mod b/go.mod index b4c9a67..810ba9d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.16 require ( github.com/DATA-DOG/go-txdb v0.1.3 + github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 github.com/allisson/go-env v0.3.0 github.com/go-chi/chi/v5 v5.0.0 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 @@ -16,6 +17,8 @@ require ( github.com/lib/pq v1.10.0 github.com/steinfletcher/apitest v1.5.2 github.com/stretchr/testify v1.7.0 + github.com/swaggo/http-swagger v1.0.0 + github.com/swaggo/swag v1.7.0 github.com/urfave/cli/v2 v2.3.0 go.uber.org/zap v1.16.0 ) diff --git a/go.sum b/go.sum index d0aef4b..3b925d2 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,16 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/DATA-DOG/go-txdb v0.1.3 h1:R4v6OuOcy2O147e2zHxU0B4NDtF+INb5R9q/CV7AEMg= github.com/DATA-DOG/go-txdb v0.1.3/go.mod h1:DhAhxMXZpUJVGnT+p9IbzJoRKvlArO2pkHjnGX7o0n0= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/allisson/go-env v0.3.0 h1:tUcH3zFXCIT2MLWQp84mV5iifpbG1+poXlqDgRJIYy0= github.com/allisson/go-env v0.3.0/go.mod h1:It6Dwy/LfOpLY/uIJiBpqQFifCosR4vPbnoBt4RYSkM= github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= @@ -70,6 +78,7 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -93,11 +102,27 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= +github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi/v5 v5.0.0 h1:DBPx88FjZJH3FsICfDAfIfnb7XxKIYVGG6lOPlhENAg= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA= +github.com/go-openapi/spec v0.20.0 h1:HGLc8AJ7ynOxwv0Lq4TsnwLsWMawHAYiJIFzbcML86I= +github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY= +github.com/go-openapi/swag v0.19.12 h1:Bc0bnY2c3AoF7Gc+IMIAQQsD8fLHjHpc19wXvYuayQI= +github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M= github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -218,6 +243,8 @@ github.com/jmoiron/sqlx v1.3.1 h1:aLN7YINNZ7cYOPK3QC83dbM6KT0NMqVMw961TqrejlE= github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -230,12 +257,12 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -243,6 +270,10 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= @@ -259,6 +290,8 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -304,8 +337,15 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM= +github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E= +github.com/swaggo/http-swagger v1.0.0 h1:ksYgVBCYmAaxFsGVGojlPROgYfiQQSllETTWMtHJHTo= +github.com/swaggo/http-swagger v1.0.0/go.mod h1:cKIcshBU9yEAnfWv6ZzVKSsEf8h5ozxB8/zHQWyOQ/8= +github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E= +github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo= github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -315,6 +355,7 @@ github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -395,6 +436,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -410,8 +452,11 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d h1:dOiJ2n2cMwGLce/74I/QHMbnpk5GfY7InR8rczoMqRM= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201207224615-747e23833adb h1:xj2oMIbduz83x7tzglytWT7spn6rP+9hvKjTpro6/pM= +golang.org/x/net v0.0.0-20201207224615-747e23833adb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -427,6 +472,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -471,6 +517,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -522,8 +570,10 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200806022845-90696ccdc692/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200814230902-9882f1d1823d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200817023811-d00afeaade8f/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200818005847-188abfa75333 h1:a6ryybeZHQf5qnBc6IwRfVnI/75UmdtJo71f0//8Dqo= golang.org/x/tools v0.0.0-20200818005847-188abfa75333/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208062317-e652b2f42cc7 h1:2OSu5vYyX4LVqZAtqZXnFEcN26SDKIJYlEVIRl1tj8U= +golang.org/x/tools v0.0.0-20201208062317-e652b2f42cc7/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -615,8 +665,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= @@ -626,10 +677,13 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/http/handler/error.go b/http/handler/error.go index 9028591..a3bfb73 100644 --- a/http/handler/error.go +++ b/http/handler/error.go @@ -45,4 +45,4 @@ type errorResponse struct { Message string `json:"message"` Details string `json:"details,omitempty"` StatusCode int `json:"-"` -} +} //@name Error diff --git a/http/handler/webhook.go b/http/handler/webhook.go index dac6531..c00d17e 100644 --- a/http/handler/webhook.go +++ b/http/handler/webhook.go @@ -13,7 +13,7 @@ type webhookList struct { Webhooks []*postmand.Webhook `json:"webhooks"` Limit int `json:"limit"` Offset int `json:"offset"` -} +} //@name WebhookList // Webhook implements rest interface for webhook. type Webhook struct { @@ -22,6 +22,16 @@ type Webhook struct { } // List webhooks. +// List godoc +// @Summary List webhooks +// @Tags webhooks +// @Accept json +// @Produce json +// @Param limit query int false "The limit indicates the maximum number of items to return" +// @Param offset query int false "The offset indicates the starting position of the query in relation to the complete set of unpaginated items" +// @Success 200 {object} webhookList +// @Failure 500 {object} errorResponse +// @Router /webhooks [get] func (wh Webhook) List(w http.ResponseWriter, r *http.Request) { listOptions, err := makeListOptions(r, []string{}) if err != nil { @@ -56,6 +66,16 @@ func (wh Webhook) List(w http.ResponseWriter, r *http.Request) { } // Get webhook. +// Get godoc +// @Summary Show a webhook +// @Tags webhooks +// @Accept json +// @Produce json +// @Param webhook_id path string true "Webhook ID" +// @Success 200 {object} postmand.Webhook +// @Failure 404 {object} errorResponse +// @Failure 500 {object} errorResponse +// @Router /webhooks/{webhook_id} [get] func (wh Webhook) Get(w http.ResponseWriter, r *http.Request) { webhookID, err := uuid.Parse(chi.URLParam(r, "webhook_id")) if err != nil { @@ -89,6 +109,16 @@ func (wh Webhook) Get(w http.ResponseWriter, r *http.Request) { } // Create webhook. +// Create godoc +// @Summary Add an webhook +// @Tags webhooks +// @Accept json +// @Produce json +// @Param webhook body postmand.Webhook true "Add webhook" +// @Success 201 {object} postmand.Webhook +// @Failure 400 {object} errorResponse +// @Failure 500 {object} errorResponse +// @Router /webhooks [post] func (wh Webhook) Create(w http.ResponseWriter, r *http.Request) { // Parse request webhook := postmand.Webhook{} @@ -114,6 +144,18 @@ func (wh Webhook) Create(w http.ResponseWriter, r *http.Request) { } // Update webhook. +// Update godoc +// @Summary Update an webhook +// @Tags webhooks +// @Accept json +// @Produce json +// @Param webhook_id path string true "Webhook ID" +// @Param webhook body postmand.Webhook true "Update webhook" +// @Success 200 {object} postmand.Webhook +// @Failure 400 {object} errorResponse +// @Failure 404 {object} errorResponse +// @Failure 500 {object} errorResponse +// @Router /webhooks/{webhook_id} [put] func (wh Webhook) Update(w http.ResponseWriter, r *http.Request) { webhookID, err := uuid.Parse(chi.URLParam(r, "webhook_id")) if err != nil { @@ -147,6 +189,16 @@ func (wh Webhook) Update(w http.ResponseWriter, r *http.Request) { } // Delete webhook. +// Delete godoc +// @Summary Delete an webhook +// @Tags webhooks +// @Accept json +// @Produce json +// @Param webhook_id path string true "Webhook ID" +// @Success 204 "No Content" +// @Failure 404 {object} errorResponse +// @Failure 500 {object} errorResponse +// @Router /webhooks/{webhook_id} [delete] func (wh Webhook) Delete(w http.ResponseWriter, r *http.Request) { webhookID, err := uuid.Parse(chi.URLParam(r, "webhook_id")) if err != nil {