-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #98 from illacloud/develop
Release: v1.6.1
- Loading branch information
Showing
5 changed files
with
307 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// Copyright 2022 The ILLA Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package graphql | ||
|
||
import ( | ||
"net/http" | ||
"net/url" | ||
|
||
"github.com/go-resty/resty/v2" | ||
) | ||
|
||
const ( | ||
AUTH_NONE = "none" | ||
AUTH_BASIC = "basic" | ||
AUTH_BEARER = "bearer" | ||
AUTH_APIKEY = "apiKey" | ||
) | ||
|
||
func (g *Connector) doQuery(baseURL string, queryParams, headers, cookies map[string]string, authentication string, | ||
authContent map[string]string, query string, vars map[string]interface{}) (*resty.Response, error) { | ||
|
||
client := resty.New() | ||
|
||
// corner case | ||
if authentication == AUTH_APIKEY && authContent["addTo"] == "urlParams" { | ||
queryParams[authContent["key"]] = authContent["value"] | ||
authentication = AUTH_NONE | ||
} | ||
|
||
// build request url | ||
uri, err := url.Parse(baseURL) | ||
if err != nil { | ||
return nil, err | ||
} | ||
params := url.Values{} | ||
for k, v := range queryParams { | ||
if k != "" { | ||
params.Set(k, v) | ||
} | ||
} | ||
uri.RawQuery = params.Encode() | ||
reqURL := uri.String() | ||
|
||
// set authentication | ||
switch authentication { | ||
case AUTH_BASIC: | ||
client.SetBasicAuth(authContent["username"], authContent["password"]) | ||
break | ||
case AUTH_BEARER: | ||
client.SetAuthToken(authContent["bearerToken"]) | ||
break | ||
case AUTH_APIKEY: | ||
client.SetAuthScheme(authContent["headerPrefix"]) | ||
client.SetAuthToken(authContent["value"]) | ||
break | ||
case AUTH_NONE: | ||
break | ||
} | ||
|
||
queryClient := client.R() | ||
|
||
// set headers | ||
queryClient.SetHeaders(headers) | ||
queryClient.SetHeader("Content-Type", "application/json") | ||
|
||
// set cookies | ||
reqCookies := make([]*http.Cookie, 0, len(cookies)) | ||
for k, v := range cookies { | ||
reqCookies = append(reqCookies, &http.Cookie{Name: k, Value: v}) | ||
} | ||
queryClient.SetCookies(reqCookies) | ||
|
||
// set body | ||
queryClient.SetBody(map[string]interface{}{ | ||
"query": query, | ||
"variables": vars, | ||
}) | ||
|
||
// do the query | ||
resp, err := queryClient.Post(reqURL) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return resp, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// Copyright 2022 The ILLA Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package graphql | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
|
||
"github.com/illa-family/builder-backend/pkg/plugins/common" | ||
|
||
"github.com/go-playground/validator/v10" | ||
"github.com/mitchellh/mapstructure" | ||
) | ||
|
||
type Connector struct { | ||
ResourceOpts Resource | ||
ActionOpts Action | ||
} | ||
|
||
func (g *Connector) ValidateResourceOptions(resourceOptions map[string]interface{}) (common.ValidateResult, error) { | ||
// format resource options | ||
if err := mapstructure.Decode(resourceOptions, &g.ResourceOpts); err != nil { | ||
return common.ValidateResult{Valid: false}, err | ||
} | ||
|
||
// validate graphql options | ||
validate := validator.New() | ||
if err := validate.Struct(g.ResourceOpts); err != nil { | ||
return common.ValidateResult{Valid: false}, err | ||
} | ||
|
||
return common.ValidateResult{Valid: true}, nil | ||
} | ||
|
||
func (g *Connector) ValidateActionOptions(actionOptions map[string]interface{}) (common.ValidateResult, error) { | ||
// format action options | ||
if err := mapstructure.Decode(actionOptions, &g.ActionOpts); err != nil { | ||
return common.ValidateResult{Valid: false}, err | ||
} | ||
|
||
// validate graphql options | ||
validate := validator.New() | ||
if err := validate.Struct(g.ActionOpts); err != nil { | ||
return common.ValidateResult{Valid: false}, err | ||
} | ||
|
||
return common.ValidateResult{Valid: true}, nil | ||
} | ||
|
||
func (g *Connector) TestConnection(resourceOptions map[string]interface{}) (common.ConnectionResult, error) { | ||
// format resource options | ||
if err := mapstructure.Decode(resourceOptions, &g.ResourceOpts); err != nil { | ||
return common.ConnectionResult{Success: false}, err | ||
} | ||
|
||
queryParams := make(map[string]string) | ||
headers := make(map[string]string) | ||
cookies := make(map[string]string) | ||
for _, param := range g.ResourceOpts.URLParams { | ||
if param["key"] != "" { | ||
queryParams[param["key"]] = param["value"] | ||
} | ||
} | ||
|
||
for _, header := range g.ResourceOpts.Headers { | ||
if header["key"] != "" { | ||
headers[header["key"]] = header["value"] | ||
} | ||
} | ||
|
||
for _, cookie := range g.ResourceOpts.Cookies { | ||
if cookie["key"] != "" { | ||
cookies[cookie["key"]] = cookie["value"] | ||
} | ||
} | ||
|
||
resp, err := g.doQuery(g.ResourceOpts.BaseURL, queryParams, headers, cookies, g.ResourceOpts.Authentication, | ||
g.ResourceOpts.AuthContent, "{__typename}", nil) | ||
if err != nil { | ||
return common.ConnectionResult{Success: false}, err | ||
} | ||
|
||
if resp.IsError() { | ||
return common.ConnectionResult{Success: false}, errors.New("unknown error") | ||
} | ||
|
||
return common.ConnectionResult{Success: true}, nil | ||
} | ||
|
||
func (g *Connector) GetMetaInfo(resourceOptions map[string]interface{}) (common.MetaInfoResult, error) { | ||
return common.MetaInfoResult{ | ||
Success: true, | ||
Schema: nil, | ||
}, nil | ||
} | ||
|
||
func (g *Connector) Run(resourceOptions map[string]interface{}, actionOptions map[string]interface{}) (common.RuntimeResult, error) { | ||
// format resource options | ||
if err := mapstructure.Decode(resourceOptions, &g.ResourceOpts); err != nil { | ||
return common.RuntimeResult{Success: false}, err | ||
} | ||
|
||
// format action options | ||
if err := mapstructure.Decode(actionOptions, &g.ActionOpts); err != nil { | ||
return common.RuntimeResult{Success: false}, err | ||
} | ||
|
||
queryParams := make(map[string]string) | ||
headers := make(map[string]string) | ||
cookies := make(map[string]string) | ||
for _, param := range g.ResourceOpts.URLParams { | ||
if param["key"] != "" { | ||
queryParams[param["key"]] = param["value"] | ||
} | ||
} | ||
|
||
for _, header := range g.ResourceOpts.Headers { | ||
if header["key"] != "" { | ||
headers[header["key"]] = header["value"] | ||
} | ||
} | ||
for _, header := range g.ActionOpts.Headers { | ||
if header["key"] != "" { | ||
headers[header["key"]] = header["value"] | ||
} | ||
} | ||
|
||
for _, cookie := range g.ResourceOpts.Cookies { | ||
if cookie["key"] != "" { | ||
cookies[cookie["key"]] = cookie["value"] | ||
} | ||
} | ||
|
||
vars := make(map[string]interface{}) | ||
for _, variable := range g.ActionOpts.Variables { | ||
if variable["key"] != "" { | ||
vars[variable["key"].(string)] = variable["value"] | ||
} | ||
} | ||
|
||
resp, err := g.doQuery(g.ResourceOpts.BaseURL, queryParams, headers, cookies, g.ResourceOpts.Authentication, | ||
g.ResourceOpts.AuthContent, g.ActionOpts.Query, vars) | ||
if err != nil { | ||
return common.RuntimeResult{Success: false}, err | ||
} | ||
|
||
if resp.IsError() { | ||
return common.RuntimeResult{Success: false}, errors.New("unknown error") | ||
} | ||
body := make(map[string]interface{}) | ||
if err := json.Unmarshal(resp.Body(), &body); err != nil { | ||
return common.RuntimeResult{Success: false}, err | ||
} | ||
|
||
return common.RuntimeResult{Success: true, Rows: []map[string]interface{}{body}}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright 2022 The ILLA Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package graphql | ||
|
||
type Resource struct { | ||
BaseURL string `validate:"required"` | ||
URLParams []map[string]string | ||
Headers []map[string]string | ||
Cookies []map[string]string | ||
Authentication string `validate:"required,oneof=none basic bearer apiKey"` | ||
AuthContent map[string]string | ||
DisableIntrospection bool | ||
} | ||
|
||
type Action struct { | ||
Query string | ||
Variables []map[string]interface{} | ||
Headers []map[string]string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters