#133: Fixed YAML parsing bug in OpenAPI parser

This commit is contained in:
frikky
2020-12-09 15:31:24 +01:00
parent 84d527ac77
commit 97856fcd56
4 changed files with 69 additions and 21 deletions
+23 -8
View File
@@ -5846,7 +5846,7 @@ func echoOpenapiData(resp http.ResponseWriter, request *http.Request) {
req, err := http.NewRequest("GET", newbody, nil) req, err := http.NewRequest("GET", newbody, nil)
if err != nil { if err != nil {
log.Printf("Requestbuilder err: %s", err) log.Printf("[ERROR] Requestbuilder err: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Failed building request"}`)) resp.Write([]byte(`{"success": false, "reason": "Failed building request"}`))
return return
@@ -5855,14 +5855,16 @@ func echoOpenapiData(resp http.ResponseWriter, request *http.Request) {
httpClient := &http.Client{} httpClient := &http.Client{}
newresp, err := httpClient.Do(req) newresp, err := httpClient.Do(req)
if err != nil { if err != nil {
log.Printf("[ERROR] Grabbing error: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed making request for data"`))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed making remote request to get the data"}`)))
return return
} }
defer newresp.Body.Close() defer newresp.Body.Close()
urlbody, err := ioutil.ReadAll(newresp.Body) urlbody, err := ioutil.ReadAll(newresp.Body)
if err != nil { if err != nil {
log.Printf("[ERROR] URLbody error: %s", err)
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't get data from selected uri"`))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Can't get data from selected uri"`)))
return return
@@ -6035,6 +6037,8 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
// support map[string]interface and similar (openapi3.Swagger) // support map[string]interface and similar (openapi3.Swagger)
var version versionCheck var version versionCheck
log.Printf("API length SET: %d", len(string(body)))
isJson := false isJson := false
err = json.Unmarshal(body, &version) err = json.Unmarshal(body, &version)
if err != nil { if err != nil {
@@ -6042,11 +6046,11 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
err = yaml.Unmarshal(body, &version) err = yaml.Unmarshal(body, &version)
if err != nil { if err != nil {
log.Printf("Yaml error (3): %s", err) log.Printf("Yaml error (3): %s", err)
//resp.WriteHeader(422) resp.WriteHeader(422)
//resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed reading openapi to json and yaml: %s"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed reading openapi to json and yaml. Is version defined?: %s"}`, err)))
//return return
} else { } else {
log.Printf("Successfully parsed YAML!") log.Printf("Successfully parsed YAML (3)!")
} }
} else { } else {
isJson = true isJson = true
@@ -6056,6 +6060,8 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
if len(version.SwaggerVersion) > 0 && len(version.Swagger) == 0 { if len(version.SwaggerVersion) > 0 && len(version.Swagger) == 0 {
version.Swagger = version.SwaggerVersion version.Swagger = version.SwaggerVersion
} }
log.Printf("Version: %#v", version)
log.Printf("OpenAPI: %s", version.OpenAPI)
if strings.HasPrefix(version.Swagger, "3.") || strings.HasPrefix(version.OpenAPI, "3.") { if strings.HasPrefix(version.Swagger, "3.") || strings.HasPrefix(version.OpenAPI, "3.") {
log.Println("Handling v3 API") log.Println("Handling v3 API")
@@ -6077,9 +6083,16 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
log.Printf("FIXME: NEED TO TRANSFORM FROM YAML TO JSON for %s", idstring) log.Printf("FIXME: NEED TO TRANSFORM FROM YAML TO JSON for %s", idstring)
} }
swaggerdata, err := json.Marshal(swagger)
if err != nil {
log.Printf("Failed unmarshaling v3 data: %s", err)
resp.WriteHeader(422)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed marshalling swaggerv3 data: %s"}`, err)))
return
}
parsed := ParsedOpenApi{ parsed := ParsedOpenApi{
ID: idstring, ID: idstring,
Body: string(body), Body: string(swaggerdata),
} }
ctx := context.Background() ctx := context.Background()
@@ -6090,6 +6103,8 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed reading openapi2: %s"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed reading openapi2: %s"}`, err)))
return return
} }
log.Printf("Successfully set OpenAPI with ID %s", idstring)
resp.WriteHeader(200) resp.WriteHeader(200)
resp.Write([]byte(fmt.Sprintf(`{"success": true, "id": "%s"}`, idstring))) resp.Write([]byte(fmt.Sprintf(`{"success": true, "id": "%s"}`, idstring)))
return return
@@ -6124,7 +6139,7 @@ func validateSwagger(resp http.ResponseWriter, request *http.Request) {
swaggerdata, err := json.Marshal(swaggerv3) swaggerdata, err := json.Marshal(swaggerv3)
if err != nil { if err != nil {
log.Printf("Failed unmarshaling v3 data: %s", err) log.Printf("Failed unmarshaling v3 from v2 data: %s", err)
resp.WriteHeader(422) resp.WriteHeader(422)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed marshalling swaggerv3 data: %s"}`, err))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed marshalling swaggerv3 data: %s"}`, err)))
return return
+1
View File
@@ -972,6 +972,7 @@ const AngularWorkflow = (props) => {
setLastSaved(false) setLastSaved(false)
/* /*
// Used to not be able to edit trigger-based branches.
const triggercheck = workflow.triggers.find(trigger => trigger.id === event.target.data()["source"]) const triggercheck = workflow.triggers.find(trigger => trigger.id === event.target.data()["source"])
if (triggercheck === undefined) { if (triggercheck === undefined) {
*/ */
+29 -4
View File
@@ -26,6 +26,7 @@ import CircularProgress from '@material-ui/core/CircularProgress';
import Chip from '@material-ui/core/Chip'; import Chip from '@material-ui/core/Chip';
import ChipInput from 'material-ui-chip-input' import ChipInput from 'material-ui-chip-input'
import YAML from 'yaml'
import ErrorOutline from '@material-ui/icons/ErrorOutline'; import ErrorOutline from '@material-ui/icons/ErrorOutline';
import { useAlert } from "react-alert"; import { useAlert } from "react-alert";
import words from "shellwords" import words from "shellwords"
@@ -325,15 +326,37 @@ const AppCreator = (props) => {
throw new Error("NOT 200 :O") throw new Error("NOT 200 :O")
} }
//console.log("DATA: ", response.text())
return response.json() return response.json()
}) })
.then((responseJson) => { .then((responseJson) => {
console.log("THE BODY IS HERE")
setIsAppLoaded(true) setIsAppLoaded(true)
if (!responseJson.success) { if (!responseJson.success) {
alert.error("Failed to verify") alert.error("Failed to verify")
} else { } else{
const data = JSON.parse(responseJson.body) console.log("HMM 2")
parseIncomingOpenapiData(data) var jsonvalid = false
var tmpvalue = ""
try {
tmpvalue = JSON.parse(responseJson.body)
jsonvalid = true
} catch (e) {
console.log("Error JSON: ", e)
}
if (!jsonvalid) {
try {
tmpvalue = YAML.parse(responseJson.body, )
jsonvalid = true
} catch(e) {
console.log("Error YAML: ", e)
}
}
if (jsonvalid) {
parseIncomingOpenapiData(tmpvalue)
}
} }
}) })
.catch(error => { .catch(error => {
@@ -359,13 +382,15 @@ const AppCreator = (props) => {
// Sets the data up as it should be at later points // Sets the data up as it should be at later points
// This is the data FROM the database, not what's being saved // This is the data FROM the database, not what's being saved
const parseIncomingOpenapiData = (data) => { const parseIncomingOpenapiData = (data) => {
//console.log("DATA: ", data.info)
setBasedata(data) setBasedata(data)
if (data.info !== null && data.info !== undefined) {
console.log("DATA: ", data)
setName(data.info.title) setName(data.info.title)
setDescription(data.info.description) setDescription(data.info.description)
document.title = "Apps - "+data.info.title document.title = "Apps - "+data.info.title
if (data.info !== null && data.info !== undefined) {
if (data.info["x-logo"] !== undefined) { if (data.info["x-logo"] !== undefined) {
setFileBase64(data.info["x-logo"]) setFileBase64(data.info["x-logo"])
} }
+11 -4
View File
@@ -1167,6 +1167,7 @@ const Apps = (props) => {
return return
} }
console.log("Validating response!")
validateOpenApi(responseJson) validateOpenApi(responseJson)
}) })
.catch(error => { .catch(error => {
@@ -1185,10 +1186,12 @@ const Apps = (props) => {
try { try {
return JSON.stringify(YAML.parse(apidata)) const parsed = YAML.parse(YAML.stringify(apidata))
//const parsed = YAML.parse(apidata))
return YAML.stringify(parsed)
} catch(error) { } catch(error) {
console.log("YAML DECODE ERROR - TRY SOMETHING ELSE?: "+error) console.log("YAML DECODE ERROR - TRY SOMETHING ELSE?: "+error)
setOpenApiError(error.toString()) setOpenApiError("Local error: "+ error.toString())
} }
return "" return ""
@@ -1197,18 +1200,22 @@ const Apps = (props) => {
// Sends the data to backend, which should return a version 3 of the same API // Sends the data to backend, which should return a version 3 of the same API
// If 200 - continue, otherwise, there's some issue somewhere // If 200 - continue, otherwise, there's some issue somewhere
const validateOpenApi = (openApidata) => { const validateOpenApi = (openApidata) => {
const newApidata = escapeApiData(openApidata) var newApidata = escapeApiData(openApidata)
if (newApidata === "") { if (newApidata === "") {
// Used to return here
newApidata = openApidata
return return
} }
//console.log(newApidata)
setValidation(true) setValidation(true)
fetch(globalUrl+"/api/v1/validate_openapi", { fetch(globalUrl+"/api/v1/validate_openapi", {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
}, },
body: newApidata, body: openApidata,
credentials: "include", credentials: "include",
}) })
.then((response) => { .then((response) => {