Skip to content

Commit

Permalink
Adding warning dialog if a user disables a sanitization rule
Browse files Browse the repository at this point in the history
  • Loading branch information
ehamai committed Dec 21, 2023
1 parent 5e66b77 commit 88a116b
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 67 deletions.
84 changes: 17 additions & 67 deletions src/components/Sanitizer/Sanitizer.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { Checkbox, DefaultButton, Link, PrimaryButton, Stack, Text } from "@fluentui/react"
import { checkboxStyle, getContainerStyle, layoutStackStyle, radioButtonStackStyle } from "./Sanitizer.styles"
import { FormEvent, useState } from "react";
import { DefaultButton, Link, PrimaryButton, Stack, Text } from "@fluentui/react"
import { getContainerStyle, layoutStackStyle } from "./Sanitizer.styles"
import { useState } from "react";
import { HarFile } from "../../sanitizer/models/harFile";
import { SanitizationCategories } from "../../sanitizer/sanitizer";
import { onFileUpload, sanitizeAndCompressFile } from "../../common/fileUpload";
import { useAppInsightsContext } from "@microsoft/applicationinsights-react-js";
import { SanitizerRuleCheckboxes } from "./SanitizerRuleCheckboxes";

export interface SanitizerProps {
setInspectFile: React.Dispatch<React.SetStateAction<boolean>>;
setSanitizedFileJson: React.Dispatch<React.SetStateAction<HarFile | null>>;
}

const stackTokens = {
childrenGap: 10
};

