From 494356e13404f9029ef69a79e1d75a75267be8d5 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Mon, 16 Dec 2024 13:13:06 -0600 Subject: [PATCH 1/2] prevent credentials from appearing in code snippets --- .../theme/ApiExplorer/CodeSnippets/index.tsx | 85 +++++++++---------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx index efa351cd3..11bbd05df 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx @@ -5,13 +5,6 @@ * LICENSE file in the root directory of this source tree. * ========================================================================== */ -/* ============================================================================ - * Copyright (c) Palo Alto Networks - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * ========================================================================== */ - import React, { useState, useEffect } from "react"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; @@ -59,6 +52,38 @@ function CodeSnippets({ postman, codeSamples }: Props) { const headerParams = useTypedSelector((state: any) => state.params.header); const auth = useTypedSelector((state: any) => state.auth); + const clonedAuth = JSON.parse(JSON.stringify(auth)); + + function scrubCredentials(obj: any) { + for (const key in obj) { + if (typeof obj[key] === "object" && obj[key] !== null) { + obj[key] = scrubCredentials(obj[key]); + } else { + obj[key] = `<${key}>`; + } + } + + return obj; + } + + // scrub credentials from code snippets + const cleanedAuth = { + ...clonedAuth, + data: scrubCredentials(clonedAuth.data), + }; + + // Create a Postman request object using cleanedAuth + const cleanedPostmanRequest = buildPostmanRequest(postman, { + queryParams, + pathParams, + cookieParams, + contentType, + accept, + headerParams, + body, + server, + auth: cleanedAuth, + }); // User-defined languages array // Can override languageSet, change order of langs, override options and variants @@ -105,21 +130,10 @@ function CodeSnippets({ postman, codeSamples }: Props) { } if (language && !!language.options) { - const postmanRequest = buildPostmanRequest(postman, { - queryParams, - pathParams, - cookieParams, - contentType, - accept, - headerParams, - body, - server, - auth, - }); codegen.convert( language.language, language.variant, - postmanRequest, + cleanedPostmanRequest, language.options, (error: any, snippet: string) => { if (error) { @@ -137,22 +151,10 @@ function CodeSnippets({ postman, codeSamples }: Props) { // This allows users to define only the minimal properties necessary in languageTabs // User-defined properties should override languageSet properties const mergedLanguage = { ...langSource[0], ...language }; - const postmanRequest = buildPostmanRequest(postman, { - queryParams, - pathParams, - cookieParams, - contentType, - accept, - headerParams, - body, - server, - auth, - }); - codegen.convert( mergedLanguage.language, mergedLanguage.variant, - postmanRequest, + cleanedPostmanRequest, mergedLanguage.options, (error: any, snippet: string) => { if (error) { @@ -175,27 +177,16 @@ function CodeSnippets({ postman, codeSamples }: Props) { postman, queryParams, server, - auth, + cleanedPostmanRequest, mergedLangs, ]); - // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set + // no dependencies was intentionally set for this particular hook. it's safe as long as if conditions are set useEffect(function onSelectedVariantUpdate() { if (selectedVariant && selectedVariant !== language?.variant) { - const postmanRequest = buildPostmanRequest(postman, { - queryParams, - pathParams, - cookieParams, - contentType, - accept, - headerParams, - body, - server, - auth, - }); codegen.convert( language.language, selectedVariant, - postmanRequest, + cleanedPostmanRequest, language.options, (error: any, snippet: string) => { if (error) { @@ -207,7 +198,7 @@ function CodeSnippets({ postman, codeSamples }: Props) { } }); - // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set + // no dependencies was intentionally set for this particular hook. it's safe as long as if conditions are set // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(function onSelectedSampleUpdate() { if ( From 97d0d8b84bf27ab54508526872b28c7bedfd795d Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Mon, 16 Dec 2024 15:22:17 -0600 Subject: [PATCH 2/2] use credential name or type as placeholder --- .../src/theme/ApiExplorer/CodeSnippets/index.tsx | 14 +++++++++----- .../src/theme/ApiExplorer/buildPostmanRequest.ts | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx index 11bbd05df..c3c9e9b2c 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/CodeSnippets/index.tsx @@ -12,6 +12,7 @@ import ApiCodeBlock from "@theme/ApiExplorer/ApiCodeBlock"; import buildPostmanRequest from "@theme/ApiExplorer/buildPostmanRequest"; import CodeTabs from "@theme/ApiExplorer/CodeTabs"; import { useTypedSelector } from "@theme/ApiItem/hooks"; +import cloneDeep from "lodash/cloneDeep"; import codegen from "postman-code-generators"; import sdk from "postman-collection"; @@ -52,14 +53,17 @@ function CodeSnippets({ postman, codeSamples }: Props) { const headerParams = useTypedSelector((state: any) => state.params.header); const auth = useTypedSelector((state: any) => state.auth); - const clonedAuth = JSON.parse(JSON.stringify(auth)); + const clonedAuth = cloneDeep(auth); + let placeholder: string; - function scrubCredentials(obj: any) { + function cleanCredentials(obj: any) { for (const key in obj) { if (typeof obj[key] === "object" && obj[key] !== null) { - obj[key] = scrubCredentials(obj[key]); + // use name as placeholder if exists + placeholder = clonedAuth?.options?.[key]?.[0]?.name; + obj[key] = cleanCredentials(obj[key]); } else { - obj[key] = `<${key}>`; + obj[key] = `<${placeholder ?? key}>`; } } @@ -69,7 +73,7 @@ function CodeSnippets({ postman, codeSamples }: Props) { // scrub credentials from code snippets const cleanedAuth = { ...clonedAuth, - data: scrubCredentials(clonedAuth.data), + data: cleanCredentials(clonedAuth.data), }; // Create a Postman request object using cleanedAuth diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/buildPostmanRequest.ts b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/buildPostmanRequest.ts index 465f90b15..c40e5d9e3 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/buildPostmanRequest.ts +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/buildPostmanRequest.ts @@ -298,7 +298,7 @@ function buildPostmanRequest( if (apiKey === undefined) { otherHeaders.push({ key: a.name, - value: "", + value: `<${a.name ?? a.type}>`, }); continue; }