fix: secret variables being populated as undefined on code snippets (#4180)

This commit is contained in:
Nivedin
2024-07-18 14:44:37 +05:30
committed by GitHub
parent 7ad3f660ae
commit 7ebc9a6fd6
9 changed files with 134 additions and 87 deletions

View File

@@ -38,6 +38,7 @@
"@hoppscotch/js-sandbox": "workspace:^",
"@hoppscotch/ui": "0.2.0",
"@hoppscotch/vue-toasted": "0.1.0",
"@hoppscotch/httpsnippet": "3.0.6",
"@lezer/highlight": "1.2.0",
"@unhead/vue": "1.8.8",
"@urql/core": "4.2.0",
@@ -58,7 +59,6 @@
"graphql": "16.8.1",
"graphql-language-service-interface": "2.10.2",
"graphql-tag": "2.12.6",
"httpsnippet": "3.0.1",
"insomnia-importers": "3.6.0",
"io-ts": "2.2.20",
"js-yaml": "4.1.0",

View File

@@ -178,7 +178,7 @@ const requestCode = computed(() => {
...aggregateEnvs,
],
}
const effectiveRequest = getEffectiveRESTRequest(request.value, env)
const effectiveRequest = getEffectiveRESTRequest(request.value, env, true)
const result = generateCode(
codegenType.value,

View File

@@ -126,7 +126,7 @@ export const parseCurlCommand = (curlCommand: string) => {
hasBodyBeenParsed = true
}
const urlString = concatParams(urlObject, danglingParams)
const urlString = decodeURIComponent(concatParams(urlObject, danglingParams))
let multipartUploads: Record<string, string> = pipe(
O.of(parsedArguments),

View File

@@ -53,7 +53,7 @@ const parseURL = (urlText: string | number) =>
u
.toString()
.replace(/^'|'$/g, "")
.replaceAll(/[^a-zA-Z0-9_\-./?&=:@%+#,;()'\s]/g, "")
.replaceAll(/[^a-zA-Z0-9_\-./?&=:@%+#,;()'<>\s]/g, "")
),
O.filter((u) => u.length > 0),
O.chain((u) =>

View File

@@ -1,4 +1,4 @@
import { HTTPSnippet } from "httpsnippet"
import { HTTPSnippet } from "@hoppscotch/httpsnippet"
import { HoppRESTRequest } from "@hoppscotch/data"
import * as O from "fp-ts/Option"
import * as E from "fp-ts/Either"

View File

@@ -69,10 +69,10 @@ export const getComputedAuthHeaders = (
// TODO: Support a better b64 implementation than btoa ?
if (request.auth.authType === "basic") {
const username = parse
? parseTemplateString(request.auth.username, envVars)
? parseTemplateString(request.auth.username, envVars, false, true)
: request.auth.username
const password = parse
? parseTemplateString(request.auth.password, envVars)
? parseTemplateString(request.auth.password, envVars, false, true)
: request.auth.password
headers.push({
@@ -92,16 +92,18 @@ export const getComputedAuthHeaders = (
headers.push({
active: true,
key: "Authorization",
value: `Bearer ${parse ? parseTemplateString(token, envVars) : token}`,
value: `Bearer ${
parse ? parseTemplateString(token, envVars, false, true) : token
}`,
})
} else if (request.auth.authType === "api-key") {
const { key, addTo } = request.auth
if (addTo === "HEADERS" && key) {
headers.push({
active: true,
key: parseTemplateString(key, envVars),
key: parseTemplateString(key, envVars, false, true),
value: parse
? parseTemplateString(request.auth.value ?? "", envVars)
? parseTemplateString(request.auth.value ?? "", envVars, false, true)
: request.auth.value ?? "",
})
}
@@ -215,8 +217,8 @@ export const getComputedParams = (
source: "auth" as const,
param: {
active: true,
key: parseTemplateString(req.auth.key, envVars),
value: parseTemplateString(req.auth.value, envVars),
key: parseTemplateString(req.auth.key, envVars, false, true),
value: parseTemplateString(req.auth.value, envVars, false, true),
},
},
]
@@ -230,7 +232,7 @@ export const getComputedParams = (
param: {
active: true,
key: "access_token",
value: parseTemplateString(grantTypeInfo.token, envVars),
value: parseTemplateString(grantTypeInfo.token, envVars, false, true),
},
},
]
@@ -244,6 +246,11 @@ export const resolvesEnvsInBody = (
if (!body.contentType) return body
if (body.contentType === "multipart/form-data") {
if (!body.body)
return {
contentType: "",
body: [],
}
return {
contentType: "multipart/form-data",
body: body.body.map(
@@ -251,10 +258,10 @@ export const resolvesEnvsInBody = (
<FormDataKeyValue>{
active: entry.active,
isFile: entry.isFile,
key: parseTemplateString(entry.key, env.variables),
key: parseTemplateString(entry.key, env.variables, false, true),
value: entry.isFile
? entry.value
: parseTemplateString(entry.value, env.variables),
: parseTemplateString(entry.value, env.variables, false, true),
}
),
}
@@ -262,13 +269,14 @@ export const resolvesEnvsInBody = (
return {
contentType: body.contentType,
body: parseTemplateString(body.body ?? "", env.variables),
body: parseTemplateString(body.body ?? "", env.variables, false, true),
}
}
function getFinalBodyFromRequest(
request: HoppRESTRequest,
envVariables: Environment["variables"]
envVariables: Environment["variables"],
showKeyIfSecret = false
): FormData | string | null {
if (request.body.contentType === null) return null
@@ -289,8 +297,8 @@ function getFinalBodyFromRequest(
* which will be resolved in further steps.
*/
A.map(({ key, value }) => [
parseTemplateStringE(key, envVariables),
parseTemplateStringE(value, envVariables),
parseTemplateStringE(key, envVariables, false, showKeyIfSecret),
parseTemplateStringE(value, envVariables, false, showKeyIfSecret),
]),
/**
@@ -349,12 +357,14 @@ function getFinalBodyFromRequest(
*
* @param request The request to source from
* @param environment The environment to apply
* @param showKeyIfSecret Whether to show the key if the value is a secret
*
* @returns An object with extra fields defining a complete request
*/
export function getEffectiveRESTRequest(
request: HoppRESTRequest,
environment: Environment
environment: Environment,
showKeyIfSecret = false
): EffectiveHoppRESTRequest {
const effectiveFinalHeaders = pipe(
getComputedHeaders(request, environment.variables).map((h) => h.header),
@@ -362,8 +372,18 @@ export function getEffectiveRESTRequest(
A.filter((x) => x.active && x.key !== ""),
A.map((x) => ({
active: true,
key: parseTemplateString(x.key, environment.variables),
value: parseTemplateString(x.value, environment.variables),
key: parseTemplateString(
x.key,
environment.variables,
false,
showKeyIfSecret
),
value: parseTemplateString(
x.value,
environment.variables,
false,
showKeyIfSecret
),
}))
)
@@ -373,8 +393,18 @@ export function getEffectiveRESTRequest(
A.filter((x) => x.active && x.key !== ""),
A.map((x) => ({
active: true,
key: parseTemplateString(x.key, environment.variables),
value: parseTemplateString(x.value, environment.variables),
key: parseTemplateString(
x.key,
environment.variables,
false,
showKeyIfSecret
),
value: parseTemplateString(
x.value,
environment.variables,
false,
showKeyIfSecret
),
}))
)
@@ -390,14 +420,17 @@ export function getEffectiveRESTRequest(
const effectiveFinalBody = getFinalBodyFromRequest(
request,
environment.variables
environment.variables,
showKeyIfSecret
)
return {
...request,
effectiveFinalURL: parseTemplateString(
request.endpoint,
environment.variables
environment.variables,
false,
showKeyIfSecret
),
effectiveFinalHeaders,
effectiveFinalParams,

View File

@@ -93,7 +93,8 @@ export function parseTemplateStringE(
variables:
| Environment["variables"]
| { secret: true; value: string; key: string }[],
maskValue = false
maskValue = false,
showKeyIfSecret = false
) {
if (!variables || !str) {
return E.right(str)
@@ -101,12 +102,22 @@ export function parseTemplateStringE(
let result = str
let depth = 0
let isSecret = false
while (result.match(REGEX_ENV_VAR) != null && depth <= ENV_MAX_EXPAND_LIMIT) {
while (
result.match(REGEX_ENV_VAR) != null &&
depth <= ENV_MAX_EXPAND_LIMIT &&
!isSecret
) {
result = decodeURI(encodeURI(result)).replace(REGEX_ENV_VAR, (_, p1) => {
const variable = variables.find((x) => x && x.key === p1)
if (variable && "value" in variable) {
// Show the key if it is a secret and explicitly specified
if (variable.secret && showKeyIfSecret) {
isSecret = true
return `<<${p1}>>`
}
// Mask the value if it is a secret and explicitly specified
if (variable.secret && maskValue) {
return "*".repeat(
@@ -144,10 +155,11 @@ export const parseTemplateString = (
variables:
| Environment["variables"]
| { secret: true; value: string; key: string }[],
maskValue = false
maskValue = false,
showKeyIfSecret = false
) =>
pipe(
parseTemplateStringE(str, variables, maskValue),
parseTemplateStringE(str, variables, maskValue, showKeyIfSecret),
E.getOrElse(() => str)
)