Skip to content

Add maskCredentials as a pluginOption #1212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions demo/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ const config: Config = {
docsPluginId: "classic",
config: {
petstore_versioned: {
maskCredentials: false,
specPath: "examples/petstore.yaml",
outputDir: "docs/petstore_versioned", // No trailing slash
sidebarOptions: {
Expand Down Expand Up @@ -327,10 +328,12 @@ const config: Config = {
},
} satisfies OpenApiPlugin.Options,
burgers: {
maskCredentials: true,
specPath: "examples/food/burgers/openapi.yaml",
outputDir: "docs/food/burgers",
} satisfies OpenApiPlugin.Options,
yogurt: {
maskCredentials: false,
specPath: "examples/food/yogurtstore/openapi.yaml",
outputDir: "docs/food/yogurtstore",
} satisfies OpenApiPlugin.Options,
Expand Down
3 changes: 3 additions & 0 deletions demo/templates/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ hide_send_button: true
{{#frontMatter.show_extensions}}
show_extensions: true
{{/frontMatter.show_extensions}}
{{#frontMatter.mask_credentials_disabled}}
mask_credentials: false
{{/frontMatter.mask_credentials_disabled}}
---

This is a Custom Api Page Generated by docusaurus-openapi-docs using `api.mustache` template
Expand Down
40 changes: 21 additions & 19 deletions packages/docusaurus-plugin-openapi-docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ import type * as OpenApiPlugin from "docusaurus-plugin-openapi-docs";
petstore: {
specPath: "examples/petstore.yaml",
outputDir: "docs/petstore",
maskCredentials: false, // Disable credential masking in code snippets
sidebarOptions: {
groupPathsBy: "tag",
},
Expand Down Expand Up @@ -155,25 +156,26 @@ The `docusaurus-plugin-openapi-docs` plugin can be configured with the following

`config` can be configured with the following options:

| Name | Type | Default | Description |
| -------------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| `specPath` | `string` | `null` | Designated URL or path to the source of an OpenAPI specification file or directory of multiple OpenAPI specification files. |
| `outputDir` | `string` | `null` | Desired output path for generated MDX and sidebar files. |
| `proxy` | `string` | `null` | _Optional:_ Proxy URL to prepend to base URL when performing API requests from browser. |
| `template` | `string` | `null` | _Optional:_ Customize MDX content with a desired template. |
| `infoTemplate` | `string` | `null` | _Optional:_ Customize MDX content for **info** pages only. |
| `tagTemplate` | `string` | `null` | _Optional:_ Customize MDX content for **tag** pages only. |
| `schemaTemplate` | `string` | `null` | _Optional:_ Customize MDX content for **schema** pages only. |
| `downloadUrl` | `string` | `null` | _Optional:_ Designated URL for downloading OpenAPI specification. (requires `info` section/doc) |
| `hideSendButton` | `boolean` | `null` | _Optional:_ If set to `true`, hides the “Send API Request” button in the API demo panel. |
| `showExtensions` | `boolean` | `null` | _Optional:_ If set to `true`, renders operation‑level vendor‑extensions in descriptions. |
| `sidebarOptions` | `object` | `null` | _Optional:_ Set of options for sidebar configuration. See below for a list of supported options. |
| `version` | `string` | `null` | _Optional:_ Version assigned to a single or micro‑spec API specified in `specPath`. |
| `label` | `string` | `null` | _Optional:_ Version label used when generating the version‑selector dropdown menu. |
| `baseUrl` | `string` | `null` | _Optional:_ Base URL for versioned docs in the version‑selector dropdown. |
| `versions` | `object` | `null` | _Optional:_ Options for versioning configuration. See below for a list of supported options. |
| `markdownGenerators` | `object` | `null` | _Optional:_ Customize MDX content via generator functions. See below for a list of supported options. |
| `showSchemas` | `boolean` | `null` | _Optional:_ If set to `true`, generates standalone schema pages and adds them to the sidebar. |
| Name | Type | Default | Description |
| -------------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `specPath` | `string` | `null` | Designated URL or path to the source of an OpenAPI specification file or directory of multiple OpenAPI specification files. |
| `outputDir` | `string` | `null` | Desired output path for generated MDX and sidebar files. |
| `proxy` | `string` | `null` | _Optional:_ Proxy URL to prepend to base URL when performing API requests from browser. |
| `template` | `string` | `null` | _Optional:_ Customize MDX content with a desired template. |
| `infoTemplate` | `string` | `null` | _Optional:_ Customize MDX content for **info** pages only. |
| `tagTemplate` | `string` | `null` | _Optional:_ Customize MDX content for **tag** pages only. |
| `schemaTemplate` | `string` | `null` | _Optional:_ Customize MDX content for **schema** pages only. |
| `downloadUrl` | `string` | `null` | _Optional:_ Designated URL for downloading OpenAPI specification. (requires `info` section/doc) |
| `hideSendButton` | `boolean` | `null` | _Optional:_ If set to `true`, hides the “Send API Request” button in the API demo panel. |
| `showExtensions` | `boolean` | `null` | _Optional:_ If set to `true`, renders operation‑level vendor‑extensions in descriptions. |
| `maskCredentials` | `boolean` | `true` | _Optional:_ If set to `false`, disables credential masking in generated code snippets. By default, credentials are masked for security. |
| `sidebarOptions` | `object` | `null` | _Optional:_ Set of options for sidebar configuration. See below for a list of supported options. |
| `version` | `string` | `null` | _Optional:_ Version assigned to a single or micro‑spec API specified in `specPath`. |
| `label` | `string` | `null` | _Optional:_ Version label used when generating the version‑selector dropdown menu. |
| `baseUrl` | `string` | `null` | _Optional:_ Base URL for versioned docs in the version‑selector dropdown. |
| `versions` | `object` | `null` | _Optional:_ Options for versioning configuration. See below for a list of supported options. |
| `markdownGenerators` | `object` | `null` | _Optional:_ Customize MDX content via generator functions. See below for a list of supported options. |
| `showSchemas` | `boolean` | `null` | _Optional:_ If set to `true`, generates standalone schema pages and adds them to the sidebar. |

### sidebarOptions

Expand Down
3 changes: 3 additions & 0 deletions packages/docusaurus-plugin-openapi-docs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ hide_send_button: true
{{#frontMatter.show_extensions}}
show_extensions: true
{{/frontMatter.show_extensions}}
{{#frontMatter.mask_credentials_disabled}}
mask_credentials: false
{{/frontMatter.mask_credentials_disabled}}
---

{{{markdown}}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function jsonToCollection(data: OpenApiObject): Promise<Collection> {
if (!schemaPack.validationResult?.result) {
return reject(schemaPack.validationResult?.reason);
}

schemaPack.convert((_err: any, conversionResult: any) => {
if (_err || !conversionResult.result) {
return reject(_err || conversionResult.reason);
Expand Down Expand Up @@ -256,6 +256,9 @@ function createItems(
...(options?.showExtensions && {
show_extensions: options.showExtensions,
}),
...(options?.maskCredentials === false && {
mask_credentials_disabled: true,
}),
},
api: {
...defaults,
Expand Down Expand Up @@ -409,6 +412,9 @@ function createItems(
...(options?.showExtensions && {
show_extensions: options.showExtensions,
}),
...(options?.maskCredentials === false && {
mask_credentials_disabled: true,
}),
},
api: {
...defaults,
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-plugin-openapi-docs/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const OptionsSchema = Joi.object({
markdownGenerators: markdownGenerators,
showSchemas: Joi.boolean(),
disableCompression: Joi.boolean(),
maskCredentials: Joi.boolean(),
version: Joi.string().when("versions", {
is: Joi.exist(),
then: Joi.required(),
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-plugin-openapi-docs/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export interface APIOptions {
markdownGenerators?: MarkdownGenerator;
showSchemas?: boolean;
disableCompression?: boolean;
maskCredentials?: boolean;
}

export interface MarkdownGenerator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const languageSet: Language[] = generateLanguageSet();
export interface Props {
postman: sdk.Request;
codeSamples: CodeSample[];
maskCredentials?: boolean;
}

function CodeTab({ children, hidden, className }: any): React.JSX.Element {
Expand All @@ -39,7 +40,11 @@ function CodeTab({ children, hidden, className }: any): React.JSX.Element {
);
}

function CodeSnippets({ postman, codeSamples }: Props) {
function CodeSnippets({
postman,
codeSamples,
maskCredentials: propMaskCredentials,
}: Props) {
const { siteConfig } = useDocusaurusContext();

const contentType = useTypedSelector((state: any) => state.contentType.value);
Expand All @@ -53,33 +58,42 @@ function CodeSnippets({ postman, codeSamples }: Props) {
const headerParams = useTypedSelector((state: any) => state.params.header);

const auth = useTypedSelector((state: any) => state.auth);
const clonedAuth = cloneDeep(auth);
let placeholder: string;

function cleanCredentials(obj: any) {
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
// use name as placeholder if exists
const comboAuthId = Object.keys(obj).join(" and ");
const authOptions =
clonedAuth?.options?.[key] ?? clonedAuth?.options?.[comboAuthId];
placeholder = authOptions?.[0]?.name;
obj[key] = cleanCredentials(obj[key]);
} else {
obj[key] = `<${placeholder ?? key}>`;
}
}
// Check if credential masking is enabled (default: true)
const maskCredentials = propMaskCredentials ?? true;

return obj;
}
// Clone Auth if maskCredentials is not false
const cleanedAuth = maskCredentials
? (() => {
const clonedAuth = cloneDeep(auth);
let placeholder: string;

function cleanCredentials(obj: any) {
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
// use name as placeholder if exists
const comboAuthId = Object.keys(obj).join(" and ");
const authOptions =
clonedAuth?.options?.[key] ??
clonedAuth?.options?.[comboAuthId];
placeholder = authOptions?.[0]?.name;
obj[key] = cleanCredentials(obj[key]);
} else {
obj[key] = `<${placeholder ?? key}>`;
}
}

return obj;
}

// scrub credentials from code snippets
const cleanedAuth = {
...clonedAuth,
data: cleanCredentials(clonedAuth.data),
};
return {
...clonedAuth,
data: cleanCredentials(clonedAuth.data),
};
})()
: auth;

// Create a Postman request object using cleanedAuth
// Create a Postman request object using cleanedAuth or original auth
const cleanedPostmanRequest = buildPostmanRequest(postman, {
queryParams,
pathParams,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import React from "react";

import { useDoc } from "@docusaurus/plugin-content-docs/client";
import CodeSnippets from "@theme/ApiExplorer/CodeSnippets";
import Request from "@theme/ApiExplorer/Request";
import Response from "@theme/ApiExplorer/Response";
Expand All @@ -21,6 +22,9 @@ function ApiExplorer({
item: NonNullable<ApiItem>;
infoPath: string;
}) {
const metadata = useDoc();
const { mask_credentials } = metadata.frontMatter;

const postman = new sdk.Request(
item.postman
? sdk.Request.isRequest(item.postman)
Expand All @@ -36,6 +40,7 @@ function ApiExplorer({
<CodeSnippets
postman={postman}
codeSamples={(item as any)["x-codeSamples"] ?? []}
maskCredentials={mask_credentials}
/>
)}
<Request item={item} />
Expand Down