docusaurus-theme-openapi-docs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/babel.config.js +35 -0
- package/lib/index.js +48 -0
- package/lib/markdown/createDescription.js +20 -0
- package/lib/markdown/schema.js +121 -0
- package/lib/markdown/utils.js +45 -0
- package/lib/theme/ApiDemoPanel/Accept/index.js +41 -0
- package/lib/theme/ApiDemoPanel/Accept/slice.js +32 -0
- package/lib/theme/ApiDemoPanel/Authorization/auth-types.js +32 -0
- package/lib/theme/ApiDemoPanel/Authorization/index.js +174 -0
- package/lib/theme/ApiDemoPanel/Authorization/slice.js +137 -0
- package/lib/theme/ApiDemoPanel/Body/index.js +185 -0
- package/lib/theme/ApiDemoPanel/Body/slice.js +105 -0
- package/lib/theme/ApiDemoPanel/ContentType/index.js +41 -0
- package/lib/theme/ApiDemoPanel/ContentType/slice.js +32 -0
- package/lib/theme/ApiDemoPanel/Curl/index.js +236 -0
- package/lib/theme/ApiDemoPanel/Curl/styles.module.css +84 -0
- package/lib/theme/ApiDemoPanel/Execute/index.js +85 -0
- package/lib/theme/ApiDemoPanel/Execute/makeRequest.js +202 -0
- package/lib/theme/ApiDemoPanel/FloatingButton/index.js +32 -0
- package/lib/theme/ApiDemoPanel/FloatingButton/styles.module.css +26 -0
- package/lib/theme/ApiDemoPanel/FormFileUpload/index.js +97 -0
- package/lib/theme/ApiDemoPanel/FormFileUpload/styles.module.css +75 -0
- package/lib/theme/ApiDemoPanel/FormItem/index.js +35 -0
- package/lib/theme/ApiDemoPanel/FormItem/styles.module.css +7 -0
- package/lib/theme/ApiDemoPanel/FormMultiSelect/index.js +52 -0
- package/lib/theme/ApiDemoPanel/FormMultiSelect/styles.module.css +38 -0
- package/lib/theme/ApiDemoPanel/FormSelect/index.js +39 -0
- package/lib/theme/ApiDemoPanel/FormSelect/styles.module.css +51 -0
- package/lib/theme/ApiDemoPanel/FormTextInput/index.js +30 -0
- package/lib/theme/ApiDemoPanel/FormTextInput/styles.module.css +21 -0
- package/lib/theme/ApiDemoPanel/MethodEndpoint/index.js +60 -0
- package/lib/theme/ApiDemoPanel/ParamOptions/index.js +248 -0
- package/lib/theme/ApiDemoPanel/ParamOptions/slice.js +35 -0
- package/lib/theme/ApiDemoPanel/ParamOptions/styles.module.css +180 -0
- package/lib/theme/ApiDemoPanel/Response/index.js +75 -0
- package/lib/theme/ApiDemoPanel/Response/slice.js +37 -0
- package/lib/theme/ApiDemoPanel/SecuritySchemes/index.js +51 -0
- package/lib/theme/ApiDemoPanel/Server/index.js +109 -0
- package/lib/theme/ApiDemoPanel/Server/slice.js +41 -0
- package/lib/theme/ApiDemoPanel/Server/styles.module.css +61 -0
- package/lib/theme/ApiDemoPanel/VSCode/index.js +252 -0
- package/lib/theme/ApiDemoPanel/VSCode/styles.module.css +19 -0
- package/lib/theme/ApiDemoPanel/buildPostmanRequest.js +329 -0
- package/lib/theme/ApiDemoPanel/hooks.js +20 -0
- package/lib/theme/ApiDemoPanel/index.js +134 -0
- package/lib/theme/ApiDemoPanel/persistanceMiddleware.js +44 -0
- package/lib/theme/ApiDemoPanel/postman-collection.d.ts +10 -0
- package/lib/theme/ApiDemoPanel/storage-utils.js +47 -0
- package/lib/theme/ApiDemoPanel/store.js +48 -0
- package/lib/theme/ApiDemoPanel/styles.module.css +44 -0
- package/lib/theme/ApiItem/index.js +160 -0
- package/lib/theme/ApiItem/styles.module.css +109 -0
- package/lib/theme/ParamsItem/index.js +68 -0
- package/lib/theme/ParamsItem/styles.module.css +24 -0
- package/lib/theme/SchemaItem/index.js +58 -0
- package/lib/theme/SchemaItem/styles.module.css +24 -0
- package/lib/theme/Tabs/index.js +258 -0
- package/lib/theme/Tabs/styles.module.css +118 -0
- package/lib/theme-classic.d.ts +8 -0
- package/lib/theme-openapi.d.ts +48 -0
- package/lib/theme-translations.d.ts +9 -0
- package/lib/types.js +1 -0
- package/lib-next/index.js +38 -0
- package/lib-next/markdown/createDescription.js +13 -0
- package/lib-next/markdown/schema.js +115 -0
- package/lib-next/markdown/utils.js +31 -0
- package/lib-next/theme/ApiDemoPanel/Accept/index.js +33 -0
- package/lib-next/theme/ApiDemoPanel/Accept/slice.js +19 -0
- package/lib-next/theme/ApiDemoPanel/Authorization/auth-types.js +22 -0
- package/lib-next/theme/ApiDemoPanel/Authorization/index.js +203 -0
- package/lib-next/theme/ApiDemoPanel/Authorization/slice.js +101 -0
- package/lib-next/theme/ApiDemoPanel/Body/index.js +210 -0
- package/lib-next/theme/ApiDemoPanel/Body/slice.js +89 -0
- package/lib-next/theme/ApiDemoPanel/ContentType/index.js +33 -0
- package/lib-next/theme/ApiDemoPanel/ContentType/slice.js +19 -0
- package/lib-next/theme/ApiDemoPanel/Curl/index.js +264 -0
- package/lib-next/theme/ApiDemoPanel/Curl/styles.module.css +84 -0
- package/lib-next/theme/ApiDemoPanel/Execute/index.js +74 -0
- package/lib-next/theme/ApiDemoPanel/Execute/makeRequest.js +183 -0
- package/lib-next/theme/ApiDemoPanel/FloatingButton/index.js +19 -0
- package/lib-next/theme/ApiDemoPanel/FloatingButton/styles.module.css +26 -0
- package/lib-next/theme/ApiDemoPanel/FormFileUpload/index.js +113 -0
- package/lib-next/theme/ApiDemoPanel/FormFileUpload/styles.module.css +75 -0
- package/lib-next/theme/ApiDemoPanel/FormItem/index.js +29 -0
- package/lib-next/theme/ApiDemoPanel/FormItem/styles.module.css +7 -0
- package/lib-next/theme/ApiDemoPanel/FormMultiSelect/index.js +49 -0
- package/lib-next/theme/ApiDemoPanel/FormMultiSelect/styles.module.css +38 -0
- package/lib-next/theme/ApiDemoPanel/FormSelect/index.js +28 -0
- package/lib-next/theme/ApiDemoPanel/FormSelect/styles.module.css +51 -0
- package/lib-next/theme/ApiDemoPanel/FormTextInput/index.js +23 -0
- package/lib-next/theme/ApiDemoPanel/FormTextInput/styles.module.css +21 -0
- package/lib-next/theme/ApiDemoPanel/MethodEndpoint/index.js +53 -0
- package/lib-next/theme/ApiDemoPanel/ParamOptions/index.js +284 -0
- package/lib-next/theme/ApiDemoPanel/ParamOptions/slice.js +22 -0
- package/lib-next/theme/ApiDemoPanel/ParamOptions/styles.module.css +180 -0
- package/lib-next/theme/ApiDemoPanel/Response/index.js +65 -0
- package/lib-next/theme/ApiDemoPanel/Response/slice.js +22 -0
- package/lib-next/theme/ApiDemoPanel/SecuritySchemes/index.js +48 -0
- package/lib-next/theme/ApiDemoPanel/Server/index.js +114 -0
- package/lib-next/theme/ApiDemoPanel/Server/slice.js +25 -0
- package/lib-next/theme/ApiDemoPanel/Server/styles.module.css +61 -0
- package/lib-next/theme/ApiDemoPanel/VSCode/index.js +265 -0
- package/lib-next/theme/ApiDemoPanel/VSCode/styles.module.css +19 -0
- package/lib-next/theme/ApiDemoPanel/buildPostmanRequest.js +310 -0
- package/lib-next/theme/ApiDemoPanel/hooks.js +9 -0
- package/lib-next/theme/ApiDemoPanel/index.js +110 -0
- package/lib-next/theme/ApiDemoPanel/persistanceMiddleware.js +38 -0
- package/lib-next/theme/ApiDemoPanel/postman-collection.d.ts +10 -0
- package/lib-next/theme/ApiDemoPanel/storage-utils.js +35 -0
- package/lib-next/theme/ApiDemoPanel/store.js +30 -0
- package/lib-next/theme/ApiDemoPanel/styles.module.css +44 -0
- package/lib-next/theme/ApiItem/index.js +171 -0
- package/lib-next/theme/ApiItem/styles.module.css +109 -0
- package/lib-next/theme/ParamsItem/index.js +68 -0
- package/lib-next/theme/ParamsItem/styles.module.css +24 -0
- package/lib-next/theme/SchemaItem/index.js +58 -0
- package/lib-next/theme/SchemaItem/styles.module.css +24 -0
- package/lib-next/theme/Tabs/index.js +258 -0
- package/lib-next/theme/Tabs/styles.module.css +118 -0
- package/lib-next/theme-classic.d.ts +8 -0
- package/lib-next/theme-openapi.d.ts +48 -0
- package/lib-next/theme-translations.d.ts +9 -0
- package/lib-next/types.js +1 -0
- package/package.json +68 -0
- package/src/index.ts +42 -0
- package/src/markdown/createDescription.ts +13 -0
- package/src/markdown/schema.ts +115 -0
- package/src/markdown/utils.ts +39 -0
- package/src/theme/ApiDemoPanel/Accept/index.tsx +35 -0
- package/src/theme/ApiDemoPanel/Accept/slice.ts +29 -0
- package/src/theme/ApiDemoPanel/Authorization/auth-types.ts +26 -0
- package/src/theme/ApiDemoPanel/Authorization/index.tsx +211 -0
- package/src/theme/ApiDemoPanel/Authorization/slice.ts +145 -0
- package/src/theme/ApiDemoPanel/Body/index.tsx +218 -0
- package/src/theme/ApiDemoPanel/Body/slice.ts +133 -0
- package/src/theme/ApiDemoPanel/ContentType/index.tsx +35 -0
- package/src/theme/ApiDemoPanel/ContentType/slice.ts +29 -0
- package/src/theme/ApiDemoPanel/Curl/index.tsx +280 -0
- package/src/theme/ApiDemoPanel/Curl/styles.module.css +84 -0
- package/src/theme/ApiDemoPanel/Execute/index.tsx +88 -0
- package/src/theme/ApiDemoPanel/Execute/makeRequest.ts +184 -0
- package/src/theme/ApiDemoPanel/FloatingButton/index.tsx +27 -0
- package/src/theme/ApiDemoPanel/FloatingButton/styles.module.css +26 -0
- package/src/theme/ApiDemoPanel/FormFileUpload/index.tsx +116 -0
- package/src/theme/ApiDemoPanel/FormFileUpload/styles.module.css +75 -0
- package/src/theme/ApiDemoPanel/FormItem/index.tsx +28 -0
- package/src/theme/ApiDemoPanel/FormItem/styles.module.css +7 -0
- package/src/theme/ApiDemoPanel/FormMultiSelect/index.tsx +54 -0
- package/src/theme/ApiDemoPanel/FormMultiSelect/styles.module.css +38 -0
- package/src/theme/ApiDemoPanel/FormSelect/index.tsx +36 -0
- package/src/theme/ApiDemoPanel/FormSelect/styles.module.css +51 -0
- package/src/theme/ApiDemoPanel/FormTextInput/index.tsx +32 -0
- package/src/theme/ApiDemoPanel/FormTextInput/styles.module.css +21 -0
- package/src/theme/ApiDemoPanel/MethodEndpoint/index.tsx +55 -0
- package/src/theme/ApiDemoPanel/ParamOptions/index.tsx +316 -0
- package/src/theme/ApiDemoPanel/ParamOptions/slice.ts +37 -0
- package/src/theme/ApiDemoPanel/ParamOptions/styles.module.css +180 -0
- package/src/theme/ApiDemoPanel/Response/index.tsx +66 -0
- package/src/theme/ApiDemoPanel/Response/slice.ts +31 -0
- package/src/theme/ApiDemoPanel/SecuritySchemes/index.tsx +49 -0
- package/src/theme/ApiDemoPanel/Server/index.tsx +103 -0
- package/src/theme/ApiDemoPanel/Server/slice.ts +40 -0
- package/src/theme/ApiDemoPanel/Server/styles.module.css +61 -0
- package/src/theme/ApiDemoPanel/VSCode/index.tsx +205 -0
- package/src/theme/ApiDemoPanel/VSCode/styles.module.css +19 -0
- package/src/theme/ApiDemoPanel/buildPostmanRequest.ts +307 -0
- package/src/theme/ApiDemoPanel/hooks.ts +13 -0
- package/src/theme/ApiDemoPanel/index.tsx +118 -0
- package/src/theme/ApiDemoPanel/persistanceMiddleware.ts +46 -0
- package/src/theme/ApiDemoPanel/postman-collection.d.ts +10 -0
- package/src/theme/ApiDemoPanel/storage-utils.ts +39 -0
- package/src/theme/ApiDemoPanel/store.ts +41 -0
- package/src/theme/ApiDemoPanel/styles.module.css +44 -0
- package/src/theme/ApiItem/index.tsx +171 -0
- package/src/theme/ApiItem/styles.module.css +109 -0
- package/src/theme/ParamsItem/index.js +68 -0
- package/src/theme/ParamsItem/styles.module.css +24 -0
- package/src/theme/SchemaItem/index.js +58 -0
- package/src/theme/SchemaItem/styles.module.css +24 -0
- package/src/theme/Tabs/index.js +258 -0
- package/src/theme/Tabs/styles.module.css +118 -0
- package/src/theme-classic.d.ts +8 -0
- package/src/theme-openapi.d.ts +48 -0
- package/src/theme-translations.d.ts +9 -0
- package/src/types.ts +70 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
export type Children = string | undefined | (string | undefined)[];
|
|
9
|
+
|
|
10
|
+
export type Props = Record<string, any> & { children?: Children };
|
|
11
|
+
|
|
12
|
+
export function create(tag: string, props: Props): string {
|
|
13
|
+
const { children, ...rest } = props;
|
|
14
|
+
|
|
15
|
+
let propString = "";
|
|
16
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
17
|
+
propString += ` ${key}={${JSON.stringify(value)}}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return `<${tag}${propString}>${render(children)}</${tag}>`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function guard<T>(
|
|
24
|
+
value: T | undefined,
|
|
25
|
+
cb: (value: T) => Children
|
|
26
|
+
): string {
|
|
27
|
+
if (value) {
|
|
28
|
+
const children = cb(value);
|
|
29
|
+
return render(children);
|
|
30
|
+
}
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function render(children: Children): string {
|
|
35
|
+
if (Array.isArray(children)) {
|
|
36
|
+
return children.filter((c) => c !== undefined).join("");
|
|
37
|
+
}
|
|
38
|
+
return children ?? "";
|
|
39
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import React from "react";
|
|
9
|
+
|
|
10
|
+
import { useTypedDispatch, useTypedSelector } from "../hooks";
|
|
11
|
+
import FormItem from "./../FormItem";
|
|
12
|
+
import FormSelect from "./../FormSelect";
|
|
13
|
+
import { setAccept } from "./slice";
|
|
14
|
+
|
|
15
|
+
function Accept() {
|
|
16
|
+
const value = useTypedSelector((state) => state.accept.value);
|
|
17
|
+
const options = useTypedSelector((state) => state.accept.options);
|
|
18
|
+
const dispatch = useTypedDispatch();
|
|
19
|
+
|
|
20
|
+
if (options.length <= 1) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<FormItem label="Accept">
|
|
26
|
+
<FormSelect
|
|
27
|
+
value={value}
|
|
28
|
+
options={options}
|
|
29
|
+
onChange={(e) => dispatch(setAccept(e.target.value))}
|
|
30
|
+
/>
|
|
31
|
+
</FormItem>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default Accept;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|
9
|
+
|
|
10
|
+
export interface State {
|
|
11
|
+
value: string;
|
|
12
|
+
options: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const initialState: State = {} as any;
|
|
16
|
+
|
|
17
|
+
export const slice = createSlice({
|
|
18
|
+
name: "accept",
|
|
19
|
+
initialState,
|
|
20
|
+
reducers: {
|
|
21
|
+
setAccept: (state, action: PayloadAction<string>) => {
|
|
22
|
+
state.value = action.payload;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const { setAccept } = slice.actions;
|
|
28
|
+
|
|
29
|
+
export default slice.reducer;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
export function getAuthDataKeys(security: { [key: string]: any }) {
|
|
9
|
+
// Bearer Auth
|
|
10
|
+
if (security.type === "http" && security.scheme === "bearer") {
|
|
11
|
+
return ["token"];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Basic Auth
|
|
15
|
+
if (security.type === "http" && security.scheme === "basic") {
|
|
16
|
+
return ["username", "password"];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// API Auth
|
|
20
|
+
if (security.type === "apiKey") {
|
|
21
|
+
return ["apiKey"];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// none
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import React, { useState } from "react";
|
|
9
|
+
|
|
10
|
+
import clsx from "clsx";
|
|
11
|
+
|
|
12
|
+
import FormItem from "../FormItem";
|
|
13
|
+
import FormSelect from "../FormSelect";
|
|
14
|
+
import FormTextInput from "../FormTextInput";
|
|
15
|
+
import { useTypedDispatch, useTypedSelector } from "../hooks";
|
|
16
|
+
import styles from "../styles.module.css";
|
|
17
|
+
import { AuthState, Scheme, setAuthData, setSelectedAuth } from "./slice";
|
|
18
|
+
|
|
19
|
+
type Props = {
|
|
20
|
+
mode: "locked" | "unlocked";
|
|
21
|
+
} & JSX.IntrinsicElements["button"];
|
|
22
|
+
|
|
23
|
+
function LockButton({ mode, children, style, ...rest }: Props) {
|
|
24
|
+
return (
|
|
25
|
+
<button
|
|
26
|
+
className={clsx("button", "button--primary", {
|
|
27
|
+
"button--outline": mode !== "locked",
|
|
28
|
+
})}
|
|
29
|
+
style={{
|
|
30
|
+
marginLeft: "auto",
|
|
31
|
+
display: "flex",
|
|
32
|
+
alignItems: "center",
|
|
33
|
+
marginBottom: "var(--ifm-spacing-vertical)",
|
|
34
|
+
...style,
|
|
35
|
+
}}
|
|
36
|
+
{...rest}
|
|
37
|
+
>
|
|
38
|
+
<span>{children}</span>
|
|
39
|
+
|
|
40
|
+
<svg
|
|
41
|
+
style={{
|
|
42
|
+
marginLeft: "12px",
|
|
43
|
+
width: "18px",
|
|
44
|
+
height: "18px",
|
|
45
|
+
fill: "currentColor",
|
|
46
|
+
}}
|
|
47
|
+
viewBox="0 0 20 20"
|
|
48
|
+
id={mode}
|
|
49
|
+
>
|
|
50
|
+
{mode === "locked" ? (
|
|
51
|
+
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"></path>
|
|
52
|
+
) : (
|
|
53
|
+
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
|
54
|
+
)}
|
|
55
|
+
</svg>
|
|
56
|
+
</button>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function validateData(selectedAuth: Scheme[], data: AuthState["data"]) {
|
|
61
|
+
for (const scheme of selectedAuth) {
|
|
62
|
+
if (data[scheme.key] === undefined) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const hasMissingKeys = Object.values(data[scheme.key]).includes(undefined);
|
|
66
|
+
if (hasMissingKeys) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function Authorization() {
|
|
74
|
+
const [editing, setEditing] = useState(false);
|
|
75
|
+
|
|
76
|
+
const data = useTypedSelector((state) => state.auth.data);
|
|
77
|
+
const options = useTypedSelector((state) => state.auth.options);
|
|
78
|
+
const selected = useTypedSelector((state) => state.auth.selected);
|
|
79
|
+
|
|
80
|
+
const dispatch = useTypedDispatch();
|
|
81
|
+
|
|
82
|
+
if (selected === undefined) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const selectedAuth = options[selected];
|
|
87
|
+
|
|
88
|
+
const authenticated = validateData(selectedAuth, data);
|
|
89
|
+
|
|
90
|
+
const optionKeys = Object.keys(options);
|
|
91
|
+
|
|
92
|
+
if (editing) {
|
|
93
|
+
return (
|
|
94
|
+
<div className={styles.optionsPanel}>
|
|
95
|
+
{optionKeys.length > 1 && (
|
|
96
|
+
<FormItem label="Security Scheme">
|
|
97
|
+
<FormSelect
|
|
98
|
+
options={optionKeys}
|
|
99
|
+
value={selected}
|
|
100
|
+
onChange={(e) => {
|
|
101
|
+
dispatch(setSelectedAuth(e.target.value));
|
|
102
|
+
}}
|
|
103
|
+
/>
|
|
104
|
+
</FormItem>
|
|
105
|
+
)}
|
|
106
|
+
{selectedAuth.map((a) => {
|
|
107
|
+
if (a.type === "http" && a.scheme === "bearer") {
|
|
108
|
+
return (
|
|
109
|
+
<FormItem label="Bearer Token" key={selected + "-bearer"}>
|
|
110
|
+
<FormTextInput
|
|
111
|
+
placeholder="Bearer Token"
|
|
112
|
+
value={data[a.key].token ?? ""}
|
|
113
|
+
onChange={(e) => {
|
|
114
|
+
const value = e.target.value.trim();
|
|
115
|
+
dispatch(
|
|
116
|
+
setAuthData({
|
|
117
|
+
scheme: a.key,
|
|
118
|
+
key: "token",
|
|
119
|
+
value: value ? value : undefined,
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
</FormItem>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (a.type === "http" && a.scheme === "basic") {
|
|
129
|
+
return (
|
|
130
|
+
<React.Fragment key={selected + "-basic"}>
|
|
131
|
+
<FormItem label="Username">
|
|
132
|
+
<FormTextInput
|
|
133
|
+
placeholder="Username"
|
|
134
|
+
value={data[a.key].username ?? ""}
|
|
135
|
+
onChange={(e) => {
|
|
136
|
+
const value = e.target.value.trim();
|
|
137
|
+
dispatch(
|
|
138
|
+
setAuthData({
|
|
139
|
+
scheme: a.key,
|
|
140
|
+
key: "username",
|
|
141
|
+
value: value ? value : undefined,
|
|
142
|
+
})
|
|
143
|
+
);
|
|
144
|
+
}}
|
|
145
|
+
/>
|
|
146
|
+
</FormItem>
|
|
147
|
+
<FormItem label="Password">
|
|
148
|
+
<FormTextInput
|
|
149
|
+
placeholder="Password"
|
|
150
|
+
password
|
|
151
|
+
value={data[a.key].password ?? ""}
|
|
152
|
+
onChange={(e) => {
|
|
153
|
+
const value = e.target.value.trim();
|
|
154
|
+
dispatch(
|
|
155
|
+
setAuthData({
|
|
156
|
+
scheme: a.key,
|
|
157
|
+
key: "password",
|
|
158
|
+
value: value ? value : undefined,
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
}}
|
|
162
|
+
/>
|
|
163
|
+
</FormItem>
|
|
164
|
+
</React.Fragment>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return null;
|
|
169
|
+
})}
|
|
170
|
+
<LockButton
|
|
171
|
+
mode="unlocked"
|
|
172
|
+
style={{
|
|
173
|
+
marginTop: "var(--ifm-spacing-vertical)",
|
|
174
|
+
marginBottom: 0,
|
|
175
|
+
}}
|
|
176
|
+
onClick={() => {
|
|
177
|
+
setEditing(false);
|
|
178
|
+
}}
|
|
179
|
+
>
|
|
180
|
+
Save
|
|
181
|
+
</LockButton>
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (authenticated) {
|
|
187
|
+
return (
|
|
188
|
+
<LockButton
|
|
189
|
+
mode="locked"
|
|
190
|
+
onClick={() => {
|
|
191
|
+
setEditing(true);
|
|
192
|
+
}}
|
|
193
|
+
>
|
|
194
|
+
Authorized
|
|
195
|
+
</LockButton>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<LockButton
|
|
201
|
+
mode="unlocked"
|
|
202
|
+
onClick={() => {
|
|
203
|
+
setEditing(true);
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
Authorize
|
|
207
|
+
</LockButton>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export default Authorization;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|
9
|
+
import {
|
|
10
|
+
SecurityRequirementObject,
|
|
11
|
+
SecuritySchemeObject,
|
|
12
|
+
} from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
|
13
|
+
|
|
14
|
+
import { ThemeConfig } from "../../../types";
|
|
15
|
+
import { createStorage, hashArray } from "../storage-utils";
|
|
16
|
+
import { getAuthDataKeys } from "./auth-types";
|
|
17
|
+
|
|
18
|
+
// The global definitions
|
|
19
|
+
// "securitySchemes": {
|
|
20
|
+
// "BearerAuth": { "type": "http", "scheme": "BeAreR" },
|
|
21
|
+
// "BasicAuth": { "type": "http", "scheme": "basic" }
|
|
22
|
+
// },
|
|
23
|
+
|
|
24
|
+
// The operation level requirements
|
|
25
|
+
// "security": [
|
|
26
|
+
// { "BearerAuth": [] },
|
|
27
|
+
// { "BearerAuth": [], "BasicAuth": [] }
|
|
28
|
+
// ],
|
|
29
|
+
|
|
30
|
+
// SLICE_STATE
|
|
31
|
+
// data:
|
|
32
|
+
// BearerAuth:
|
|
33
|
+
// token=xxx
|
|
34
|
+
// BasicAuth:
|
|
35
|
+
// username=xxx
|
|
36
|
+
// password=xxx
|
|
37
|
+
//
|
|
38
|
+
// options:
|
|
39
|
+
// "BearerAuth": [{ key: "BearerAuth", scopes: [], ...rest }]
|
|
40
|
+
// "BearerAuth and BasicAuth": [{ key: "BearerAuth", scopes: [], ...rest }, { key: "BasicAuth", scopes: [], ...rest }]
|
|
41
|
+
//
|
|
42
|
+
// selected: "BearerAuth and BasicAuth"
|
|
43
|
+
|
|
44
|
+
// LOCAL_STORAGE
|
|
45
|
+
// hash(SLICE_STATE.options) -> "BearerAuth and BasicAuth"
|
|
46
|
+
// BearerAuth -> { token: xxx }
|
|
47
|
+
// BasicAuth -> { username: xxx, password: xxx }
|
|
48
|
+
|
|
49
|
+
export function createAuth({
|
|
50
|
+
security,
|
|
51
|
+
securitySchemes,
|
|
52
|
+
options: opts,
|
|
53
|
+
}: {
|
|
54
|
+
security?: SecurityRequirementObject[];
|
|
55
|
+
securitySchemes?: {
|
|
56
|
+
[key: string]: SecuritySchemeObject;
|
|
57
|
+
};
|
|
58
|
+
options?: ThemeConfig["api"];
|
|
59
|
+
}): AuthState {
|
|
60
|
+
const storage = createStorage(opts?.authPersistance);
|
|
61
|
+
|
|
62
|
+
let data: AuthState["data"] = {};
|
|
63
|
+
let options: AuthState["options"] = {};
|
|
64
|
+
|
|
65
|
+
for (const option of security ?? []) {
|
|
66
|
+
const id = Object.keys(option).join(" and ");
|
|
67
|
+
for (const [schemeID, scopes] of Object.entries(option)) {
|
|
68
|
+
const scheme = securitySchemes?.[schemeID];
|
|
69
|
+
if (scheme) {
|
|
70
|
+
if (options[id] === undefined) {
|
|
71
|
+
options[id] = [];
|
|
72
|
+
}
|
|
73
|
+
const dataKeys = getAuthDataKeys(scheme);
|
|
74
|
+
for (const key of dataKeys) {
|
|
75
|
+
if (data[schemeID] === undefined) {
|
|
76
|
+
data[schemeID] = {};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let persisted = undefined;
|
|
80
|
+
try {
|
|
81
|
+
persisted = JSON.parse(storage.getItem(schemeID) ?? "")[key];
|
|
82
|
+
} catch {}
|
|
83
|
+
|
|
84
|
+
data[schemeID][key] = persisted;
|
|
85
|
+
}
|
|
86
|
+
options[id].push({
|
|
87
|
+
...scheme,
|
|
88
|
+
key: schemeID,
|
|
89
|
+
scopes,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let persisted = undefined;
|
|
96
|
+
try {
|
|
97
|
+
persisted = storage.getItem(hashArray(Object.keys(options))) ?? undefined;
|
|
98
|
+
} catch {}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
data,
|
|
102
|
+
options,
|
|
103
|
+
selected: persisted ?? Object.keys(options)[0],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export type Scheme = {
|
|
108
|
+
key: string;
|
|
109
|
+
scopes: string[];
|
|
110
|
+
} & SecuritySchemeObject;
|
|
111
|
+
|
|
112
|
+
export interface AuthState {
|
|
113
|
+
data: {
|
|
114
|
+
[scheme: string]: {
|
|
115
|
+
[key: string]: string | undefined;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
options: {
|
|
119
|
+
[key: string]: Scheme[];
|
|
120
|
+
};
|
|
121
|
+
selected?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const initialState: AuthState = {} as any;
|
|
125
|
+
|
|
126
|
+
export const slice = createSlice({
|
|
127
|
+
name: "auth",
|
|
128
|
+
initialState,
|
|
129
|
+
reducers: {
|
|
130
|
+
setAuthData: (
|
|
131
|
+
state,
|
|
132
|
+
action: PayloadAction<{ scheme: string; key: string; value?: string }>
|
|
133
|
+
) => {
|
|
134
|
+
const { scheme, key, value } = action.payload;
|
|
135
|
+
state.data[scheme][key] = value;
|
|
136
|
+
},
|
|
137
|
+
setSelectedAuth: (state, action: PayloadAction<string>) => {
|
|
138
|
+
state.selected = action.payload;
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export const { setAuthData, setSelectedAuth } = slice.actions;
|
|
144
|
+
|
|
145
|
+
export default slice.reducer;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import React from "react";
|
|
9
|
+
|
|
10
|
+
import { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
|
11
|
+
|
|
12
|
+
import ContentType from "../ContentType";
|
|
13
|
+
import FormSelect from "../FormSelect";
|
|
14
|
+
import { useTypedDispatch, useTypedSelector } from "../hooks";
|
|
15
|
+
import FormFileUpload from "./../FormFileUpload";
|
|
16
|
+
import FormItem from "./../FormItem";
|
|
17
|
+
import FormTextInput from "./../FormTextInput";
|
|
18
|
+
import VSCode from "./../VSCode";
|
|
19
|
+
import {
|
|
20
|
+
clearFormBodyKey,
|
|
21
|
+
clearRawBody,
|
|
22
|
+
setFileFormBody,
|
|
23
|
+
setFileRawBody,
|
|
24
|
+
setStringFormBody,
|
|
25
|
+
setStringRawBody,
|
|
26
|
+
} from "./slice";
|
|
27
|
+
|
|
28
|
+
interface Props {
|
|
29
|
+
jsonRequestBodyExample: string;
|
|
30
|
+
requestBodyMetadata?: RequestBodyObject;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function BodyWrap({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
34
|
+
const contentType = useTypedSelector((state) => state.contentType.value);
|
|
35
|
+
|
|
36
|
+
// NOTE: We used to check if body was required, but opted to always show the request body
|
|
37
|
+
// to reduce confusion, see: https://github.com/cloud-annotations/docusaurus-openapi/issues/145
|
|
38
|
+
|
|
39
|
+
// No body
|
|
40
|
+
if (contentType === undefined) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<>
|
|
46
|
+
<ContentType />
|
|
47
|
+
<Body
|
|
48
|
+
requestBodyMetadata={requestBodyMetadata}
|
|
49
|
+
jsonRequestBodyExample={jsonRequestBodyExample}
|
|
50
|
+
/>
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
|
|
56
|
+
const contentType = useTypedSelector((state) => state.contentType.value);
|
|
57
|
+
|
|
58
|
+
const dispatch = useTypedDispatch();
|
|
59
|
+
|
|
60
|
+
// Lot's of possible content-types:
|
|
61
|
+
// - application/json
|
|
62
|
+
// - application/xml
|
|
63
|
+
// - text/plain
|
|
64
|
+
// - text/css
|
|
65
|
+
// - text/html
|
|
66
|
+
// - text/javascript
|
|
67
|
+
// - application/javascript
|
|
68
|
+
// - multipart/form-data
|
|
69
|
+
// - application/x-www-form-urlencoded
|
|
70
|
+
// - image/svg+xml;charset=US-ASCII
|
|
71
|
+
|
|
72
|
+
// Show editor:
|
|
73
|
+
// - application/json
|
|
74
|
+
// - application/xml
|
|
75
|
+
// - */*
|
|
76
|
+
|
|
77
|
+
// Show form:
|
|
78
|
+
// - multipart/form-data
|
|
79
|
+
// - application/x-www-form-urlencoded
|
|
80
|
+
|
|
81
|
+
const schema = requestBodyMetadata?.content?.[contentType]?.schema;
|
|
82
|
+
|
|
83
|
+
if (schema?.format === "binary") {
|
|
84
|
+
return (
|
|
85
|
+
<FormItem label="Body">
|
|
86
|
+
<FormFileUpload
|
|
87
|
+
placeholder={schema.description || "Body"}
|
|
88
|
+
onChange={(file) => {
|
|
89
|
+
if (file === undefined) {
|
|
90
|
+
dispatch(clearRawBody());
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
dispatch(
|
|
94
|
+
setFileRawBody({
|
|
95
|
+
src: `/path/to/${file.name}`,
|
|
96
|
+
content: file,
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
</FormItem>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (
|
|
106
|
+
(contentType === "multipart/form-data" ||
|
|
107
|
+
contentType === "application/x-www-form-urlencoded") &&
|
|
108
|
+
schema?.type === "object"
|
|
109
|
+
) {
|
|
110
|
+
return (
|
|
111
|
+
<FormItem label="Body">
|
|
112
|
+
<div
|
|
113
|
+
style={{
|
|
114
|
+
marginTop: "calc(var(--ifm-pre-padding) / 2)",
|
|
115
|
+
borderRadius: "4px",
|
|
116
|
+
padding: "var(--ifm-pre-padding)",
|
|
117
|
+
border: "1px solid var(--openapi-monaco-border-color)",
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
{Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
|
|
121
|
+
if (val.format === "binary") {
|
|
122
|
+
return (
|
|
123
|
+
<FormItem key={key} label={key}>
|
|
124
|
+
<FormFileUpload
|
|
125
|
+
placeholder={val.description || key}
|
|
126
|
+
onChange={(file) => {
|
|
127
|
+
if (file === undefined) {
|
|
128
|
+
dispatch(clearFormBodyKey(key));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
dispatch(
|
|
132
|
+
setFileFormBody({
|
|
133
|
+
key: key,
|
|
134
|
+
value: {
|
|
135
|
+
src: `/path/to/${file.name}`,
|
|
136
|
+
content: file,
|
|
137
|
+
},
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
142
|
+
</FormItem>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (val.enum) {
|
|
147
|
+
return (
|
|
148
|
+
<FormItem key={key} label={key}>
|
|
149
|
+
<FormSelect
|
|
150
|
+
options={["---", ...val.enum]}
|
|
151
|
+
onChange={(e) => {
|
|
152
|
+
const val = e.target.value;
|
|
153
|
+
if (val === "---") {
|
|
154
|
+
dispatch(clearFormBodyKey(key));
|
|
155
|
+
} else {
|
|
156
|
+
dispatch(
|
|
157
|
+
setStringFormBody({
|
|
158
|
+
key: key,
|
|
159
|
+
value: val,
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}}
|
|
164
|
+
/>
|
|
165
|
+
</FormItem>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
// TODO: support all the other types.
|
|
169
|
+
return (
|
|
170
|
+
<FormItem key={key} label={key}>
|
|
171
|
+
<FormTextInput
|
|
172
|
+
placeholder={val.description || key}
|
|
173
|
+
onChange={(e) => {
|
|
174
|
+
dispatch(
|
|
175
|
+
setStringFormBody({ key: key, value: e.target.value })
|
|
176
|
+
);
|
|
177
|
+
}}
|
|
178
|
+
/>
|
|
179
|
+
</FormItem>
|
|
180
|
+
);
|
|
181
|
+
})}
|
|
182
|
+
</div>
|
|
183
|
+
</FormItem>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
let language = "plaintext";
|
|
188
|
+
let exampleBodyString = ""; //"body content";
|
|
189
|
+
|
|
190
|
+
if (contentType === "application/json") {
|
|
191
|
+
if (jsonRequestBodyExample) {
|
|
192
|
+
exampleBodyString = JSON.stringify(jsonRequestBodyExample, null, 2);
|
|
193
|
+
}
|
|
194
|
+
language = "json";
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (contentType === "application/xml") {
|
|
198
|
+
language = "xml";
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<FormItem label="Body">
|
|
203
|
+
<VSCode
|
|
204
|
+
value={exampleBodyString}
|
|
205
|
+
language={language}
|
|
206
|
+
onChange={(value) => {
|
|
207
|
+
if (value.trim() === "") {
|
|
208
|
+
dispatch(clearRawBody());
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
dispatch(setStringRawBody(value));
|
|
212
|
+
}}
|
|
213
|
+
/>
|
|
214
|
+
</FormItem>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export default BodyWrap;
|