From acb050860af539581eacc4f0c4945c292b378950 Mon Sep 17 00:00:00 2001 From: Nerzal Date: Mon, 17 Apr 2023 20:58:12 +0200 Subject: [PATCH] V2: Fix tests after module upgrade (#1557) * V2: Fix tests after v2 module upgrade * formData is now being placed into the request body instead of the parameters --------- Co-authored-by: Tobias Theel --- enums_test.go | 2 +- gen/gen_test.go | 2 +- operationv3.go | 14 +++--- operationv3_test.go | 42 +++++++--------- parser_test.go | 6 +-- parserv3_test.go | 5 +- testdata/conflict_name/expected.json | 16 +++--- .../internal/expected.json | 50 +++++++++---------- testdata/v3/simple/api/api.go | 6 +++ testdata/v3/simple/main.go | 1 + testdata/v3/simple/web/handler.go | 13 +++++ 11 files changed, 89 insertions(+), 68 deletions(-) diff --git a/enums_test.go b/enums_test.go index 1d8e1930f..f730dd647 100644 --- a/enums_test.go +++ b/enums_test.go @@ -14,7 +14,7 @@ func TestParseGlobalEnums(t *testing.T) { err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth) require.NoError(t, err) - const constsPath = "github.com/swaggo/swag/testdata/enums/consts" + const constsPath = "github.com/swaggo/swag/v2/testdata/enums/consts" table := p.packages.packages[constsPath].ConstTable require.NotNil(t, table, "const table must not be nil") diff --git a/gen/gen_test.go b/gen/gen_test.go index 95ed3fc71..aade104f8 100644 --- a/gen/gen_test.go +++ b/gen/gen_test.go @@ -223,7 +223,7 @@ func TestGen_BuildDescriptionWithQuotes(t *testing.T) { require.NoError(t, err) } } - cmd := exec.Command("go", "build", "-buildmode=plugin", "github.com/swaggo/swag/testdata/quotes") + cmd := exec.Command("go", "build", "-buildmode=plugin", "github.com/swaggo/swag/v2/testdata/quotes") cmd.Dir = config.SearchDir diff --git a/operationv3.go b/operationv3.go index 393de54b6..f54c59e2a 100644 --- a/operationv3.go +++ b/operationv3.go @@ -364,7 +364,7 @@ func (o *OperationV3) ParseParamComment(commentLine string, astFile *ast.File) e case OBJECT: return fmt.Errorf("%s is not supported type for %s", refType, paramType) } - case "query", "formData": + case "query": switch objectType { case ARRAY: if !IsPrimitiveType(refType) && !(refType == "file" && paramType == "formData") { @@ -417,7 +417,7 @@ func (o *OperationV3) ParseParamComment(commentLine string, astFile *ast.File) e return nil } - case "body": + case "body", "formData": if objectType == PRIMITIVE { schema := PrimitiveSchemaV3(refType) @@ -426,7 +426,7 @@ func (o *OperationV3) ParseParamComment(commentLine string, astFile *ast.File) e return err } - o.fillRequestBody(schema, required, description, true) + o.fillRequestBody(schema, required, description, true, paramType == "formData") return nil @@ -442,7 +442,7 @@ func (o *OperationV3) ParseParamComment(commentLine string, astFile *ast.File) e return err } - o.fillRequestBody(schema, required, description, false) + o.fillRequestBody(schema, required, description, false, paramType == "formData") return nil @@ -464,13 +464,15 @@ func (o *OperationV3) ParseParamComment(commentLine string, astFile *ast.File) e return nil } -func (o *OperationV3) fillRequestBody(schema *spec.RefOrSpec[spec.Schema], required bool, description string, primitive bool) { +func (o *OperationV3) fillRequestBody(schema *spec.RefOrSpec[spec.Schema], required bool, description string, primitive, formData bool) { if o.RequestBody == nil { o.RequestBody = spec.NewRequestBodySpec() o.RequestBody.Spec.Spec.Content = make(map[string]*spec.Extendable[spec.MediaType]) - if primitive { + if primitive && !formData { o.RequestBody.Spec.Spec.Content["text/plain"] = spec.NewMediaType() + } else if formData { + o.RequestBody.Spec.Spec.Content["application/x-www-form-urlencoded"] = spec.NewMediaType() } else { o.RequestBody.Spec.Spec.Content["application/json"] = spec.NewMediaType() } diff --git a/operationv3_test.go b/operationv3_test.go index 7e5ad86b4..6d79ca4cf 100644 --- a/operationv3_test.go +++ b/operationv3_test.go @@ -773,7 +773,7 @@ func TestOperation_ParseParamCommentV3(t *testing.T) { t.Run("integer", func(t *testing.T) { t.Parallel() - for _, paramType := range []string{"header", "path", "query", "formData"} { + for _, paramType := range []string{"header", "path", "query"} { t.Run(paramType, func(t *testing.T) { o := NewOperationV3(New()) err := o.ParseComment(`@Param some_id `+paramType+` int true "Some ID"`, nil) @@ -808,7 +808,7 @@ func TestOperation_ParseParamCommentV3(t *testing.T) { t.Run("string", func(t *testing.T) { t.Parallel() - for _, paramType := range []string{"header", "path", "query", "formData"} { + for _, paramType := range []string{"header", "path", "query"} { t.Run(paramType, func(t *testing.T) { o := NewOperationV3(New()) err := o.ParseComment(`@Param some_string `+paramType+` string true "Some String"`, nil) @@ -842,7 +842,7 @@ func TestOperation_ParseParamCommentV3(t *testing.T) { t.Run("object", func(t *testing.T) { t.Parallel() - for _, paramType := range []string{"header", "path", "query", "formData"} { + for _, paramType := range []string{"header", "path", "query"} { t.Run(paramType, func(t *testing.T) { assert.Error(t, NewOperationV3(New()). @@ -1108,18 +1108,17 @@ func TestParseParamCommentByFormDataTypeV3(t *testing.T) { err := operation.ParseComment(comment, nil) assert.NoError(t, err) - assert.Len(t, operation.Parameters, 1) + assert.Len(t, operation.Parameters, 0) + assert.NotNil(t, operation.RequestBody) - parameters := operation.Operation.Parameters - assert.NotNil(t, parameters) + requestBody := operation.RequestBody + assert.True(t, requestBody.Spec.Spec.Required) + assert.Equal(t, "this is a test file", requestBody.Spec.Spec.Description) + assert.NotNil(t, requestBody) - parameterSpec := parameters[0].Spec.Spec - assert.NotNil(t, parameterSpec) - assert.Equal(t, "this is a test file", parameterSpec.Description) - assert.Equal(t, "file", parameterSpec.Name) - assert.True(t, parameterSpec.Required) - assert.Equal(t, "formData", parameterSpec.In) - assert.Equal(t, typeFile, parameterSpec.Schema.Spec.Type) + requestBodySpec := requestBody.Spec.Spec + assert.NotNil(t, requestBodySpec) + assert.Equal(t, typeFile, requestBodySpec.Content["application/x-www-form-urlencoded"].Spec.Schema.Spec.Type) } func TestParseParamCommentByFormDataTypeUint64V3(t *testing.T) { @@ -1131,18 +1130,15 @@ func TestParseParamCommentByFormDataTypeUint64V3(t *testing.T) { err := operation.ParseComment(comment, nil) assert.NoError(t, err) - assert.Len(t, operation.Parameters, 1) + assert.Len(t, operation.Parameters, 0) - parameters := operation.Operation.Parameters - assert.NotNil(t, parameters) + requestBody := operation.RequestBody + assert.NotNil(t, requestBody) + assert.Equal(t, "this is a test file", requestBody.Spec.Spec.Description) - parameterSpec := parameters[0].Spec.Spec - assert.NotNil(t, parameterSpec) - assert.Equal(t, "this is a test file", parameterSpec.Description) - assert.Equal(t, "file", parameterSpec.Name) - assert.True(t, parameterSpec.Required) - assert.Equal(t, "formData", parameterSpec.In) - assert.Equal(t, typeInteger, parameterSpec.Schema.Spec.Type) + requestBodySpec := requestBody.Spec.Spec.Content["application/x-www-form-urlencoded"].Spec + assert.NotNil(t, requestBodySpec) + assert.Equal(t, typeInteger, requestBodySpec.Schema.Spec.Type) } func TestParseParamCommentByNotSupportedTypeV3(t *testing.T) { diff --git a/parser_test.go b/parser_test.go index ea29728bb..92cb0624d 100644 --- a/parser_test.go +++ b/parser_test.go @@ -2142,9 +2142,9 @@ func TestParseTypeOverrides(t *testing.T) { searchDir := "testdata/global_override" p := New(SetOverrides(map[string]string{ - "github.com/swaggo/swag/testdata/global_override/types.Application": "string", - "github.com/swaggo/swag/testdata/global_override/types.Application2": "github.com/swaggo/swag/testdata/global_override/othertypes.Application", - "github.com/swaggo/swag/testdata/global_override/types.ShouldSkip": "", + "github.com/swaggo/swag/v2/testdata/global_override/types.Application": "string", + "github.com/swaggo/swag/v2/testdata/global_override/types.Application2": "github.com/swaggo/swag/v2/testdata/global_override/othertypes.Application", + "github.com/swaggo/swag/v2/testdata/global_override/types.ShouldSkip": "", })) err := p.ParseAPI(searchDir, mainAPIFile, defaultParseDepth) assert.NoError(t, err) diff --git a/parserv3_test.go b/parserv3_test.go index 70680722f..b889188cf 100644 --- a/parserv3_test.go +++ b/parserv3_test.go @@ -355,7 +355,7 @@ func TestParseSimpleApiV3(t *testing.T) { assert.NoError(t, err) paths := p.openAPI.Paths.Spec.Paths - assert.Equal(t, 14, len(paths)) + assert.Equal(t, 15, len(paths)) path := paths["/testapi/get-string-by-int/{some_id}"].Spec.Spec.Get.Spec assert.Equal(t, "get string by ID", path.Description) @@ -365,5 +365,8 @@ func TestParseSimpleApiV3(t *testing.T) { response := path.Responses.Spec.Response["200"] assert.Equal(t, "ok", response.Spec.Spec.Description) + path = paths["/FormData"].Spec.Spec.Post.Spec + assert.NotNil(t, path) + assert.NotNil(t, path.RequestBody) //TODO add asserts } diff --git a/testdata/conflict_name/expected.json b/testdata/conflict_name/expected.json index 0b3576dbc..68aa1440d 100644 --- a/testdata/conflict_name/expected.json +++ b/testdata/conflict_name/expected.json @@ -24,7 +24,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_conflict_name_model.ErrorsResponse" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_conflict_name_model.ErrorsResponse" } } } @@ -47,7 +47,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_conflict_name_model2.ErrorsResponse" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_conflict_name_model2.ErrorsResponse" } } } @@ -55,7 +55,7 @@ } }, "definitions": { - "github_com_swaggo_swag_testdata_conflict_name_model.ErrorsResponse": { + "github_com_swaggo_swag_v2_testdata_conflict_name_model.ErrorsResponse": { "type": "object", "properties": { "newTime": { @@ -63,7 +63,7 @@ } } }, - "github_com_swaggo_swag_testdata_conflict_name_model.MyStruct": { + "github_com_swaggo_swag_v2_testdata_conflict_name_model.MyStruct": { "type": "object", "properties": { "name": { @@ -71,7 +71,7 @@ } } }, - "github_com_swaggo_swag_testdata_conflict_name_model2.ErrorsResponse": { + "github_com_swaggo_swag_v2_testdata_conflict_name_model2.ErrorsResponse": { "type": "object", "properties": { "newTime": { @@ -79,7 +79,7 @@ } } }, - "github_com_swaggo_swag_testdata_conflict_name_model2.MyStruct": { + "github_com_swaggo_swag_v2_testdata_conflict_name_model2.MyStruct": { "type": "object", "properties": { "name": { @@ -91,7 +91,7 @@ "type": "object", "properties": { "my": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_conflict_name_model.MyStruct" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_conflict_name_model.MyStruct" }, "name": { "type": "string" @@ -102,7 +102,7 @@ "type": "object", "properties": { "my": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_conflict_name_model2.MyStruct" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_conflict_name_model2.MyStruct" }, "name": { "type": "string" diff --git a/testdata/generics_package_alias/internal/expected.json b/testdata/generics_package_alias/internal/expected.json index 2f6c85f52..c796453ce 100644 --- a/testdata/generics_package_alias/internal/expected.json +++ b/testdata/generics_package_alias/internal/expected.json @@ -18,7 +18,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1_ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1_ProductDto" } } } @@ -58,7 +58,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1_ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1_ProductDto" } } } @@ -98,7 +98,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1_ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1_ProductDto" } } } @@ -138,7 +138,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1_ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1_ProductDto" } } } @@ -158,7 +158,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1_ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1_ProductDto" } } } @@ -178,7 +178,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1_ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1_ProductDto" } } } @@ -198,7 +198,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1_ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1_ProductDto" } } } @@ -218,7 +218,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external1_Customer" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external1_Customer" } } } @@ -238,7 +238,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external2_Customer" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external2_Customer" } } } @@ -258,7 +258,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external3_Customer" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external3_Customer" } } } @@ -278,7 +278,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external4_Customer" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external4_Customer" } } } @@ -399,7 +399,7 @@ } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external1_Customer": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external1_Customer": { "type": "object", "properties": { "items1": { @@ -410,7 +410,7 @@ } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external2_Customer": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external2_Customer": { "type": "object", "properties": { "items1": { @@ -421,7 +421,7 @@ } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external3_Customer": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external3_Customer": { "type": "object", "properties": { "items1": { @@ -432,7 +432,7 @@ } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-external4_Customer": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-external4_Customer": { "type": "object", "properties": { "items1": { @@ -443,29 +443,29 @@ } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1_ProductDto": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1_ProductDto": { "type": "object", "properties": { "items1": { "type": "array", "items": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ProductDto" } } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1_ProductDto": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1_ProductDto": { "type": "object", "properties": { "items1": { "type": "array", "items": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ProductDto" } } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ProductDto": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ProductDto": { "type": "object", "properties": { "name1": { @@ -473,29 +473,29 @@ } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1_ProductDto": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1_ProductDto": { "type": "object", "properties": { "items2": { "type": "array", "items": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path1_v1.ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path1_v1.ProductDto" } } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1_ProductDto": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ListResult-github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1_ProductDto": { "type": "object", "properties": { "items2": { "type": "array", "items": { - "$ref": "#/definitions/github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ProductDto" + "$ref": "#/definitions/github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ProductDto" } } } }, - "github_com_swaggo_swag_testdata_generics_package_alias_internal_path2_v1.ProductDto": { + "github_com_swaggo_swag_v2_testdata_generics_package_alias_internal_path2_v1.ProductDto": { "type": "object", "properties": { "name2": { diff --git a/testdata/v3/simple/api/api.go b/testdata/v3/simple/api/api.go index 116d5e86a..91433b466 100644 --- a/testdata/v3/simple/api/api.go +++ b/testdata/v3/simple/api/api.go @@ -138,3 +138,9 @@ func GetPet6FunctionScopedResponse() { Name string } } + +// @param Token formData web.Request true "Params" comment +// @Router /FormData [post] +func FormData() { + +} diff --git a/testdata/v3/simple/main.go b/testdata/v3/simple/main.go index 0b960233b..a4721c6c6 100644 --- a/testdata/v3/simple/main.go +++ b/testdata/v3/simple/main.go @@ -24,5 +24,6 @@ func main() { http.HandleFunc("/testapi/get-string-by-int/", api.GetStringByInt) http.HandleFunc("/testapi/get-struct-array-by-string/", api.GetStructArrayByString) http.HandleFunc("/testapi/upload", api.Upload) + http.ListenAndServe(":8080", nil) } diff --git a/testdata/v3/simple/web/handler.go b/testdata/v3/simple/web/handler.go index e67a67f40..3afcdd0d1 100644 --- a/testdata/v3/simple/web/handler.go +++ b/testdata/v3/simple/web/handler.go @@ -99,3 +99,16 @@ type Pet5c struct { *Pet5b Odd bool `json:"odd" binding:"required"` } + +type Request struct { + GrantType string `json:"grant_type" validate:"required"` + ClientID string `json:"client_id" validate:"required"` + ClientSecret string `json:"client_secret" validate:"required"` + RedirectURI string `json:"redirect_uri"` + Code string `json:"code"` + CodeVerifier string `json:"code_verifier"` + Scope string `json:"scope"` + Username string `json:"username"` + Password string `json:"password"` + RefreshToken string `json:"refresh_token"` +}