commit f1033c67acf244293b62de8f2da158dc55581efc Author: DeveloperDurp Date: Wed Mar 29 18:54:45 2023 -0500 initial commit example diff --git a/README.md b/README.md new file mode 100644 index 0000000..c4879ed --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Celler example + +Gen doc + +```console +$ go get -u github.com/swaggo/swag/cmd/swag +$ swag init +``` + +Run app + +```console +$ go run main.go +``` + +[open swagger](http://localhost:8080/swagger/index.html) + diff --git a/controller/accounts.go b/controller/accounts.go new file mode 100644 index 0000000..2815e02 --- /dev/null +++ b/controller/accounts.go @@ -0,0 +1,191 @@ +package controller + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/swaggo/swag/example/celler/httputil" + "github.com/swaggo/swag/example/celler/model" +) + +// ShowAccount godoc +// +// @Summary Show an account +// @Description get string by ID +// @Tags accounts +// @Accept json +// @Produce json +// @Param id path int true "Account ID" +// @Success 200 {object} model.Account +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /accounts/{id} [get] +func (c *Controller) ShowAccount(ctx *gin.Context) { + id := ctx.Param("id") + aid, err := strconv.Atoi(id) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + account, err := model.AccountOne(aid) + if err != nil { + httputil.NewError(ctx, http.StatusNotFound, err) + return + } + ctx.JSON(http.StatusOK, account) +} + +// ListAccounts godoc +// +// @Summary List accounts +// @Description get accounts +// @Tags accounts +// @Accept json +// @Produce json +// @Param q query string false "name search by q" Format(email) +// @Success 200 {array} model.Account +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /accounts [get] +func (c *Controller) ListAccounts(ctx *gin.Context) { + q := ctx.Request.URL.Query().Get("q") + accounts, err := model.AccountsAll(q) + if err != nil { + httputil.NewError(ctx, http.StatusNotFound, err) + return + } + ctx.JSON(http.StatusOK, accounts) +} + +// AddAccount godoc +// +// @Summary Add an account +// @Description add by json account +// @Tags accounts +// @Accept json +// @Produce json +// @Param account body model.AddAccount true "Add account" +// @Success 200 {object} model.Account +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /accounts [post] +func (c *Controller) AddAccount(ctx *gin.Context) { + var addAccount model.AddAccount + if err := ctx.ShouldBindJSON(&addAccount); err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + if err := addAccount.Validation(); err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + account := model.Account{ + Name: addAccount.Name, + } + lastID, err := account.Insert() + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + account.ID = lastID + ctx.JSON(http.StatusOK, account) +} + +// UpdateAccount godoc +// +// @Summary Update an account +// @Description Update by json account +// @Tags accounts +// @Accept json +// @Produce json +// @Param id path int true "Account ID" +// @Param account body model.UpdateAccount true "Update account" +// @Success 200 {object} model.Account +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /accounts/{id} [patch] +func (c *Controller) UpdateAccount(ctx *gin.Context) { + id := ctx.Param("id") + aid, err := strconv.Atoi(id) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + var updateAccount model.UpdateAccount + if err := ctx.ShouldBindJSON(&updateAccount); err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + account := model.Account{ + ID: aid, + Name: updateAccount.Name, + } + err = account.Update() + if err != nil { + httputil.NewError(ctx, http.StatusNotFound, err) + return + } + ctx.JSON(http.StatusOK, account) +} + +// DeleteAccount godoc +// +// @Summary Delete an account +// @Description Delete by account ID +// @Tags accounts +// @Accept json +// @Produce json +// @Param id path int true "Account ID" Format(int64) +// @Success 204 {object} model.Account +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /accounts/{id} [delete] +func (c *Controller) DeleteAccount(ctx *gin.Context) { + id := ctx.Param("id") + aid, err := strconv.Atoi(id) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + err = model.Delete(aid) + if err != nil { + httputil.NewError(ctx, http.StatusNotFound, err) + return + } + ctx.JSON(http.StatusNoContent, gin.H{}) +} + +// UploadAccountImage godoc +// +// @Summary Upload account image +// @Description Upload file +// @Tags accounts +// @Accept multipart/form-data +// @Produce json +// @Param id path int true "Account ID" +// @Param file formData file true "account image" +// @Success 200 {object} controller.Message +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /accounts/{id}/images [post] +func (c *Controller) UploadAccountImage(ctx *gin.Context) { + id, err := strconv.Atoi(ctx.Param("id")) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + file, err := ctx.FormFile("file") + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + ctx.JSON(http.StatusOK, Message{Message: fmt.Sprintf("upload complete userID=%d filename=%s", id, file.Filename)}) +} diff --git a/controller/admin.go b/controller/admin.go new file mode 100644 index 0000000..b288d34 --- /dev/null +++ b/controller/admin.go @@ -0,0 +1,42 @@ +package controller + +import ( + "errors" + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/swaggo/swag/example/celler/httputil" + "github.com/swaggo/swag/example/celler/model" +) + +// Auth godoc +// +// @Summary Auth admin +// @Description get admin info +// @Tags accounts,admin +// @Accept json +// @Produce json +// @Success 200 {object} model.Admin +// @Failure 400 {object} httputil.HTTPError +// @Failure 401 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Security ApiKeyAuth +// @Router /admin/auth [post] +func (c *Controller) Auth(ctx *gin.Context) { + authHeader := ctx.GetHeader("Authorization") + if len(authHeader) == 0 { + httputil.NewError(ctx, http.StatusBadRequest, errors.New("please set Header Authorization")) + return + } + if authHeader != "admin" { + httputil.NewError(ctx, http.StatusUnauthorized, fmt.Errorf("this user isn't authorized to operation key=%s expected=admin", authHeader)) + return + } + admin := model.Admin{ + ID: 1, + Name: "admin", + } + ctx.JSON(http.StatusOK, admin) +} diff --git a/controller/bottles.go b/controller/bottles.go new file mode 100644 index 0000000..925414d --- /dev/null +++ b/controller/bottles.go @@ -0,0 +1,61 @@ +package controller + +import ( + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + + "github.com/swaggo/swag/example/celler/httputil" + "github.com/swaggo/swag/example/celler/model" +) + +// ShowBottle godoc +// +// @Summary Show a bottle +// @Description get string by ID +// @ID get-string-by-int +// @Tags bottles +// @Accept json +// @Produce json +// @Param id path int true "Bottle ID" +// @Success 200 {object} model.Bottle +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /bottles/{id} [get] +func (c *Controller) ShowBottle(ctx *gin.Context) { + id := ctx.Param("id") + bid, err := strconv.Atoi(id) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + bottle, err := model.BottleOne(bid) + if err != nil { + httputil.NewError(ctx, http.StatusNotFound, err) + return + } + ctx.JSON(http.StatusOK, bottle) +} + +// ListBottles godoc +// +// @Summary List bottles +// @Description get bottles +// @Tags bottles +// @Accept json +// @Produce json +// @Success 200 {array} model.Bottle +// @Failure 400 {object} httputil.HTTPError +// @Failure 404 {object} httputil.HTTPError +// @Failure 500 {object} httputil.HTTPError +// @Router /bottles [get] +func (c *Controller) ListBottles(ctx *gin.Context) { + bottles, err := model.BottlesAll() + if err != nil { + httputil.NewError(ctx, http.StatusNotFound, err) + return + } + ctx.JSON(http.StatusOK, bottles) +} diff --git a/controller/controller.go b/controller/controller.go new file mode 100644 index 0000000..e00d638 --- /dev/null +++ b/controller/controller.go @@ -0,0 +1,15 @@ +package controller + +// Controller example +type Controller struct { +} + +// NewController example +func NewController() *Controller { + return &Controller{} +} + +// Message example +type Message struct { + Message string `json:"message" example:"message"` +} diff --git a/controller/examples.go b/controller/examples.go new file mode 100644 index 0000000..e27a4c3 --- /dev/null +++ b/controller/examples.go @@ -0,0 +1,160 @@ +package controller + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/swaggo/swag/example/celler/httputil" +) + +// PingExample godoc +// +// @Summary ping example +// @Description do ping +// @Tags example +// @Accept json +// @Produce plain +// @Success 200 {string} string "pong" +// @Failure 400 {string} string "ok" +// @Failure 404 {string} string "ok" +// @Failure 500 {string} string "ok" +// @Router /examples/ping [get] +func (c *Controller) PingExample(ctx *gin.Context) { + ctx.String(http.StatusOK, "pong") +} + +// CalcExample godoc +// +// @Summary calc example +// @Description plus +// @Tags example +// @Accept json +// @Produce plain +// @Param val1 query int true "used for calc" +// @Param val2 query int true "used for calc" +// @Success 200 {integer} string "answer" +// @Failure 400 {string} string "ok" +// @Failure 404 {string} string "ok" +// @Failure 500 {string} string "ok" +// @Router /examples/calc [get] +func (c *Controller) CalcExample(ctx *gin.Context) { + val1, err := strconv.Atoi(ctx.Query("val1")) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + val2, err := strconv.Atoi(ctx.Query("val2")) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + ans := val1 + val2 + ctx.String(http.StatusOK, "%d", ans) +} + +// PathParamsExample godoc +// +// @Summary path params example +// @Description path params +// @Tags example +// @Accept json +// @Produce plain +// @Param group_id path int true "Group ID" +// @Param account_id path int true "Account ID" +// @Success 200 {string} string "answer" +// @Failure 400 {string} string "ok" +// @Failure 404 {string} string "ok" +// @Failure 500 {string} string "ok" +// @Router /examples/groups/{group_id}/accounts/{account_id} [get] +func (c *Controller) PathParamsExample(ctx *gin.Context) { + groupID, err := strconv.Atoi(ctx.Param("group_id")) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + accountID, err := strconv.Atoi(ctx.Param("account_id")) + if err != nil { + httputil.NewError(ctx, http.StatusBadRequest, err) + return + } + ctx.String(http.StatusOK, "group_id=%d account_id=%d", groupID, accountID) +} + +// HeaderExample godoc +// +// @Summary custome header example +// @Description custome header +// @Tags example +// @Accept json +// @Produce plain +// @Param Authorization header string true "Authentication header" +// @Success 200 {string} string "answer" +// @Failure 400 {string} string "ok" +// @Failure 404 {string} string "ok" +// @Failure 500 {string} string "ok" +// @Router /examples/header [get] +func (c *Controller) HeaderExample(ctx *gin.Context) { + ctx.String(http.StatusOK, ctx.GetHeader("Authorization")) +} + +// SecuritiesExample godoc +// +// @Summary custome header example +// @Description custome header +// @Tags example +// @Accept json +// @Produce json +// @Param Authorization header string true "Authentication header" +// @Success 200 {string} string "answer" +// @Failure 400 {string} string "ok" +// @Failure 404 {string} string "ok" +// @Failure 500 {string} string "ok" +// @Security ApiKeyAuth +// @Security OAuth2Implicit[admin, write] +// @Router /examples/securities [get] +func (c *Controller) SecuritiesExample(ctx *gin.Context) { +} + +// AttributeExample godoc +// +// @Summary attribute example +// @Description attribute +// @Tags example +// @Accept json +// @Produce plain +// @Param enumstring query string false "string enums" Enums(A, B, C) +// @Param enumint query int false "int enums" Enums(1, 2, 3) +// @Param enumnumber query number false "int enums" Enums(1.1, 1.2, 1.3) +// @Param string query string false "string valid" minlength(5) maxlength(10) +// @Param int query int false "int valid" minimum(1) maximum(10) +// @Param default query string false "string default" default(A) +// @Success 200 {string} string "answer" +// @Failure 400 {string} string "ok" +// @Failure 404 {string} string "ok" +// @Failure 500 {string} string "ok" +// @Router /examples/attribute [get] +func (c *Controller) AttributeExample(ctx *gin.Context) { + ctx.String(http.StatusOK, fmt.Sprintf("enumstring=%s enumint=%s enumnumber=%s string=%s int=%s default=%s", + ctx.Query("enumstring"), + ctx.Query("enumint"), + ctx.Query("enumnumber"), + ctx.Query("string"), + ctx.Query("int"), + ctx.Query("default"), + )) +} + +// PostExample godoc +// +// @Summary post request example +// @Description post request example +// @Accept json +// @Produce plain +// @Param message body model.Account true "Account Info" +// @Success 200 {string} string "success" +// @Failure 500 {string} string "fail" +// @Router /examples/post [post] +func (c *Controller) PostExample(ctx *gin.Context) { +} diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..4c63f80 --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,1049 @@ +// Code generated by swaggo/swag. DO NOT EDIT. + +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "API Support", + "url": "http://www.swagger.io/support", + "email": "support@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/accounts": { + "get": { + "description": "get accounts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "List accounts", + "parameters": [ + { + "type": "string", + "format": "email", + "description": "name search by q", + "name": "q", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Account" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + }, + "post": { + "description": "add by json account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Add an account", + "parameters": [ + { + "description": "Add account", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddAccount" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/accounts/{id}": { + "get": { + "description": "get string by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Show an account", + "parameters": [ + { + "type": "integer", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + }, + "delete": { + "description": "Delete by account ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Delete an account", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + }, + "patch": { + "description": "Update by json account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Update an account", + "parameters": [ + { + "type": "integer", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update account", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UpdateAccount" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/accounts/{id}/images": { + "post": { + "description": "Upload file", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Upload account image", + "parameters": [ + { + "type": "integer", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "file", + "description": "account image", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/controller.Message" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/admin/auth": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get admin info", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts", + "admin" + ], + "summary": "Auth admin", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Admin" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/bottles": { + "get": { + "description": "get bottles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "bottles" + ], + "summary": "List bottles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Bottle" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/bottles/{id}": { + "get": { + "description": "get string by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "bottles" + ], + "summary": "Show a bottle", + "operationId": "get-string-by-int", + "parameters": [ + { + "type": "integer", + "description": "Bottle ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Bottle" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/examples/attribute": { + "get": { + "description": "attribute", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "attribute example", + "parameters": [ + { + "enum": [ + "A", + "B", + "C" + ], + "type": "string", + "description": "string enums", + "name": "enumstring", + "in": "query" + }, + { + "enum": [ + 1, + 2, + 3 + ], + "type": "integer", + "description": "int enums", + "name": "enumint", + "in": "query" + }, + { + "enum": [ + 1.1, + 1.2, + 1.3 + ], + "type": "number", + "description": "int enums", + "name": "enumnumber", + "in": "query" + }, + { + "maxLength": 10, + "minLength": 5, + "type": "string", + "description": "string valid", + "name": "string", + "in": "query" + }, + { + "maximum": 10, + "minimum": 1, + "type": "integer", + "description": "int valid", + "name": "int", + "in": "query" + }, + { + "type": "string", + "default": "A", + "description": "string default", + "name": "default", + "in": "query" + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/calc": { + "get": { + "description": "plus", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "calc example", + "parameters": [ + { + "type": "integer", + "description": "used for calc", + "name": "val1", + "in": "query", + "required": true + }, + { + "type": "integer", + "description": "used for calc", + "name": "val2", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "integer" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/groups/{group_id}/accounts/{account_id}": { + "get": { + "description": "path params", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "path params example", + "parameters": [ + { + "type": "integer", + "description": "Group ID", + "name": "group_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Account ID", + "name": "account_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/header": { + "get": { + "description": "custome header", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "custome header example", + "parameters": [ + { + "type": "string", + "description": "Authentication header", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/ping": { + "get": { + "description": "do ping", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "ping example", + "responses": { + "200": { + "description": "pong", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/post": { + "post": { + "description": "post request example", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "summary": "post request example", + "parameters": [ + { + "description": "Account Info", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Account" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "fail", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/securities": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + }, + { + "OAuth2Implicit": [ + "admin", + "write" + ] + } + ], + "description": "custome header", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "example" + ], + "summary": "custome header example", + "parameters": [ + { + "type": "string", + "description": "Authentication header", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "controller.Message": { + "type": "object", + "properties": { + "message": { + "type": "string", + "example": "message" + } + } + }, + "httputil.HTTPError": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "status bad request" + } + } + }, + "model.Account": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "account name" + }, + "uuid": { + "type": "string", + "format": "uuid", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + } + }, + "model.AddAccount": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "account name" + } + } + }, + "model.Admin": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "admin name" + } + } + }, + "model.Bottle": { + "type": "object", + "properties": { + "account": { + "$ref": "#/definitions/model.Account" + }, + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "bottle_name" + } + } + }, + "model.UpdateAccount": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "account name" + } + } + } + }, + "securityDefinitions": { + "ApiKeyAuth": { + "description": "Description for what is this security definition being used", + "type": "apiKey", + "name": "Authorization", + "in": "header" + }, + "BasicAuth": { + "type": "basic" + }, + "OAuth2AccessCode": { + "type": "oauth2", + "flow": "accessCode", + "authorizationUrl": "https://example.com/oauth/authorize", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information" + } + }, + "OAuth2Application": { + "type": "oauth2", + "flow": "application", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information", + "write": "\t\t\t\t\t\t\tGrants write access" + } + }, + "OAuth2Implicit": { + "type": "oauth2", + "flow": "implicit", + "authorizationUrl": "https://example.com/oauth/authorize", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information", + "write": "\t\t\t\t\t\t\tGrants write access" + } + }, + "OAuth2Password": { + "type": "oauth2", + "flow": "password", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information", + "read": "\t\t\t\t\t\t\t\tGrants read access", + "write": "\t\t\t\t\t\t\tGrants write access" + } + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "1.0", + Host: "localhost:8080", + BasePath: "/api/v1", + Schemes: []string{}, + Title: "Swagger Example API", + Description: "This is a sample server celler server.", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..092dbd3 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,1026 @@ +{ + "swagger": "2.0", + "info": { + "description": "This is a sample server celler server.", + "title": "Swagger Example API", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "API Support", + "url": "http://www.swagger.io/support", + "email": "support@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0" + }, + "host": "localhost:8080", + "basePath": "/api/v1", + "paths": { + "/accounts": { + "get": { + "description": "get accounts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "List accounts", + "parameters": [ + { + "type": "string", + "format": "email", + "description": "name search by q", + "name": "q", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Account" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + }, + "post": { + "description": "add by json account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Add an account", + "parameters": [ + { + "description": "Add account", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.AddAccount" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/accounts/{id}": { + "get": { + "description": "get string by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Show an account", + "parameters": [ + { + "type": "integer", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + }, + "delete": { + "description": "Delete by account ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Delete an account", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + }, + "patch": { + "description": "Update by json account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Update an account", + "parameters": [ + { + "type": "integer", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update account", + "name": "account", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.UpdateAccount" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/accounts/{id}/images": { + "post": { + "description": "Upload file", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts" + ], + "summary": "Upload account image", + "parameters": [ + { + "type": "integer", + "description": "Account ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "file", + "description": "account image", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/controller.Message" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/admin/auth": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get admin info", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "accounts", + "admin" + ], + "summary": "Auth admin", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Admin" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/bottles": { + "get": { + "description": "get bottles", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "bottles" + ], + "summary": "List bottles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Bottle" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/bottles/{id}": { + "get": { + "description": "get string by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "bottles" + ], + "summary": "Show a bottle", + "operationId": "get-string-by-int", + "parameters": [ + { + "type": "integer", + "description": "Bottle ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Bottle" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/httputil.HTTPError" + } + } + } + } + }, + "/examples/attribute": { + "get": { + "description": "attribute", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "attribute example", + "parameters": [ + { + "enum": [ + "A", + "B", + "C" + ], + "type": "string", + "description": "string enums", + "name": "enumstring", + "in": "query" + }, + { + "enum": [ + 1, + 2, + 3 + ], + "type": "integer", + "description": "int enums", + "name": "enumint", + "in": "query" + }, + { + "enum": [ + 1.1, + 1.2, + 1.3 + ], + "type": "number", + "description": "int enums", + "name": "enumnumber", + "in": "query" + }, + { + "maxLength": 10, + "minLength": 5, + "type": "string", + "description": "string valid", + "name": "string", + "in": "query" + }, + { + "maximum": 10, + "minimum": 1, + "type": "integer", + "description": "int valid", + "name": "int", + "in": "query" + }, + { + "type": "string", + "default": "A", + "description": "string default", + "name": "default", + "in": "query" + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/calc": { + "get": { + "description": "plus", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "calc example", + "parameters": [ + { + "type": "integer", + "description": "used for calc", + "name": "val1", + "in": "query", + "required": true + }, + { + "type": "integer", + "description": "used for calc", + "name": "val2", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "integer" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/groups/{group_id}/accounts/{account_id}": { + "get": { + "description": "path params", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "path params example", + "parameters": [ + { + "type": "integer", + "description": "Group ID", + "name": "group_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Account ID", + "name": "account_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/header": { + "get": { + "description": "custome header", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "custome header example", + "parameters": [ + { + "type": "string", + "description": "Authentication header", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/ping": { + "get": { + "description": "do ping", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "tags": [ + "example" + ], + "summary": "ping example", + "responses": { + "200": { + "description": "pong", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/post": { + "post": { + "description": "post request example", + "consumes": [ + "application/json" + ], + "produces": [ + "text/plain" + ], + "summary": "post request example", + "parameters": [ + { + "description": "Account Info", + "name": "message", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Account" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "fail", + "schema": { + "type": "string" + } + } + } + } + }, + "/examples/securities": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + }, + { + "OAuth2Implicit": [ + "admin", + "write" + ] + } + ], + "description": "custome header", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "example" + ], + "summary": "custome header example", + "parameters": [ + { + "type": "string", + "description": "Authentication header", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "answer", + "schema": { + "type": "string" + } + }, + "400": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "404": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "500": { + "description": "ok", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "controller.Message": { + "type": "object", + "properties": { + "message": { + "type": "string", + "example": "message" + } + } + }, + "httputil.HTTPError": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "example": 400 + }, + "message": { + "type": "string", + "example": "status bad request" + } + } + }, + "model.Account": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "account name" + }, + "uuid": { + "type": "string", + "format": "uuid", + "example": "550e8400-e29b-41d4-a716-446655440000" + } + } + }, + "model.AddAccount": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "account name" + } + } + }, + "model.Admin": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "admin name" + } + } + }, + "model.Bottle": { + "type": "object", + "properties": { + "account": { + "$ref": "#/definitions/model.Account" + }, + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "bottle_name" + } + } + }, + "model.UpdateAccount": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "account name" + } + } + } + }, + "securityDefinitions": { + "ApiKeyAuth": { + "description": "Description for what is this security definition being used", + "type": "apiKey", + "name": "Authorization", + "in": "header" + }, + "BasicAuth": { + "type": "basic" + }, + "OAuth2AccessCode": { + "type": "oauth2", + "flow": "accessCode", + "authorizationUrl": "https://example.com/oauth/authorize", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information" + } + }, + "OAuth2Application": { + "type": "oauth2", + "flow": "application", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information", + "write": "\t\t\t\t\t\t\tGrants write access" + } + }, + "OAuth2Implicit": { + "type": "oauth2", + "flow": "implicit", + "authorizationUrl": "https://example.com/oauth/authorize", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information", + "write": "\t\t\t\t\t\t\tGrants write access" + } + }, + "OAuth2Password": { + "type": "oauth2", + "flow": "password", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": "\t\t\t\t\t\t\tGrants read and write access to administrative information", + "read": "\t\t\t\t\t\t\t\tGrants read access", + "write": "\t\t\t\t\t\t\tGrants write access" + } + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..9c3bfd7 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,689 @@ +basePath: /api/v1 +definitions: + controller.Message: + properties: + message: + example: message + type: string + type: object + httputil.HTTPError: + properties: + code: + example: 400 + type: integer + message: + example: status bad request + type: string + type: object + model.Account: + properties: + id: + example: 1 + format: int64 + type: integer + name: + example: account name + type: string + uuid: + example: 550e8400-e29b-41d4-a716-446655440000 + format: uuid + type: string + type: object + model.AddAccount: + properties: + name: + example: account name + type: string + type: object + model.Admin: + properties: + id: + example: 1 + type: integer + name: + example: admin name + type: string + type: object + model.Bottle: + properties: + account: + $ref: '#/definitions/model.Account' + id: + example: 1 + type: integer + name: + example: bottle_name + type: string + type: object + model.UpdateAccount: + properties: + name: + example: account name + type: string + type: object +host: localhost:8080 +info: + contact: + email: support@swagger.io + name: API Support + url: http://www.swagger.io/support + description: This is a sample server celler server. + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: http://swagger.io/terms/ + title: Swagger Example API + version: "1.0" +paths: + /accounts: + get: + consumes: + - application/json + description: get accounts + parameters: + - description: name search by q + format: email + in: query + name: q + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Account' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: List accounts + tags: + - accounts + post: + consumes: + - application/json + description: add by json account + parameters: + - description: Add account + in: body + name: account + required: true + schema: + $ref: '#/definitions/model.AddAccount' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Add an account + tags: + - accounts + /accounts/{id}: + delete: + consumes: + - application/json + description: Delete by account ID + parameters: + - description: Account ID + format: int64 + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "204": + description: No Content + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Delete an account + tags: + - accounts + get: + consumes: + - application/json + description: get string by ID + parameters: + - description: Account ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Show an account + tags: + - accounts + patch: + consumes: + - application/json + description: Update by json account + parameters: + - description: Account ID + in: path + name: id + required: true + type: integer + - description: Update account + in: body + name: account + required: true + schema: + $ref: '#/definitions/model.UpdateAccount' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Update an account + tags: + - accounts + /accounts/{id}/images: + post: + consumes: + - multipart/form-data + description: Upload file + parameters: + - description: Account ID + in: path + name: id + required: true + type: integer + - description: account image + in: formData + name: file + required: true + type: file + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/controller.Message' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Upload account image + tags: + - accounts + /admin/auth: + post: + consumes: + - application/json + description: get admin info + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Admin' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + security: + - ApiKeyAuth: [] + summary: Auth admin + tags: + - accounts + - admin + /bottles: + get: + consumes: + - application/json + description: get bottles + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Bottle' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: List bottles + tags: + - bottles + /bottles/{id}: + get: + consumes: + - application/json + description: get string by ID + operationId: get-string-by-int + parameters: + - description: Bottle ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Bottle' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Show a bottle + tags: + - bottles + /examples/attribute: + get: + consumes: + - application/json + description: attribute + parameters: + - description: string enums + enum: + - A + - B + - C + in: query + name: enumstring + type: string + - description: int enums + enum: + - 1 + - 2 + - 3 + in: query + name: enumint + type: integer + - description: int enums + enum: + - 1.1 + - 1.2 + - 1.3 + in: query + name: enumnumber + type: number + - description: string valid + in: query + maxLength: 10 + minLength: 5 + name: string + type: string + - description: int valid + in: query + maximum: 10 + minimum: 1 + name: int + type: integer + - default: A + description: string default + in: query + name: default + type: string + produces: + - text/plain + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: attribute example + tags: + - example + /examples/calc: + get: + consumes: + - application/json + description: plus + parameters: + - description: used for calc + in: query + name: val1 + required: true + type: integer + - description: used for calc + in: query + name: val2 + required: true + type: integer + produces: + - text/plain + responses: + "200": + description: answer + schema: + type: integer + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: calc example + tags: + - example + /examples/groups/{group_id}/accounts/{account_id}: + get: + consumes: + - application/json + description: path params + parameters: + - description: Group ID + in: path + name: group_id + required: true + type: integer + - description: Account ID + in: path + name: account_id + required: true + type: integer + produces: + - text/plain + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: path params example + tags: + - example + /examples/header: + get: + consumes: + - application/json + description: custome header + parameters: + - description: Authentication header + in: header + name: Authorization + required: true + type: string + produces: + - text/plain + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: custome header example + tags: + - example + /examples/ping: + get: + consumes: + - application/json + description: do ping + produces: + - text/plain + responses: + "200": + description: pong + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: ping example + tags: + - example + /examples/post: + post: + consumes: + - application/json + description: post request example + parameters: + - description: Account Info + in: body + name: message + required: true + schema: + $ref: '#/definitions/model.Account' + produces: + - text/plain + responses: + "200": + description: success + schema: + type: string + "500": + description: fail + schema: + type: string + summary: post request example + /examples/securities: + get: + consumes: + - application/json + description: custome header + parameters: + - description: Authentication header + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + security: + - ApiKeyAuth: [] + - OAuth2Implicit: + - admin + - write + summary: custome header example + tags: + - example +securityDefinitions: + ApiKeyAuth: + description: Description for what is this security definition being used + in: header + name: Authorization + type: apiKey + BasicAuth: + type: basic + OAuth2AccessCode: + authorizationUrl: https://example.com/oauth/authorize + flow: accessCode + scopes: + admin: "\t\t\t\t\t\t\tGrants read and write access to administrative information" + tokenUrl: https://example.com/oauth/token + type: oauth2 + OAuth2Application: + flow: application + scopes: + admin: "\t\t\t\t\t\t\tGrants read and write access to administrative information" + write: "\t\t\t\t\t\t\tGrants write access" + tokenUrl: https://example.com/oauth/token + type: oauth2 + OAuth2Implicit: + authorizationUrl: https://example.com/oauth/authorize + flow: implicit + scopes: + admin: "\t\t\t\t\t\t\tGrants read and write access to administrative information" + write: "\t\t\t\t\t\t\tGrants write access" + type: oauth2 + OAuth2Password: + flow: password + scopes: + admin: "\t\t\t\t\t\t\tGrants read and write access to administrative information" + read: "\t\t\t\t\t\t\t\tGrants read access" + write: "\t\t\t\t\t\t\tGrants write access" + tokenUrl: https://example.com/oauth/token + type: oauth2 +swagger: "2.0" diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml new file mode 100644 index 0000000..e9deea7 --- /dev/null +++ b/docs/swagger/swagger.yaml @@ -0,0 +1,692 @@ +basePath: /api/v1 +definitions: + controller.Message: + properties: + message: + example: message + type: string + type: object + httputil.HTTPError: + properties: + code: + example: 400 + type: integer + message: + example: status bad request + type: string + type: object + model.Account: + properties: + id: + example: 1 + format: int64 + type: integer + name: + example: account name + type: string + uuid: + example: 550e8400-e29b-41d4-a716-446655440000 + format: uuid + type: string + type: object + model.AddAccount: + properties: + name: + example: account name + type: string + type: object + model.Admin: + properties: + id: + example: 1 + type: integer + name: + example: admin name + type: string + type: object + model.Bottle: + properties: + account: + $ref: '#/definitions/model.Account' + id: + example: 1 + type: integer + name: + example: bottle_name + type: string + type: object + model.UpdateAccount: + properties: + name: + example: account name + type: string + type: object +host: localhost:8080 +info: + contact: + email: support@swagger.io + name: API Support + url: http://www.swagger.io/support + description: This is a sample server celler server. + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: http://swagger.io/terms/ + title: Swagger Example API + version: "1.0" +paths: + /accounts: + get: + consumes: + - application/json + description: get accounts + parameters: + - description: name search by q + format: email + in: query + name: q + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Account' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: List accounts + tags: + - accounts + post: + consumes: + - application/json + description: add by json account + parameters: + - description: Add account + in: body + name: account + required: true + schema: + $ref: '#/definitions/model.AddAccount' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Add an account + tags: + - accounts + /accounts/{id}: + delete: + consumes: + - application/json + description: Delete by account ID + parameters: + - description: Account ID + format: int64 + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "204": + description: No Content + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Delete an account + tags: + - accounts + get: + consumes: + - application/json + description: get string by ID + parameters: + - description: Account ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Show an account + tags: + - accounts + patch: + consumes: + - application/json + description: Update by json account + parameters: + - description: Account ID + in: path + name: id + required: true + type: integer + - description: Update account + in: body + name: account + required: true + schema: + $ref: '#/definitions/model.UpdateAccount' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Account' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Update an account + tags: + - accounts + /accounts/{id}/images: + post: + consumes: + - multipart/form-data + description: Upload file + parameters: + - description: Account ID + in: path + name: id + required: true + type: integer + - description: account image + in: formData + name: file + required: true + type: file + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/controller.Message' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Upload account image + tags: + - accounts + /admin/auth: + post: + consumes: + - application/json + description: get admin info + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Admin' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + security: + - ApiKeyAuth: [] + summary: Auth admin + tags: + - accounts + - admin + /bottles: + get: + consumes: + - application/json + description: get bottles + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.Bottle' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: List bottles + tags: + - bottles + /bottles/{id}: + get: + consumes: + - application/json + description: get string by ID + operationId: get-string-by-int + parameters: + - description: Bottle ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Bottle' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httputil.HTTPError' + "404": + description: Not Found + schema: + $ref: '#/definitions/httputil.HTTPError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/httputil.HTTPError' + summary: Show a bottle + tags: + - bottles + /examples/attribute: + get: + consumes: + - application/json + description: attribute + parameters: + - description: string enums + enum: + - A + - B + - C + in: query + name: enumstring + type: string + - description: int enums + enum: + - 1 + - 2 + - 3 + in: query + name: enumint + type: integer + - description: int enums + enum: + - 1.1 + - 1.2 + - 1.3 + in: query + name: enumnumber + type: number + - description: string valid + in: query + maxLength: 10 + minLength: 5 + name: string + type: string + - description: int valid + in: query + maximum: 10 + minimum: 1 + name: int + type: integer + - default: A + description: string default + in: query + name: default + type: string + produces: + - application/json + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: attribute example + tags: + - example + /examples/calc: + get: + consumes: + - application/json + description: plus + parameters: + - description: used for calc + in: query + name: val1 + required: true + type: integer + - description: used for calc + in: query + name: val2 + required: true + type: integer + produces: + - application/json + responses: + "200": + description: answer + schema: + type: integer + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: calc example + tags: + - example + /examples/groups/{group_id}/accounts/{account_id}: + get: + consumes: + - application/json + description: path params + parameters: + - description: Group ID + in: path + name: group_id + required: true + type: integer + - description: Account ID + in: path + name: account_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: path params example + tags: + - example + /examples/header: + get: + consumes: + - application/json + description: custome header + parameters: + - description: Authentication header + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: custome header example + tags: + - example + /examples/ping: + get: + consumes: + - application/json + description: do ping + produces: + - application/json + responses: + "200": + description: pong + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + summary: ping example + tags: + - example + /examples/post: + post: + consumes: + - application/json + description: post request example + parameters: + - description: Account Info + in: body + name: message + required: true + schema: + $ref: '#/definitions/model.Account' + produces: + - text/plain + responses: + "200": + description: success + schema: + type: string + "500": + description: fail + schema: + type: string + summary: post request example + /examples/securities: + get: + consumes: + - application/json + description: custome header + parameters: + - description: Authentication header + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: answer + schema: + type: string + "400": + description: ok + schema: + type: string + "404": + description: ok + schema: + type: string + "500": + description: ok + schema: + type: string + security: + - ApiKeyAuth: [] + - OAuth2Implicit: + - admin + - write + summary: custome header example + tags: + - example +securityDefinitions: + ApiKeyAuth: + in: header + name: Authorization + type: apiKey + BasicAuth: + type: basic + OAuth2AccessCode: + authorizationUrl: https://example.com/oauth/authorize + flow: accessCode + scopes: + admin: ' Grants read and write access to administrative + information' + tokenUrl: https://example.com/oauth/token + type: oauth2 + OAuth2Application: + flow: application + scopes: + admin: ' Grants read and write access to administrative + information' + write: ' Grants write access' + tokenUrl: https://example.com/oauth/token + type: oauth2 + OAuth2Implicit: + authorizationUrl: https://example.com/oauth/authorize + flow: implicit + scopes: + admin: ' Grants read and write access to administrative + information' + write: ' Grants write access' + type: oauth2 + OAuth2Password: + flow: password + scopes: + admin: ' Grants read and write access to administrative + information' + read: ' Grants read access' + write: ' Grants write access' + tokenUrl: https://example.com/oauth/token + type: oauth2 +swagger: "2.0" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c9e9b26 --- /dev/null +++ b/go.mod @@ -0,0 +1,40 @@ +module github.com/swaggo/swag/example/celler + +go 1.17 + +require ( + github.com/gin-gonic/gin v1.7.7 + github.com/gofrs/uuid v4.2.0+incompatible + github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 + github.com/swaggo/gin-swagger v1.4.2 + github.com/swaggo/swag v1.8.1 +) + +require ( + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.6 // indirect + github.com/go-openapi/spec v0.20.4 // indirect + github.com/go-openapi/swag v0.19.15 // indirect + github.com/go-playground/locales v0.13.0 // indirect + github.com/go-playground/universal-translator v0.17.0 // indirect + github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/golang/protobuf v1.3.3 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.9 // indirect + github.com/leodido/go-urn v1.2.0 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect + github.com/ugorji/go/codec v1.1.7 // indirect + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + golang.org/x/tools v0.1.12 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9531805 --- /dev/null +++ b/go.sum @@ -0,0 +1,170 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +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/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs= +github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= +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.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/gzip v0.0.3 h1:etUaeesHhEORpZMp18zoOhepboiWnFtXrBZxszWUn4k= +github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= +github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= +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.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +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/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +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/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/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +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/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +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/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= +github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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.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-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM= +github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= +github.com/swaggo/gin-swagger v1.4.2 h1:qDs1YrBOTnurDG/JVMc8678KhoS1B1okQGPtIqVz4YU= +github.com/swaggo/gin-swagger v1.4.2/go.mod h1:hmJ1vPn+XjUvnbzjCdUAxVqgraxELxk8x5zAsjCE5mg= +github.com/swaggo/swag v1.7.9/go.mod h1:gZ+TJ2w/Ve1RwQsA2IRoSOTidHz6DX+PIG8GWvbnoLU= +github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI= +github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/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.8/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= diff --git a/httputil/error.go b/httputil/error.go new file mode 100644 index 0000000..1b7166a --- /dev/null +++ b/httputil/error.go @@ -0,0 +1,18 @@ +package httputil + +import "github.com/gin-gonic/gin" + +// NewError example +func NewError(ctx *gin.Context, status int, err error) { + er := HTTPError{ + Code: status, + Message: err.Error(), + } + ctx.JSON(status, er) +} + +// HTTPError example +type HTTPError struct { + Code int `json:"code" example:"400"` + Message string `json:"message" example:"status bad request"` +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..ec27d47 --- /dev/null +++ b/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "errors" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/swaggo/swag/example/celler/controller" + _ "github.com/swaggo/swag/example/celler/docs" + "github.com/swaggo/swag/example/celler/httputil" + + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" +) + +// @title Swagger Example API +// @version 1.0 +// @description This is a sample server celler server. +// @termsOfService http://swagger.io/terms/ + +// @contact.name API Support +// @contact.url http://www.swagger.io/support +// @contact.email support@swagger.io + +// @license.name Apache 2.0 +// @license.url http://www.apache.org/licenses/LICENSE-2.0.html + +// @host localhost:8080 +// @BasePath /api/v1 + +// @securityDefinitions.basic BasicAuth + +// @securityDefinitions.apikey ApiKeyAuth +// @in header +// @name Authorization +// @description Description for what is this security definition being used + +// @securitydefinitions.oauth2.application OAuth2Application +// @tokenUrl https://example.com/oauth/token +// @scope.write Grants write access +// @scope.admin Grants read and write access to administrative information + +// @securitydefinitions.oauth2.implicit OAuth2Implicit +// @authorizationUrl https://example.com/oauth/authorize +// @scope.write Grants write access +// @scope.admin Grants read and write access to administrative information + +// @securitydefinitions.oauth2.password OAuth2Password +// @tokenUrl https://example.com/oauth/token +// @scope.read Grants read access +// @scope.write Grants write access +// @scope.admin Grants read and write access to administrative information + +// @securitydefinitions.oauth2.accessCode OAuth2AccessCode +// @tokenUrl https://example.com/oauth/token +// @authorizationUrl https://example.com/oauth/authorize +// @scope.admin Grants read and write access to administrative information + +func main() { + r := gin.Default() + + c := controller.NewController() + + v1 := r.Group("/api/v1") + { + accounts := v1.Group("/accounts") + { + accounts.GET(":id", c.ShowAccount) + accounts.GET("", c.ListAccounts) + accounts.POST("", c.AddAccount) + accounts.DELETE(":id", c.DeleteAccount) + accounts.PATCH(":id", c.UpdateAccount) + accounts.POST(":id/images", c.UploadAccountImage) + } + bottles := v1.Group("/bottles") + { + bottles.GET(":id", c.ShowBottle) + bottles.GET("", c.ListBottles) + } + admin := v1.Group("/admin") + { + admin.Use(auth()) + admin.POST("/auth", c.Auth) + } + examples := v1.Group("/examples") + { + examples.GET("ping", c.PingExample) + examples.GET("calc", c.CalcExample) + examples.GET("groups/:group_id/accounts/:account_id", c.PathParamsExample) + examples.GET("header", c.HeaderExample) + examples.GET("securities", c.SecuritiesExample) + examples.GET("attribute", c.AttributeExample) + } + } + r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + r.Run(":8080") +} + +func auth() gin.HandlerFunc { + return func(c *gin.Context) { + if len(c.GetHeader("Authorization")) == 0 { + httputil.NewError(c, http.StatusUnauthorized, errors.New("Authorization is required Header")) + c.Abort() + } + c.Next() + } +} diff --git a/model/account.go b/model/account.go new file mode 100644 index 0000000..d921ef1 --- /dev/null +++ b/model/account.go @@ -0,0 +1,112 @@ +package model + +import ( + "errors" + "fmt" + + uuid "github.com/gofrs/uuid" +) + +// Account example +type Account struct { + ID int `json:"id" example:"1" format:"int64"` + Name string `json:"name" example:"account name"` + UUID uuid.UUID `json:"uuid" example:"550e8400-e29b-41d4-a716-446655440000" format:"uuid"` +} + +// example +var ( + ErrNameInvalid = errors.New("name is empty") +) + +// AddAccount example +type AddAccount struct { + Name string `json:"name" example:"account name"` +} + +// Validation example +func (a AddAccount) Validation() error { + switch { + case len(a.Name) == 0: + return ErrNameInvalid + default: + return nil + } +} + +// UpdateAccount example +type UpdateAccount struct { + Name string `json:"name" example:"account name"` +} + +// Validation example +func (a UpdateAccount) Validation() error { + switch { + case len(a.Name) == 0: + return ErrNameInvalid + default: + return nil + } +} + +// AccountsAll example +func AccountsAll(q string) ([]Account, error) { + if q == "" { + return accounts, nil + } + as := []Account{} + for k, v := range accounts { + if q == v.Name { + as = append(as, accounts[k]) + } + } + return as, nil +} + +// AccountOne example +func AccountOne(id int) (Account, error) { + for _, v := range accounts { + if id == v.ID { + return v, nil + } + } + return Account{}, ErrNoRow +} + +// Insert example +func (a Account) Insert() (int, error) { + accountMaxID++ + a.ID = accountMaxID + a.Name = fmt.Sprintf("account_%d", accountMaxID) + accounts = append(accounts, a) + return accountMaxID, nil +} + +// Delete example +func Delete(id int) error { + for k, v := range accounts { + if id == v.ID { + accounts = append(accounts[:k], accounts[k+1:]...) + return nil + } + } + return fmt.Errorf("account id=%d is not found", id) +} + +// Update example +func (a Account) Update() error { + for k, v := range accounts { + if a.ID == v.ID { + accounts[k].Name = a.Name + return nil + } + } + return fmt.Errorf("account id=%d is not found", a.ID) +} + +var accountMaxID = 3 +var accounts = []Account{ + {ID: 1, Name: "account_1"}, + {ID: 2, Name: "account_2"}, + {ID: 3, Name: "account_3"}, +} diff --git a/model/admin.go b/model/admin.go new file mode 100644 index 0000000..315e8a9 --- /dev/null +++ b/model/admin.go @@ -0,0 +1,7 @@ +package model + +// Admin example +type Admin struct { + ID int `json:"id" example:"1"` + Name string `json:"name" example:"admin name"` +} diff --git a/model/bottle.go b/model/bottle.go new file mode 100644 index 0000000..43b4405 --- /dev/null +++ b/model/bottle.go @@ -0,0 +1,29 @@ +package model + +// Bottle example +type Bottle struct { + ID int `json:"id" example:"1"` + Name string `json:"name" example:"bottle_name"` + Account Account `json:"account"` +} + +// BottlesAll example +func BottlesAll() ([]Bottle, error) { + return bottles, nil +} + +// BottleOne example +func BottleOne(id int) (*Bottle, error) { + for _, v := range bottles { + if id == v.ID { + return &v, nil + } + } + return nil, ErrNoRow +} + +var bottles = []Bottle{ + {ID: 1, Name: "bottle_1", Account: Account{ID: 1, Name: "accout_1"}}, + {ID: 2, Name: "bottle_2", Account: Account{ID: 2, Name: "accout_2"}}, + {ID: 3, Name: "bottle_3", Account: Account{ID: 3, Name: "accout_3"}}, +} diff --git a/model/error.go b/model/error.go new file mode 100644 index 0000000..27317dc --- /dev/null +++ b/model/error.go @@ -0,0 +1,8 @@ +package model + +import "errors" + +var ( + // ErrNoRow example + ErrNoRow = errors.New("no rows in result set") +)