export const Sanitizer = (props: SanitizerProps) => {
const { setInspectFile, setSanitizedFileJson } = props;

Expand All @@ -31,28 +28,16 @@ export const Sanitizer = (props: SanitizerProps) => {

const appInsights = useAppInsightsContext();

const onChecked = (event: FormEvent<HTMLInputElement | HTMLElement> | undefined, checked?: boolean | undefined) => {
if (event) {
const newRulesToRun = { ...sanitizationCategories };
if (newRulesToRun[event.currentTarget.id] === undefined) {
throw Error(`Could not find property: "${event.currentTarget.id}"`);
}

newRulesToRun[event.currentTarget.id] = (event.currentTarget as any).checked;
setSanitizationCategories(newRulesToRun);
}
}

const restart = () => {
setDownloadUrl('');
setFileName('');
}

const dropHandler = async (event: React.DragEvent<HTMLDivElement>) =>{
const dropHandler = async (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
setIsDraggingFile(false);

if(event.dataTransfer.items && event.dataTransfer.items.length > 0 && event.dataTransfer.items[0].kind === 'file'){
if (event.dataTransfer.items && event.dataTransfer.items.length > 0 && event.dataTransfer.items[0].kind === 'file') {
await sanitizeAndCompressFile(
(event.dataTransfer.items[0].getAsFile() as File),
sanitizationCategories,
Expand All @@ -63,17 +48,17 @@ export const Sanitizer = (props: SanitizerProps) => {
}
}

const dragOverHandler = (event: React.DragEvent<HTMLDivElement>) =>{
const dragOverHandler = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
setIsDraggingFile(true);
}

const dragEndHandler = (event: React.DragEvent<HTMLDivElement>) =>{
const dragEndHandler = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
setIsDraggingFile(false);
}

const getButtons = () => {
const getDownloadOrInspectButtons = () => {
if (!downloadUrl) {
return <input
type="file"
Expand All @@ -98,48 +83,13 @@ export const Sanitizer = (props: SanitizerProps) => {
}

return <Stack enableScopedSelectors horizontalAlign="center" verticalAlign='center' style={layoutStackStyle}>
<Text variant='xxLarge' style={{ position: 'relative', left: '-263px', marginBottom: '10px' }}>HAR file sanitizer (preview)</Text>
<div style={getContainerStyle(isDraggingFile)} onDrop={dropHandler} onDragOver={dragOverHandler} onDragLeave={dragEndHandler}>
<Text variant='mediumPlus'>Choose categories to sanitize. Then select or drag and drop a HAR file to upload.</Text>
<Stack tokens={stackTokens} styles={radioButtonStackStyle} horizontal wrap>
<Checkbox
label="Cookies and headers"
checked={sanitizationCategories.cookiesAndHeaders}
id={'cookiesAndHeaders'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="Authorization Tokens"
checked={sanitizationCategories.authorizationTokens}
id={'authorizationTokens'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="JSON PUT and POST Requests"
checked={sanitizationCategories.generalJsonPutPostRequests}
id={'generalJsonPutPostRequests'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="ARM Post Responses"
checked={sanitizationCategories.armPostResponses}
id={'armPostResponses'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="JSON responses"
checked={sanitizationCategories.generalJsonResponses}
id={'generalJsonResponses'}
onChange={onChecked}
styles={checkboxStyle} />
</Stack>
<div style={{ marginTop: '50px' }}>
{getButtons()}
</div>
<Text variant='xxLarge' style={{ position: 'relative', left: '-263px', marginBottom: '10px' }}>HAR file sanitizer (preview)</Text>
<div style={getContainerStyle(isDraggingFile)} onDrop={dropHandler} onDragOver={dragOverHandler} onDragLeave={dragEndHandler}>
<Text variant='mediumPlus'>Choose categories to sanitize. Then select or drag and drop a HAR file to upload.</Text>
<SanitizerRuleCheckboxes sanitizationCategories={sanitizationCategories} setSanitizationCategories={setSanitizationCategories} />
<div style={{ marginTop: '50px' }}>
{getDownloadOrInspectButtons()}
</div>
</Stack>
</div>
</Stack>
}
106 changes: 106 additions & 0 deletions src/components/Sanitizer/SanitizerRuleCheckboxes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Checkbox, Dialog, DialogFooter, DialogType, PrimaryButton, Stack } from "@fluentui/react"
import { checkboxStyle, radioButtonStackStyle } from "./Sanitizer.styles"
import { SanitizationCategories } from "../../sanitizer/sanitizer"
import { FormEvent, useState } from "react"
import React from "react"

export interface SanitizerRuleCheckboxesProps {
sanitizationCategories: SanitizationCategories,
setSanitizationCategories: React.Dispatch<React.SetStateAction<SanitizationCategories>>
}

const dialogContentProps = {
type: DialogType.normal,
title: 'Be careful when disabling sanitization rules',
subText: `Disabling a rule means that the resulting HAR file may still contain sensitive information. If you proceed, make sure you manually inspect and scrub secrets from the file. If secrets are required for an investigation, make sure the HAR file is only shared through secure channels and is password-protected.`,
};

let warningWasShown = false;

export const SanitizerRuleCheckboxes = (props: SanitizerRuleCheckboxesProps) => {
const { sanitizationCategories, setSanitizationCategories } = props;
const [hideDialog, setHideDialog] = useState(true);

const modalProps = {
isBlocking: true,
}

const updateSanitizationRules = (ruleId: string, isChecked: boolean) => {
const newRulesToRun = { ...sanitizationCategories };
if (newRulesToRun[ruleId] === undefined) {
throw Error(`Could not find property: "${ruleId}"`);
}

newRulesToRun[ruleId] = isChecked;
setSanitizationCategories(newRulesToRun);
}

const showWarningDialog = () => {
setHideDialog(false);
}

const onChecked = async (event: FormEvent<HTMLInputElement | HTMLElement> | undefined, checked?: boolean | undefined) => {
if (event) {
const { id, checked } = (event.currentTarget as any);

if (!checked && !warningWasShown) {
showWarningDialog();
warningWasShown = true;
}

updateSanitizationRules(id, checked);
}
}

const onWarningDialogClosed = () => {
setHideDialog(true);
}

return <>
<Dialog
hidden={hideDialog}
onDismiss={showWarningDialog}
dialogContentProps={dialogContentProps}
modalProps={modalProps}>
<DialogFooter>
<PrimaryButton text="Ok" onClick={ onWarningDialogClosed } />
</DialogFooter>
</Dialog>
<Stack tokens={{ childrenGap: 10 }} styles={radioButtonStackStyle} horizontal wrap>
<Checkbox
label="Cookies and headers"
checked={sanitizationCategories.cookiesAndHeaders}
id={'cookiesAndHeaders'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="Authorization Tokens"
checked={sanitizationCategories.authorizationTokens}
id={'authorizationTokens'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="JSON PUT and POST Requests"
checked={sanitizationCategories.generalJsonPutPostRequests}
id={'generalJsonPutPostRequests'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="ARM Post Responses"
checked={sanitizationCategories.armPostResponses}
id={'armPostResponses'}
onChange={onChecked}
styles={checkboxStyle} />

<Checkbox
label="JSON responses"
checked={sanitizationCategories.generalJsonResponses}
id={'generalJsonResponses'}
onChange={onChecked}
styles={checkboxStyle} />
</Stack>
</>
}

0 comments on commit 88a116b

Please sign in to comment.