Skip to content

Commit

Permalink
fix a bug on MS, sanitize HTML, and test sanitization of HTML on MS
Browse files Browse the repository at this point in the history
  • Loading branch information
taraepp committed Oct 18, 2024
1 parent 795bc28 commit e8c5571
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
}
},
"dependencies": {
"dompurify": "^3.1.7",
"html-react-parser": "^5.1.17",
"react-quill": "^2.0.0"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FormContext } from "./FormWrapper";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";
import parse from "html-react-parser";
import DOMPurify from "dompurify";

const RenderRichTextEditor: FC<BaseInputProps> = ({
label,
Expand Down Expand Up @@ -50,7 +51,7 @@ const RenderRichTextEditor: FC<BaseInputProps> = ({
};

if (!isEditMode) {
return <BaseViewInput value={parse(input.value)} label={label} />;
return <BaseViewInput value={parse(DOMPurify.sanitize(input.value))} label={label} />;
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jest.mock("react-router-dom", () => mockFunction());

describe("HelpGuide", () => {
it("renders CORE properly", async () => {
const helpKey = "Not-exists";
const helpKey = "Not-Exists";

const { findByTestId, findByText } = render(
<ReduxWrapper initialState={coreState}>
Expand All @@ -45,6 +45,9 @@ describe("HelpGuide", () => {
const helpButton = await findByTestId("help-open");
fireEvent.click(helpButton);

const defaultContent = await findByText("CORE default content");
expect(defaultContent).toBeInTheDocument();

const editButton = await findByText("Edit Help Guide");
fireEvent.click(editButton);

Expand Down
52 changes: 52 additions & 0 deletions services/common/src/components/help/HelpGuide-ms.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from "react";
import { render, fireEvent } from "@testing-library/react";
import { ReduxWrapper } from "@mds/common/tests/utils/ReduxWrapper";
import HelpGuide, { HelpGuideContent } from "./HelpGuide";
import { AUTHENTICATION } from "@mds/common/constants/reducerTypes";
import { SystemFlagEnum } from "@mds/common/constants";
import { MS_USER_ACCESS_DATA } from "@mds/common/tests/mocks/dataMocks";
import { helpReducerType } from "@mds/common/redux/slices/helpSlice";
import { BrowserRouter } from "react-router-dom";

const msState = {
[AUTHENTICATION]: {
systemFlag: SystemFlagEnum.ms,
userAccessData: MS_USER_ACCESS_DATA,
isAuthenticated: true,
},
[helpReducerType]: {
helpGuides: {},
},
};

function mockFunction() {
const original = jest.requireActual("react-router-dom");
return {
...original,
useParams: jest.fn().mockReturnValue({
tab: "overview",
}),
};
}

jest.mock("react-router-dom", () => mockFunction());

describe("HelpGuide", () => {
it("renders MS properly with default content", async () => {
const helpKey = "Not-Exists";
const { findByTestId } = render(
<BrowserRouter>
<ReduxWrapper initialState={msState}>
<HelpGuide />
<HelpGuideContent helpKey={helpKey} />
</ReduxWrapper>
</BrowserRouter>
);
const helpButton = await findByTestId("help-open");
fireEvent.click(helpButton);

const helpContent = await findByTestId("help-content");

expect(helpContent).toMatchSnapshot();
});
});
3 changes: 2 additions & 1 deletion services/common/src/components/help/HelpGuide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import HelpGuideForm from "./HelpGuideForm";
import { deleteConfirmWrapper } from "../common/ActionMenu";
import { formatSnakeCaseToSentenceCase } from "@mds/common/redux/utils/helpers";
import parse from "html-react-parser";
import DOMPurify from "dompurify";
import { useFeatureFlag } from "@mds/common/providers/featureFlags/useFeatureFlag";
import { Feature } from "@mds/common/utils";
import Loading from "../common/Loading";
Expand Down Expand Up @@ -132,7 +133,7 @@ export const HelpGuideContent: FC<HelpGuideProps> = ({ helpKey }) => {
pageTab={pageTab}
/>
) : (
parse(content)
parse(DOMPurify.sanitize(content))
);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`HelpGuide renders MS properly with default content 1`] = `
<div
data-testid="help-content"
>
<h2
class="ant-typography"
data-testid="help-title"
>
Overview
Help Guide
</h2>
<p>
console.log('should not render as inline function');}&gt;MS default content
</p>
</div>
`;
3 changes: 2 additions & 1 deletion services/common/src/tests/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const helpHandler = http.get("/%3CAPI_URL%3E/help/:helpKey", async ({ request, p

const guideData = system === SystemFlagEnum.core ? HELP_GUIDE_CORE : HELP_GUIDE_MS;

return HttpResponse.json(guideData[helpKey as string]);
const response = { records: [...guideData[helpKey as string]] };
return HttpResponse.json(response);
});

const commonHandlers = [...geoSpatialHandlers, ...projectHandlers, helpHandler];
Expand Down
9 changes: 8 additions & 1 deletion services/common/src/tests/mocks/dataMocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,12 @@ export const USER_ACCESS_DATA = [
"role_edit_project_summaries",
];

export const MS_USER_ACCESS_DATA = [
"mds_minespace_proponents",
"c_mds_users",
"c_mds_minespace_proponent",
];

export const DISTURBANCE_OPTIONS = {
records: [
{
Expand Down Expand Up @@ -8834,7 +8840,8 @@ export const HELP_GUIDE_MS = {
default: [
{
help_guid: "123",
content: "<p>MS default content</p>",
content:
"<script>console.log('hack');</script><p onClick={() => console.log('should not render as inline function');}>MS default content</p>",
tab: "all_tabs",
help_key: "default",
system: SystemFlagEnum.ms,
Expand Down
4 changes: 2 additions & 2 deletions services/core-api/app/api/help/resources/help_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class HelpListResource(Resource, UserMixin):
@requires_any_of([VIEW_ALL, MINESPACE_PROPONENT])
def get(self):
data = self.parser.parse_args()
system = data.get("system", None) if not is_minespace_user() else SystemFlag.ms
system = data.get("system", None) if not is_minespace_user() else str(SystemFlag.ms)

help_guides = Help.get_all(system)
return help_guides
Expand Down Expand Up @@ -82,7 +82,7 @@ class HelpResource(Resource, UserMixin):
@api.marshal_with(HELP_MODEL, code=200, envelope='records', as_list=True)
def get(self, help_key):
system = request.args['system']
if is_minespace_user() and system != SystemFlag.ms:
if is_minespace_user() and system != str(SystemFlag.ms):
raise BadRequest("Only MineSpace help guides may be requested.")
help_guides = Help.find_by_help_key(help_key, system)
return help_guides
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6885,6 +6885,13 @@ __metadata:
languageName: node
linkType: hard

"dompurify@npm:^3.1.7":
version: 3.1.7
resolution: "dompurify@npm:3.1.7"
checksum: 0a9b811bbc94f3dba60cf6486962362b0f1a5b4ab789f5e1cbd4749b6ba1a1fad190a677a962dc8850ce28764424765fe425e9d6508e4e93ba648ef15d54bc24
languageName: node
linkType: hard

"domutils@npm:^2.5.2, domutils@npm:^2.8.0":
version: 2.8.0
resolution: "domutils@npm:2.8.0"
Expand Down Expand Up @@ -12879,6 +12886,7 @@ __metadata:
dependencies:
"@typescript-eslint/eslint-plugin": ^5.59.1
"@typescript-eslint/parser": ^5.59.1
dompurify: ^3.1.7
eslint: 7.27.0
eslint-config-airbnb: 18.2.1
eslint-config-airbnb-typescript: ^17.0.0
Expand Down

0 comments on commit e8c5571

Please sign in to comment.