From d47d9c321e6bf9a96e00223f90af55bcd8de8a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1l=20=C5=9Eenay?= Date: Sat, 3 Sep 2022 22:03:07 +0300 Subject: [PATCH 1/7] Add securityDefinations field --- example/gin/handlers/handlers.go | 3 + swagno.go | 101 +++++++++++++++++++++++++++---- 2 files changed, 93 insertions(+), 11 deletions(-) diff --git a/example/gin/handlers/handlers.go b/example/gin/handlers/handlers.go index 8acd7c9..cc460a6 100644 --- a/example/gin/handlers/handlers.go +++ b/example/gin/handlers/handlers.go @@ -65,6 +65,9 @@ func (h *Handler) SetSwagger(a *gin.Engine) { sw := CreateNewSwagger("Swagger API", "1.0") AddEndpoints(endpoints) + sw.SetBasicAuth() + sw.SetApiKeyAuth("api_key", "query") + sw.SetOAuth2Auth("oauth2", "implicit", "http://localhost:8080/oauth2/token", "http://localhost:8080/oauth2/authorize", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) // 3 alternative way for describing tags with descriptions sw.AddTags(Tag("product", "Product operations"), Tag("merchant", "Merchant operations")) diff --git a/swagno.go b/swagno.go index 1983b3a..365140e 100644 --- a/swagno.go +++ b/swagno.go @@ -296,9 +296,10 @@ func generateSwagger(title string, version string, args ...string) (swagger Swag License: swaggerLicense{}, Contact: swaggerContact{}, }, - BasePath: "/", - Host: "", - Schemes: []string{"http", "https"}, + BasePath: "/", + Host: "", + Schemes: []string{"http", "https"}, + SecurityDefinitions: make(map[string]swaggerSecurityDefinition), } if len(args) > 0 { swagger.BasePath = args[0] @@ -334,18 +335,80 @@ func Tag(name string, description string) SwaggerTag { } } +func (s Swagger) SetBasicAuth(description ...string) { + desc := "Basic Authentication" + if len(description) > 0 { + desc = description[0] + } + s.SecurityDefinitions["basicAuth"] = swaggerSecurityDefinition{ + Type: "basic", + Description: desc, + } +} + +func (s Swagger) SetApiKeyAuth(name string, in string, description ...string) { + desc := "API Key Authentication" + if len(description) > 0 { + desc = description[0] + } + s.SecurityDefinitions[name] = swaggerSecurityDefinition{ + Type: "apiKey", + Name: name, + In: in, + Description: desc, + } +} + +func (s Swagger) SetOAuth2Auth(name string, flow string, authorizationUrl string, tokenUrl string, scopes map[string]string, description ...string) { + desc := "OAuth2 Authentication" + if len(description) > 0 { + desc = description[0] + } + + defination := swaggerSecurityDefinition{ + Type: "oauth2", + Flow: flow, + Scopes: scopes, + Description: desc, + } + + if flow == "implicit" || flow == "accessCode" { + defination.AuthorizationUrl = authorizationUrl + } + if flow == "password" || flow == "accessCode" || flow == "application" { + defination.TokenUrl = tokenUrl + } + s.SecurityDefinitions[name] = defination +} + +func Scopes(scopes ...swaggerSecurityScope) map[string]string { + scopesMap := make(map[string]string) + for _, scope := range scopes { + scopesMap[scope.Name] = scope.Description + } + return scopesMap +} + +func Scope(name string, description string) swaggerSecurityScope { + return swaggerSecurityScope{ + Name: name, + Description: description, + } +} + /* * Type definations */ type Swagger struct { - Swagger string `json:"swagger" default:"2.0"` - Info swaggerInfo `json:"info"` - Paths map[string]map[string]swaggerEndpoint `json:"paths"` - BasePath string `json:"basePath" default:"/"` - Host string `json:"host" default:""` - Definitions map[string]swaggerDefinition `json:"definitions"` - Schemes []string `json:"schemes,omitempty"` - Tags []SwaggerTag `json:"tags,omitempty"` + Swagger string `json:"swagger" default:"2.0"` + Info swaggerInfo `json:"info"` + Paths map[string]map[string]swaggerEndpoint `json:"paths"` + BasePath string `json:"basePath" default:"/"` + Host string `json:"host" default:""` + Definitions map[string]swaggerDefinition `json:"definitions"` + Schemes []string `json:"schemes,omitempty"` + Tags []SwaggerTag `json:"tags,omitempty"` + SecurityDefinitions map[string]swaggerSecurityDefinition `json:"securityDefinitions,omitempty"` } type SwaggerTag struct { @@ -432,3 +495,19 @@ type swaggerLicense struct { Name string `json:"name,omitempty"` Url string `json:"url,omitempty"` } + +type swaggerSecurityDefinition struct { + Type string `json:"type"` + Description string `json:"description,omitempty"` + Name string `json:"name,omitempty"` + In string `json:"in,omitempty"` + Flow string `json:"flow,omitempty"` + AuthorizationUrl string `json:"authorizationUrl,omitempty"` + TokenUrl string `json:"tokenUrl,omitempty"` + Scopes map[string]string `json:"scopes,omitempty"` +} + +type swaggerSecurityScope struct { + Name string + Description string +} From 4b976a331c44cc36aeb4525e7502a9b7015234fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1l=20=C5=9Eenay?= Date: Sat, 3 Sep 2022 22:56:31 +0300 Subject: [PATCH 2/7] Add security field to endpoints --- endpoints.go | 58 +++++++++++++++---- .../handlers/merchant_handler.go | 4 +- .../handlers/product_handler.go | 8 +-- example/fiber/handlers/handlers.go | 42 +++++++++----- example/gin/handlers/handlers.go | 41 +++++++------ swagno.go | 2 + 6 files changed, 105 insertions(+), 50 deletions(-) diff --git a/endpoints.go b/endpoints.go index 31c29de..73b1724 100644 --- a/endpoints.go +++ b/endpoints.go @@ -72,20 +72,21 @@ type Fields struct { } type Endpoint struct { - Method string `json:"method"` - Path string `json:"path"` - Params []Parameter `json:"params"` - Tags []string `json:"tags"` - Return interface{} `json:"return"` - Error interface{} `json:"error"` - Body interface{} `json:"body"` - Description string `json:"description"` - Consume []string `json:"consume"` - Produce []string `json:"produce"` + Method string `json:"method"` + Path string `json:"path"` + Params []Parameter `json:"params"` + Tags []string `json:"tags"` + Return interface{} `json:"return"` + Error interface{} `json:"error"` + Body interface{} `json:"body"` + Description string `json:"description"` + Consume []string `json:"consume"` + Produce []string `json:"produce"` + Security []map[string][]string `json:"security"` } // args: method, path, tags, params, body, return, error, description, consume, produce -func EndPoint(method MethodType, path string, tags string, params []Parameter, body interface{}, ret interface{}, err interface{}, des string, args ...string) Endpoint { +func EndPoint(method MethodType, path string, tags string, params []Parameter, body interface{}, ret interface{}, err interface{}, des string, secuirty []map[string][]string, args ...string) Endpoint { removedSpace := strings.ReplaceAll(tags, " ", "") endpoint := Endpoint{ Method: string(method), @@ -96,6 +97,7 @@ func EndPoint(method MethodType, path string, tags string, params []Parameter, b Body: body, Error: err, Description: des, + Security: secuirty, } if len(args) > 0 && len(args[0]) > 0 { endpoint.Consume = strings.Split(args[0], ",") @@ -367,3 +369,37 @@ func fillItemParams(param *Parameter) { param.Items.Pattern = param.Pattern param.Items.UniqueItems = param.UniqueItems } + +// Security + +func BasicAuth() []map[string][]string { + return []map[string][]string{ + { + "basicAuth": []string{}, + }, + } +} + +func ApiKeyAuth(name string) []map[string][]string { + return []map[string][]string{ + { + name: []string{}, + }, + } +} + +func OAuth(name string, scopes ...string) []map[string][]string { + return []map[string][]string{ + { + name: scopes, + }, + } +} + +func Security(schemes ...[]map[string][]string) []map[string][]string { + m := make([]map[string][]string, 0) + for _, scheme := range schemes { + m = append(m, scheme...) + } + return m +} diff --git a/example/fiber-multi-array/handlers/merchant_handler.go b/example/fiber-multi-array/handlers/merchant_handler.go index f16645e..ad450bd 100644 --- a/example/fiber-multi-array/handlers/merchant_handler.go +++ b/example/fiber-multi-array/handlers/merchant_handler.go @@ -21,6 +21,6 @@ func (h MerchantHandler) SetMerchantRoutes(a *fiber.App) { var MerchantEndpoints = []Endpoint{ // /merchant/{merchantId}?id={id} -> get product of a merchant - EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(GET, "/merchant", "merchant", Params(StrQuery("merchant", true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(GET, "/merchant", "merchant", Params(StrQuery("merchant", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), } diff --git a/example/fiber-multi-array/handlers/product_handler.go b/example/fiber-multi-array/handlers/product_handler.go index 0944280..11c3bf8 100644 --- a/example/fiber-multi-array/handlers/product_handler.go +++ b/example/fiber-multi-array/handlers/product_handler.go @@ -20,10 +20,10 @@ func (h ProductHandler) SetProductRoutes(a *fiber.App) { } var ProductEndpoints = []Endpoint{ - EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products"), - EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), + EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), // /merchant/{merchantId}?id={id} -> get product of a merchant - EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, "", nil), } diff --git a/example/fiber/handlers/handlers.go b/example/fiber/handlers/handlers.go index 02d6b25..576ddb4 100644 --- a/example/fiber/handlers/handlers.go +++ b/example/fiber/handlers/handlers.go @@ -22,46 +22,56 @@ func (h Handler) SetRoutes(a *fiber.App) { func (h *Handler) SetSwagger(a *fiber.App) { endpoints := []Endpoint{ - EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products"), - EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), + EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), // no return - EndPoint(POST, "/product-no-return", "product", Params(), nil, nil, models.ErrorResponse{}, ""), + EndPoint(POST, "/product-no-return", "product", Params(), nil, nil, models.ErrorResponse{}, "", nil), // no error - EndPoint(POST, "/product-no-error", "product", Params(), nil, nil, nil, ""), + EndPoint(POST, "/product-no-error", "product", Params(), nil, nil, nil, "", nil), // ids query enum - EndPoint(GET, "/products", "product", Params(IntEnumQuery("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/products", "product", Params(IntEnumQuery("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // ids path enum - EndPoint(GET, "/products2", "product", Params(IntEnumParam("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/products2", "product", Params(IntEnumParam("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // with fields - EndPoint(GET, "/productsMinMax", "product", Params(IntArrQuery("ids", nil, true, "test", Fields{Min: 0, Max: 10, Default: 5})), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/productsMinMax", "product", Params(IntArrQuery("ids", nil, true, "test", Fields{Min: 0, Max: 10, Default: 5})), nil, models.Product{}, models.ErrorResponse{}, "", nil), // string array query - EndPoint(GET, "/productsArr", "product", Params(StrArrQuery("strs", nil, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(GET, "/productsArrWithEnums", "product", Params(StrArrQuery("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(GET, "/productsArrWithEnumsInPath", "product", Params(StrArrParam("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/productsArr", "product", Params(StrArrQuery("strs", nil, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(GET, "/productsArrWithEnums", "product", Params(StrArrQuery("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(GET, "/productsArrWithEnumsInPath", "product", Params(StrArrParam("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // /merchant/{merchantId}?id={id} -> get product of a merchant - EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // with headers - EndPoint(POST, "/product", "header params", Params(IntHeader("header1", false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product2", "header params", Params(IntEnumHeader("header1", []int64{1, 2, 3}, false, ""), StrEnumHeader("header2", []string{"a", "b", "c"}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product3", "header params", Params(IntArrHeader("header1", []int64{1, 2, 3}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(POST, "/product-header", "header params", Params(IntHeader("header1", false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product2-header", "header params", Params(IntEnumHeader("header1", []int64{1, 2, 3}, false, ""), StrEnumHeader("header2", []string{"a", "b", "c"}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product3-header", "header params", Params(IntArrHeader("header1", []int64{1, 2, 3}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), // with file - EndPoint(POST, "/productUpload", "upload", Params(FileParam("file", true, "File to upload")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(POST, "/productUpload", "upload", Params(FileParam("file", true, "File to upload")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // without EndPoint function {Method: "GET", Path: "/product4", Description: "product", Params: Params(IntParam("id", true, "")), Return: models.Product{}, Error: models.ErrorResponse{}, Tags: []string{"WithStruct"}}, // without EndPoint function and without Params {Method: "GET", Path: "/product5", Description: "product", Params: []Parameter{{Name: "id", Type: "integer", In: "path", Required: true}}, Return: models.Product{}, Error: models.ErrorResponse{}, Tags: []string{"WithStruct"}}, + + // with security + EndPoint(POST, "/secure-product", "Secure", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "Only Basic Auth", BasicAuth()), + EndPoint(POST, "/multi-secure-product", "Secure", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "Basic Auth + Api Key Auth", Security(ApiKeyAuth("api_key"), BasicAuth())), + EndPoint(POST, "/secure-product-oauth", "Secure", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "OAuth", OAuth("oauth2_name", "read:pets")), } sw := CreateNewSwagger("Swagger API", "1.0") AddEndpoints(endpoints) + // set auth + sw.SetBasicAuth() + sw.SetApiKeyAuth("api_key", "query") + sw.SetOAuth2Auth("oauth2_name", "password", "http://localhost:8080/oauth2/token", "http://localhost:8080/oauth2/authorize", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) + // 3 alternative way for describing tags with descriptions sw.AddTags(Tag("product", "Product operations"), Tag("merchant", "Merchant operations")) sw.AddTags(SwaggerTag{Name: "WithStruct", Description: "WithStruct operations"}) diff --git a/example/gin/handlers/handlers.go b/example/gin/handlers/handlers.go index cc460a6..996e9f7 100644 --- a/example/gin/handlers/handlers.go +++ b/example/gin/handlers/handlers.go @@ -26,48 +26,55 @@ func (h Handler) SetRoutes(a *gin.Engine) { func (h *Handler) SetSwagger(a *gin.Engine) { endpoints := []Endpoint{ - EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products"), - EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), + EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), // no return - EndPoint(POST, "/product-no-return", "product", Params(), nil, nil, models.ErrorResponse{}, ""), + EndPoint(POST, "/product-no-return", "product", Params(), nil, nil, models.ErrorResponse{}, "", nil), // no error - EndPoint(POST, "/product-no-error", "product", Params(), nil, nil, nil, ""), + EndPoint(POST, "/product-no-error", "product", Params(), nil, nil, nil, "", nil), // ids query enum - EndPoint(GET, "/products", "product", Params(IntEnumQuery("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/products", "product", Params(IntEnumQuery("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // ids path enum - EndPoint(GET, "/products2", "product", Params(IntEnumParam("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/products2", "product", Params(IntEnumParam("ids", []int64{1, 2, 3}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // with fields - EndPoint(GET, "/productsMinMax", "product", Params(IntArrQuery("ids", nil, true, "test", Fields{Min: 0, Max: 10, Default: 5})), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/productsMinMax", "product", Params(IntArrQuery("ids", nil, true, "test", Fields{Min: 0, Max: 10, Default: 5})), nil, models.Product{}, models.ErrorResponse{}, "", nil), // string array query - EndPoint(GET, "/productsArr", "product", Params(StrArrQuery("strs", nil, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(GET, "/productsArrWithEnums", "product", Params(StrArrQuery("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(GET, "/productsArrWithEnumsInPath", "product", Params(StrArrParam("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/productsArr", "product", Params(StrArrQuery("strs", nil, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(GET, "/productsArrWithEnums", "product", Params(StrArrQuery("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(GET, "/productsArrWithEnumsInPath", "product", Params(StrArrParam("strs", []string{"test1", "test2"}, true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // /merchant/{merchantId}?id={id} -> get product of a merchant - EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/merchant", "merchant", Params(StrParam("merchant", true, ""), IntQuery("id", true, "product id")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // with headers - EndPoint(POST, "/product", "header params", Params(IntHeader("header1", false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product2", "header params", Params(IntEnumHeader("header1", []int64{1, 2, 3}, false, ""), StrEnumHeader("header2", []string{"a", "b", "c"}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product3", "header params", Params(IntArrHeader("header1", []int64{1, 2, 3}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(POST, "/product-header", "header params", Params(IntHeader("header1", false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product2-header", "header params", Params(IntEnumHeader("header1", []int64{1, 2, 3}, false, ""), StrEnumHeader("header2", []string{"a", "b", "c"}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product3-header", "header params", Params(IntArrHeader("header1", []int64{1, 2, 3}, false, "")), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), // with file - EndPoint(POST, "/productUpload", "upload", Params(FileParam("file", true, "File to upload")), nil, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(POST, "/productUpload", "upload", Params(FileParam("file", true, "File to upload")), nil, models.Product{}, models.ErrorResponse{}, "", nil), // without EndPoint function {Method: "GET", Path: "/product4", Description: "product", Params: Params(IntParam("id", true, "")), Return: models.Product{}, Error: models.ErrorResponse{}, Tags: []string{"WithStruct"}}, // without EndPoint function and without Params {Method: "GET", Path: "/product5", Description: "product", Params: []Parameter{{Name: "id", Type: "integer", In: "path", Required: true}}, Return: models.Product{}, Error: models.ErrorResponse{}, Tags: []string{"WithStruct"}}, + + // with security + EndPoint(POST, "/secure-product", "Secure", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "Only Basic Auth", BasicAuth()), + EndPoint(POST, "/multi-secure-product", "Secure", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "Basic Auth + Api Key Auth", Security(ApiKeyAuth("api_key"), BasicAuth())), + EndPoint(POST, "/secure-product-oauth", "Secure", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "OAuth", OAuth("oauth2_name", "read:pets")), } sw := CreateNewSwagger("Swagger API", "1.0") AddEndpoints(endpoints) + + // set auth sw.SetBasicAuth() sw.SetApiKeyAuth("api_key", "query") - sw.SetOAuth2Auth("oauth2", "implicit", "http://localhost:8080/oauth2/token", "http://localhost:8080/oauth2/authorize", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) + sw.SetOAuth2Auth("oauth2_name", "password", "http://localhost:8080/oauth2/token", "http://localhost:8080/oauth2/authorize", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) // 3 alternative way for describing tags with descriptions sw.AddTags(Tag("product", "Product operations"), Tag("merchant", "Merchant operations")) diff --git a/swagno.go b/swagno.go index 365140e..2b111a1 100644 --- a/swagno.go +++ b/swagno.go @@ -161,6 +161,7 @@ func (swagger Swagger) GenerateDocs() (jsonDocs []byte) { Tags: endpoint.Tags, Parameters: parameters, Responses: responses, + Security: endpoint.Security, } } json, err := json.MarshalIndent(swagger, "", " ") @@ -439,6 +440,7 @@ type swaggerEndpoint struct { OperationId string `json:"operationId,omitempty"` Parameters []swaggerParameter `json:"parameters"` Responses map[string]swaggerResponse `json:"responses"` + Security []map[string][]string `json:"security,omitempty"` } type swaggerParameter struct { From 2a16ba95c086338600bd875f6c55b5a8c48d4a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1l=20=C5=9Eenay?= Date: Sun, 4 Sep 2022 00:25:21 +0300 Subject: [PATCH 3/7] Update readme --- README.md | 199 ++++++++++++++++++++++++++++++++++++++++++++++++------ swagno.go | 2 +- 2 files changed, 181 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 1f493ef..96ea111 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ This project inspired by [Swaggo](https://github.com/swaggo/swag). Swaggo, uses - [General Swagger Info](#general-swagger-info) - [Adding Contact and License info (optional)](#adding-contact-and-license-info-optional) - [Adding Tags (optional)](#adding-tags-optional) + - [Security](#security) + - [Basic Auth](#basic-auth) + - [API Key Auth](#api-key-auth) + - [OAuth2](#oauth2-auth) - [Endpoints (API)](#endpoints-api) - [Contribution](#contribution) @@ -45,9 +49,9 @@ You can import without explicit period (.) like this: `import "github.com/go-swa ```go endpoints := []Endpoint{ - EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products"), - EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), + EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), } ``` @@ -208,15 +212,74 @@ sw.AddTags(SwaggerTag{Name: "WithStruct", Description: "WithStruct operations"}) sw.Tags = append(sw.Tags, SwaggerTag{Name: "headerparams", Description: "headerparams operations"}) ``` +## Security + +If you want to add security to your swagger, you can use `SetBasicAuth`, `SetApiKeyAuth`, `SetOAuth2Auth` functions. + +```go +sw.SetBasicAuth() +sw.SetApiKeyAuth("api_key", "header") +sw.SetOAuth2Auth("oauth2_name", "password", "http://localhost:8080/oauth2/token", "http://localhost:8080/oauth2/authorize", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) +``` + +#### Basic Auth + +If you have a basic auth with username and password, you can use `SetBasicAuth` function. + +```go +sw.SetBasicAuth() +``` + +#### Api Key Auth + +If you have an api key auth, you can use `SetApiKeyAuth` function. + +Parameters: + +- `name` -> name of the api key +- `in` -> location of the api key. It can be `header`, `query` + +```go +sw.SetApiKeyAuth("api_key", "header") +``` + +#### OAuth2 Auth + +If you have an oauth2 auth, you can use `SetOAuth2Auth` function. + +Parameters: + +- `name` -> name of the oauth2 +- `flow` -> flow type of the oauth2. It can be `implicit`, `password`, `application`, `accessCode` +- `authorizationUrl` -> authorization url of the oauth2 +- `tokenUrl` -> token url of the oauth2 +- `scopes` -> scopes of the oauth2 + +```go +sw.SetOAuth2Auth("oauth2_name", "password", "", "http://localhost:8080/oauth2/token", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) +``` + +For scopes, you can use `Scopes` function. It takes `Scope` as variadic parameter. +Parameters of `Scope`: + +- `name` -> name of the scope +- `description` -> description of the scope + ## Endpoints (API) +Defination: + +```go +EndPoint(method MethodType, path string, tags string, params []Parameter, body interface{}, ret interface{}, err interface{}, des string, secuirty []map[string][]string, args ...string) +``` + You need to create an Endpoint array []Endpoint and add your endpoints in this array. Example: ```go endpoints := []Endpoint{ - EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products"), - EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), + EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), } // add endpoints array to Swagno AddEndpoints(endpoints) @@ -228,9 +291,9 @@ AddEndpoints(endpoints) ```go endpoints := []swagno.Endpoint{ - swagno.EndPoint(swagno.GET, "/product", "product", swagno.Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products"), - swagno.EndPoint(swagno.GET, "/product", "product", swagno.Params(swagno.IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, ""), - swagno.EndPoint(swagno.POST, "/product", "product", swagno.Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, ""), + swagno.EndPoint(swagno.GET, "/product", "product", swagno.Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), + swagno.EndPoint(swagno.GET, "/product", "product", swagno.Params(swagno.IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + swagno.EndPoint(swagno.POST, "/product", "product", swagno.Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), } // add endpoints array to Swagno swagno.AddEndpoints(endpoints) @@ -245,24 +308,39 @@ endpoints := []Endpoint{ ``` ❗ **Don't forget to add your endpoints array to Swagno** ❗ + ```go AddEndpoints(endpoints) ``` -### Method +### Arguments: + +- [Method](#method) +- [Path](#path) +- [Tags](#tags) +- [Params](#params) +- [Body](#body) +- [Return](#return) +- [Error](#error) +- [Description](#description) +- [Security](#security) +- [Consumes](#consumes) (optional / extra argument) +- [Produces](#produces) (optional / extra argument) + +#### Method Options: GET, POST, PUT, DELETE, OPTION, PATCH, HEAD -### Path +#### Path Path of your endpoint without adding parameter options For example, you have endpoint as `/product/{id}?someParam=true` you need to add path as "/product" only, without params. -### Tags +#### Tags Tags as string seperated by comma -> "tag1,tag2" -### Params +#### Params You can use Params() function to generate params array: @@ -276,7 +354,7 @@ Or you can use []Parameter array: []Parameter{{Name: "id", Type: "integer", In: "path", Required: true}} ``` -#### Parameter Functions +##### Parameter Functions - **IntParam** _(name string, required bool, description string, args ...Fields)_ - **StrParam** _(name string, required bool, description string, args ...Fields)_ @@ -301,7 +379,7 @@ Or you can use []Parameter array: - **IntArrHeader** _(name string, arr []int64, required bool, description string, args ...Fields)_ - **StrArrHeader** _(name string, arr []string, required bool, description string, args ...Fields)_ -#### Parameter Options +##### Parameter Options | Parameter Option | Description | | ----------------- | -------------------------------------------------------------------------------------------- | @@ -333,22 +411,105 @@ Or you can use []Parameter array: | pipes | pipe separated values foo | bar. | | multi | corresponds to multiple parameter instances instead of multiple values for a single instance foo=bar&foo=baz. This is valid only for parameters in "query" or "formData".  | -### Body +#### Body use a struct model instance like `models.ProductPost{}` or nil -### Response/Return +#### Response/Return use a struct model instance like `models.Product{}` or nil -### Error Response +#### Error Response use a struct model instance like `models.ErrorResponse` or nil -### Description +#### Description Endpoint description as string +#### Security + +Before using this function, you need to define your security definitions in Swagno struct. For example: + +```go +sw.SetBasicAuth() +sw.SetApiKeyAuth("api_key", "query") +sw.SetOAuth2Auth("oauth2_name", "password", "http://localhost:8080/oauth2/token", "http://localhost:8080/oauth2/authorize", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) +``` + +If you want to add security to your endpoint, you can use one of `BasicAuth()`, `ApiKeyAuth()`, `OAuth()` functions: + +```go +BasicAuth() +``` + +```go +ApiKeyAuth("api_key", "header") +``` + +```go +OAuth("oauth2_name", "read:pets") +// you can add more scope name as argument +OAuth("oauth2_name", "read:pets", "write:pets", "...") +``` + +And use in `EndPoint` function: + +```go +EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", ApiKeyAuth("api_key", "header")) +``` + +You can add more than one security to your endpoint with `Security()` function: + +```go +EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", Security(ApiKeyAuth("api_key", "header"), BasicAuth())) +``` + +##### BasicAuth + +If you want to use basic auth to an endpoint, you can use `BasicAuth()` function. It has default name as "basicAuth". You can add description as argument: + +```go +BasicAuth("Basic Auth Description") +``` + +##### ApiKeyAuth + +If you want to use api key auth to an endpoint, you can use `ApiKeyAuth()` function. It needs name as argument. This name must match with one of your Swagno security definations. Also you can optionally add description as second argument: + +```go +ApiKeyAuth("api_key", "Api Key Auth Description") +``` + +##### OAuth2Auth + +If you want to use oauth2 auth to an endpoint, you can use `OAuth2Auth()` function. It needs name as argument. This name must match with one of your Swagno security definations. Then you can add scopes as arguments: + +```go +OAuth2Auth("oauth2_name", "read:pets", "write:pets") +``` + +#### Consumes (optional) + +For default there is only one consumes type: "application/json", you don't need to add it. If you want to add more consumes types, you can add them as string as seperated by commas to EndPoint function's extra option: + +```go +EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil, "application/xml,text/plain"), +``` + +**NOTE: If you used FileParam() in your endpoint, you don't need to add "multipart/form-data" to consumes. It will add automatically.** + +#### Produces (optional) + +For default there are two produces types: "application/json" and "application/xml", you don't need to add them. If you want to add more produces types, you can add them as string as seperated by commas to EndPoint function's extra option: + +```go +// without extra consumes -> nil as consumes +EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil, nil, "application/xml,text/plain"), +// with extra consumes +EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil, "application/xml,text/plain", "text/plain,text/html"), +``` + # Contribution We are welcome to any contribution. Swagno still has some missing features. Also we want to enrich handler implementations for other web frameworks. diff --git a/swagno.go b/swagno.go index 2b111a1..c52a358 100644 --- a/swagno.go +++ b/swagno.go @@ -124,7 +124,7 @@ func (swagger Swagger) GenerateDocs() (jsonDocs []byte) { } } - consumes := []string{"application/json", "application/xml"} + consumes := []string{"application/json"} produces := []string{"application/json", "application/xml"} for _, param := range endpoint.Params { if param.In == "formData" { From 983b952214a2a5c06710762f38659a2498a4274e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1l=20=C5=9Eenay?= Date: Sun, 4 Sep 2022 01:10:29 +0300 Subject: [PATCH 4/7] Update README.md --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 96ea111..8e79b03 100644 --- a/README.md +++ b/README.md @@ -165,9 +165,10 @@ As purpose of this section, you can compare **swagno** status with **swaggo** - [x] Describing Request Body - [x] Describing Responses - [x] MIME Types -> need to improve -- [ ] Authentication - - [ ] Basic Authentication - - [ ] API Keys +- [x] Authentication + - [x] Basic Authentication + - [x] API Keys + - [x] OAuth2 - [ ] Adding Examples - [x] File Upload -> need to improve - [x] Enums @@ -320,12 +321,12 @@ AddEndpoints(endpoints) - [Tags](#tags) - [Params](#params) - [Body](#body) -- [Return](#return) -- [Error](#error) +- [Return](#responsereturn) +- [Error](#error-response) - [Description](#description) - [Security](#security) -- [Consumes](#consumes) (optional / extra argument) -- [Produces](#produces) (optional / extra argument) +- [Consumes](#consumes-optional) (optional / extra argument) +- [Produces](#produces-optional) (optional / extra argument) #### Method From 7acabaf13c2afccd88511116c72868f6716cb911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1l=20=C5=9Eenay?= Date: Sun, 4 Sep 2022 01:30:13 +0300 Subject: [PATCH 5/7] Update README.md --- README.md | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 8e79b03..f70d741 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ This project inspired by [Swaggo](https://github.com/swaggo/swag). Swaggo, uses - [API Key Auth](#api-key-auth) - [OAuth2](#oauth2-auth) - [Endpoints (API)](#endpoints-api) + - [Arguments](#arguments) - [Contribution](#contribution) ## Getting started @@ -328,20 +329,20 @@ AddEndpoints(endpoints) - [Consumes](#consumes-optional) (optional / extra argument) - [Produces](#produces-optional) (optional / extra argument) -#### Method +### Method Options: GET, POST, PUT, DELETE, OPTION, PATCH, HEAD -#### Path +### Path Path of your endpoint without adding parameter options For example, you have endpoint as `/product/{id}?someParam=true` you need to add path as "/product" only, without params. -#### Tags +### Tags Tags as string seperated by comma -> "tag1,tag2" -#### Params +### Params You can use Params() function to generate params array: @@ -355,7 +356,7 @@ Or you can use []Parameter array: []Parameter{{Name: "id", Type: "integer", In: "path", Required: true}} ``` -##### Parameter Functions +#### Parameter Functions - **IntParam** _(name string, required bool, description string, args ...Fields)_ - **StrParam** _(name string, required bool, description string, args ...Fields)_ @@ -380,7 +381,7 @@ Or you can use []Parameter array: - **IntArrHeader** _(name string, arr []int64, required bool, description string, args ...Fields)_ - **StrArrHeader** _(name string, arr []string, required bool, description string, args ...Fields)_ -##### Parameter Options +#### Parameter Options | Parameter Option | Description | | ----------------- | -------------------------------------------------------------------------------------------- | @@ -404,31 +405,31 @@ Or you can use []Parameter array: | MultipleOf | see: https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00#section-5.1.1 | | CollenctionFormat | if type is "array", checkout the table above: | -| CollenctionFormat | Description | -| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -| csv | comma separated values foo,bar. | -| ssv | space separated values foo bar. | -| tsv | tab separated values foo\tbar. | -| pipes | pipe separated values foo | bar. | +| CollenctionFormat | Description | +| ----------------- | ----------------- | +| csv | comma separated values foo,bar.| +| ssv | space separated values foo bar.| +| tsv | tab separated values foo\tbar.| +| pipes | pipe separated values foo \| bar. | | multi | corresponds to multiple parameter instances instead of multiple values for a single instance foo=bar&foo=baz. This is valid only for parameters in "query" or "formData".  | -#### Body +### Body use a struct model instance like `models.ProductPost{}` or nil -#### Response/Return +### Response/Return use a struct model instance like `models.Product{}` or nil -#### Error Response +### Error Response use a struct model instance like `models.ErrorResponse` or nil -#### Description +### Description Endpoint description as string -#### Security +### Security Before using this function, you need to define your security definitions in Swagno struct. For example: @@ -466,7 +467,7 @@ You can add more than one security to your endpoint with `Security()` function: EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", Security(ApiKeyAuth("api_key", "header"), BasicAuth())) ``` -##### BasicAuth +#### BasicAuth If you want to use basic auth to an endpoint, you can use `BasicAuth()` function. It has default name as "basicAuth". You can add description as argument: @@ -474,7 +475,7 @@ If you want to use basic auth to an endpoint, you can use `BasicAuth()` function BasicAuth("Basic Auth Description") ``` -##### ApiKeyAuth +#### ApiKeyAuth If you want to use api key auth to an endpoint, you can use `ApiKeyAuth()` function. It needs name as argument. This name must match with one of your Swagno security definations. Also you can optionally add description as second argument: @@ -482,7 +483,7 @@ If you want to use api key auth to an endpoint, you can use `ApiKeyAuth()` funct ApiKeyAuth("api_key", "Api Key Auth Description") ``` -##### OAuth2Auth +#### OAuth2Auth If you want to use oauth2 auth to an endpoint, you can use `OAuth2Auth()` function. It needs name as argument. This name must match with one of your Swagno security definations. Then you can add scopes as arguments: @@ -490,7 +491,7 @@ If you want to use oauth2 auth to an endpoint, you can use `OAuth2Auth()` functi OAuth2Auth("oauth2_name", "read:pets", "write:pets") ``` -#### Consumes (optional) +### Consumes (optional) For default there is only one consumes type: "application/json", you don't need to add it. If you want to add more consumes types, you can add them as string as seperated by commas to EndPoint function's extra option: @@ -500,7 +501,7 @@ EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.E **NOTE: If you used FileParam() in your endpoint, you don't need to add "multipart/form-data" to consumes. It will add automatically.** -#### Produces (optional) +### Produces (optional) For default there are two produces types: "application/json" and "application/xml", you don't need to add them. If you want to add more produces types, you can add them as string as seperated by commas to EndPoint function's extra option: From 6486af7bc2d2a8dbb11db7efd78d975c3d446d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1l=20=C5=9Eenay?= Date: Sun, 4 Sep 2022 01:56:35 +0300 Subject: [PATCH 6/7] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f70d741..a42b9df 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Example: 1. Get swagno-fiber -```go +```sh go get github.com/go-swagno/swagno-fiber ``` @@ -132,7 +132,7 @@ Example: 1. Get swagno-gin -```go +```sh go get github.com/go-swagno/swagno-gin ``` From dd6aa44bee2c5030d342386bdcc4bda9e71dbfbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C4=B1l=20=C5=9Eenay?= Date: Sun, 4 Sep 2022 04:26:45 +0300 Subject: [PATCH 7/7] Update README.md --- README.md | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a42b9df..b67f6e7 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,9 @@ You can import without explicit period (.) like this: `import "github.com/go-swa ```go endpoints := []Endpoint{ - EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), - EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), - EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), + EndPoint(GET, "/product", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil), + EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil), } ``` @@ -226,36 +226,42 @@ sw.SetOAuth2Auth("oauth2_name", "password", "http://localhost:8080/oauth2/token" #### Basic Auth -If you have a basic auth with username and password, you can use `SetBasicAuth` function. +If you have a basic auth with username and password, you can use `SetBasicAuth` function. It has default name as "basicAuth". You can add description as argument: ```go sw.SetBasicAuth() +// with description +sw.SetBasicAuth("Description") ``` #### Api Key Auth -If you have an api key auth, you can use `SetApiKeyAuth` function. +If you have an api key auth, you can use `SetApiKeyAuth` function. Parameters: - `name` -> name of the api key -- `in` -> location of the api key. It can be `header`, `query` +- `in` -> location of the api key. It can be `header` or `query` +- `description` (optional) -> you can also add description as argument ```go sw.SetApiKeyAuth("api_key", "header") +// with description +sw.SetApiKeyAuth("api_key", "header", "Description") ``` #### OAuth2 Auth -If you have an oauth2 auth, you can use `SetOAuth2Auth` function. +If you have an oauth2 auth, you can use `SetOAuth2Auth` function. You can also add description as argument: Parameters: - `name` -> name of the oauth2 - `flow` -> flow type of the oauth2. It can be `implicit`, `password`, `application`, `accessCode` -- `authorizationUrl` -> authorization url of the oauth2 -- `tokenUrl` -> token url of the oauth2 +- `authorizationUrl` -> authorization url of the oauth2 (set this if flow is `impilicit` or `accessCode`, else you can set empty string) +- `tokenUrl` -> token url of the oauth2 (set this if flow is `password`, `application` or `accessCode`, else you can set empty string) - `scopes` -> scopes of the oauth2 +- `description` (optional) -> you can also add description as argument ```go sw.SetOAuth2Auth("oauth2_name", "password", "", "http://localhost:8080/oauth2/token", Scopes(Scope("read:pets", "read your pets"), Scope("write:pets", "modify pets in your account"))) @@ -287,7 +293,7 @@ endpoints := []Endpoint{ AddEndpoints(endpoints) ``` -- Arguments: (Method, Path, Tag, Params, Body, Response, Error Response, Description) +- Arguments: (Method, Path, Tag, Params, Body, Response, Error Response, Description, Security) **NOTE: If you not imported with explicit period (.), you need to get from swagno package:** @@ -446,7 +452,7 @@ BasicAuth() ``` ```go -ApiKeyAuth("api_key", "header") +ApiKeyAuth("api_key") ``` ```go @@ -458,7 +464,7 @@ OAuth("oauth2_name", "read:pets", "write:pets", "...") And use in `EndPoint` function: ```go -EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", ApiKeyAuth("api_key", "header")) +EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.Error{}, "description", ApiKeyAuth("api_key", "header")) ``` You can add more than one security to your endpoint with `Security()` function: @@ -469,7 +475,7 @@ EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.E #### BasicAuth -If you want to use basic auth to an endpoint, you can use `BasicAuth()` function. It has default name as "basicAuth". You can add description as argument: +If you want to use basic auth to an endpoint, you can use `BasicAuth()` function. ```go BasicAuth("Basic Auth Description") @@ -477,10 +483,10 @@ BasicAuth("Basic Auth Description") #### ApiKeyAuth -If you want to use api key auth to an endpoint, you can use `ApiKeyAuth()` function. It needs name as argument. This name must match with one of your Swagno security definations. Also you can optionally add description as second argument: +If you want to use api key auth to an endpoint, you can use `ApiKeyAuth()` function. It needs name as argument. This name must match with one of your Swagno security definations. ```go -ApiKeyAuth("api_key", "Api Key Auth Description") +ApiKeyAuth("api_key") ``` #### OAuth2Auth