diff --git a/packages/oscal-react-library/src/components/OSCALLoader.tsx b/packages/oscal-react-library/src/components/OSCALLoader.tsx index c7b3331b..ef22191f 100644 --- a/packages/oscal-react-library/src/components/OSCALLoader.tsx +++ b/packages/oscal-react-library/src/components/OSCALLoader.tsx @@ -121,32 +121,62 @@ export default function OSCALLoader(props: OSCALLoaderProps): ReactElement { const oscalObjectUuid = useParams()?.id ?? ""; const buildOscalUrl = (uuid: string) => `${props.backendUrl}/${props.oscalObjectType.restPath}/${uuid}`; - const determineDefaultOscalUrl = () => + const determineDefaultOscalUrl = () => (props.isRestMode ? null : getRequestedUrl()) || props.oscalObjectType.defaultUrl; const [oscalUrl, setOscalUrl] = useState(determineDefaultOscalUrl()); + + const [username, setUsername] = useState(""); + const handleUsernameChange = (value: string) => { + setUsername(value); + }; + + const [password, setPassword] = useState(""); + const handlePasswordChange = (value: string) => { + setPassword(value); + }; + + const [checked, setChecked] = useState(false); + const handleCheckboxChange = (value: boolean) => { + setChecked(value); + }; const loadOscalData = (newOscalUrl: string) => { if (!newOscalUrl) { setIsLoaded(true); return; } - fetch(newOscalUrl) - .then((response) => { - if (!response.ok) throw new Error(response.status.toString()); - else return response.text(); - }) - .then((result) => Convert.toOscal(result)) - .then((oscalObj) => { - if (isMounted.current) { - const source = Convert.oscalToJson(oscalObj); - // TODO: Currently data is passed to components through modifying objects. - // This approach should be revisited. - // https://github.com/EasyDynamics/oscal-react-library/issues/297 - setOscalData({ ...oscalObj, oscalSource: source }); - setIsLoaded(true); - } - }, handleError); + + const options = checked + ? { + method: 'GET', + headers: { + 'Authorization': `Basic ${btoa(username + ":" + password)}`, + 'Content-Type': 'application/json', + }, + } + : {}; + + fetch(newOscalUrl, options) + .then((response) => { + if (!response.ok) { + throw new Error(response.status.toString()); + } + return response.text(); + }) + .then((result) => Convert.toOscal(result)) + .then((oscalObj) => { + if (isMounted.current) { + const source = Convert.oscalToJson(oscalObj); + // TODO: Currently data is passed to components through modifying objects. + // This approach should be revisited. + // https://github.com/EasyDynamics/oscal-react-library/issues/297 + setOscalData({ ...oscalObj, oscalSource: source }); + setIsLoaded(true); + } + }) + .catch(handleError); + }; const handleFieldSave: OnFieldSaveHandlerWrapped = ( @@ -304,7 +334,7 @@ export default function OSCALLoader(props: OSCALLoaderProps): ReactElement { let form; if (props.renderForm && hasDefaultUrl) { form = ( - ); } diff --git a/packages/oscal-react-library/src/components/OSCALLoaderForm.jsx b/packages/oscal-react-library/src/components/OSCALLoaderForm.jsx index 3f5f775e..9cc423c3 100644 --- a/packages/oscal-react-library/src/components/OSCALLoaderForm.jsx +++ b/packages/oscal-react-library/src/components/OSCALLoaderForm.jsx @@ -1,11 +1,12 @@ -import React, { useRef } from "react"; +import React, { useRef, useState, useCallback } from "react"; import { styled } from "@mui/material/styles"; import Grid from "@mui/material/Grid"; import Stack from "@mui/material/Stack"; -import TextField from "@mui/material/TextField"; import Button from "@mui/material/Button"; import ReplayIcon from "@mui/icons-material/Replay"; import FileUploadIcon from "@mui/icons-material/FileUpload"; +import { TextField, FormControlLabel, Checkbox, Collapse, Box } from "@mui/material"; +import debounce from "lodash.debounce"; const OSCALDocumentForm = styled("form")( ({ theme }) => ` @@ -17,6 +18,18 @@ const OSCALDocumentForm = styled("form")( export default function OSCALLoaderForm(props) { const url = useRef(props.oscalUrl); + const [checked, setChecked] = useState(false); + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + + async function handleUsernameChange(e) { + props.onUsernameChange(e.target.value); + }; + + async function handlePasswordChange(e) { + props.onPasswordChange(e.target.value); + }; + const submitForm = () => { props.onUrlChange(url.current.value); }; @@ -28,15 +41,20 @@ export default function OSCALLoaderForm(props) { props.onUrlChange(fileUrl); }; + const handleCheckboxChange = (event) => { + props.onCheckboxChange(event.target.checked); + setChecked(event.target.checked); + }; + return ( { - submitForm(); e.preventDefault(); - }} - > + submitForm(); + }} + > {!props.isRestMode && ( <> @@ -72,9 +90,36 @@ export default function OSCALLoaderForm(props) { > Upload - + + + } + label="Enable Basic Authentication" + /> + + setUsername(e.target.value)} + onBlur={handleUsernameChange} + required={checked} + fullWidth + margin="normal" + /> + setPassword(e.target.value)} + onBlur={handlePasswordChange} + required={checked} + fullWidth + margin="normal" + /> + + )}