Skip to content

Commit

Permalink
Merge pull request #108 from CS3219-AY2324S1/add-html-sanitization
Browse files Browse the repository at this point in the history
Add html sanitization
  • Loading branch information
szelongq authored Nov 14, 2023
2 parents 98d777f + aec7c75 commit bbf9036
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 36 deletions.
15 changes: 15 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/dompurify": "^3.0.5",
"@types/jest": "^27.5.2",
"assert": "^2.1.0",
"axios": "^1.5.1",
"dompurify": "^3.0.6",
"dotenv": "^16.3.1",
"firebase": "^10.4.0",
"html-entities": "^2.4.0",
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/AdminUsersTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const AdminUsersTable: React.FC = () => {

return (
<>
<div style={{ maxHeight: "400px", overflowY: "auto", width: "100%" }}>
<div style={{ maxHeight: "600px", overflowY: "auto", width: "100%", display: "flex" }}>
<TableContainer
component={Paper}
style={{ margin: "10px", padding: "10px" }}
Expand Down Expand Up @@ -125,7 +125,7 @@ const AdminUsersTable: React.FC = () => {
</Table>
</TableContainer>
</div>
<div style={{ display: "flex", alignItems: "center" }}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
<Select
value={itemsPerPage}
onChange={handleChangeItemsPerPage}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/CollabProblemSolverLeft.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function CollabProblemSolverLeft({
{question.title}
</Typography>
<Divider sx={{ marginBottom: 2, marginTop: 5 }} />
<Typography variant="body1" sx={{ marginBottom: 2, fontSize: "18px", overflowX: 'auto' }}>
<Typography component={'span'} variant="body1" sx={{ marginBottom: 2, fontSize: "18px", overflowX: 'auto' }}>
{parseHtmlDescription(question.description)}
</Typography>
<Divider sx={{ marginBottom: 10 }} />
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ export default function Navbar() {

let settings = [
{ name: "Profile", onclick: () => navigate("/profile", { replace: true }) },
{ name: "Account", onclick: handleCloseUserMenu },
{ name: "Dashboard", onclick: handleCloseUserMenu },
{ name: "Logout", onclick: logout },
];
if (user?.role === "master") {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/NormalUsersTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const NormalUsersTable: React.FC = () => {
const currentUsers = normalUsersData.slice(indexOfFirstUser, indexOfLastUser);

return (
<><div style={{ maxHeight: '400px', overflowY: 'auto', width: '100%' }}>
<><div style={{ maxHeight: '600px', overflowY: 'auto', width: '100%', display: "flex" }}>

<TableContainer component={Paper} style={{ margin: '10px', padding: '10px' }}>
<Grid container>
Expand Down Expand Up @@ -101,7 +101,7 @@ const NormalUsersTable: React.FC = () => {
</TableBody>
</Table>
</TableContainer>
</div><div style={{ display: 'flex', alignItems: 'center' }}>
</div><div style={{ display: 'flex', alignItems: 'center', justifyContent: "center" }}>
<Select
value={itemsPerPage}
onChange={handleChangeItemsPerPage}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ProblemSolverLeft.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const ProblemSolverLeft = () => {
{question.title}
</Typography>
<Divider sx={{ marginBottom: 2, marginTop: 5 }} />
<Typography variant="body1" sx={{ marginBottom: 2, fontSize: '18px', overflowX: 'auto' }}>
<Typography component={'span'} variant="body1" sx={{ marginBottom: 2, fontSize: '18px', overflowX: 'auto' }}>
{parseHtmlDescription(question.description)}
</Typography>
<Divider sx={{ marginBottom: 10 }} />
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Questions/EditQuestionTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const EditQuestionTab: React.FC<EditQuestionPreviewProps> = ({question, onEdit,
<Typography variant="h5" gutterBottom component="div">
{question.title}
</Typography>
<Typography variant="body2" gutterBottom component="div">
<Typography variant="body2" gutterBottom component="span">
{parseHtmlDescription(question.description)}
</Typography>
<br />
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Questions/QuestionsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ const InterviewQuestionsTable: React.FC = () => {
<Typography variant="body2" style={{ padding: "5px" }}>
<b>Difficulty:</b> {selectedQuestion.difficulty}
</Typography>
<Typography variant="body2" style={{ padding: "5px" }}>
<Typography component={'span'} variant="body2" style={{ padding: "5px" }}>
<b>Description</b>: {parseHtmlDescription(selectedQuestion.description)}
</Typography>
</DialogContent>
Expand Down
66 changes: 40 additions & 26 deletions frontend/src/pages/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,35 +55,49 @@ export default function Profile() {
<Navbar />
<Container sx={{ mt: 5 }}>
<Grid container spacing={2}>
<Grid item xs={12} sm={4}>
<Avatar sx={{ height: 192, width: 192, mb: 2 }}>R</Avatar>
{user && <Chip label={user.role} color="primary" />}
<Grid item container spacing={2}>
<Grid item xs={12} sm={4}>
<Grid container direction="column" spacing={2}>
<Grid item xs={12} justifyContent={"center"}>
<Avatar sx={{ height: 192, width: 192, mb: 2 }}>R</Avatar>
</Grid>
<Grid item xs={12} alignItems={"center"}>
{user && <Chip label={user.role} color="primary" />}
</Grid>
<Grid item xs={12}>
<DeleteButtonModal />
</Grid>
</Grid>
</Grid>
<Grid item xs={12} sm={8}>
<Box display="flex" justifyContent="flex-end" width="100%">
<Button
variant="contained"
onClick={toggleEdit}
color={edit ? "success" : "primary"}
>
{edit ? "Save Details" : "Edit Details"}
</Button>
</Box>
{profileFields.map((field) => (
<ProfileField
key={field.title}
title={field.title}
data={field.data}
edit={edit}
value={value}
setValue={setValue}
/>
))}
</Grid>
</Grid>
<Grid item xs={12} sm={8}>
<Box display="flex" justifyContent="flex-end" width="100%">
<Button
variant="contained"
onClick={toggleEdit}
color={edit ? "success" : "primary"}
>
{edit ? "Save Details" : "Edit Details"}
</Button>
</Box>
{profileFields.map((field) => (
<ProfileField
key={field.title}
title={field.title}
data={field.data}
edit={edit}
value={value}
setValue={setValue}
/>
))}
<Grid item xs={12}>
{user?.role === "master" && <AdminUsersTable />}
</Grid>
<Grid item xs={12}>
{user?.role === "master" && <NormalUsersTable />}
</Grid>
</Grid>
<DeleteButtonModal />
{user?.role === "master" && <AdminUsersTable />}
{user?.role === "master" && <NormalUsersTable />}
</Container>
</Box>
);
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/utils/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {decode} from "html-entities";
import htmr from "htmr";
import {ReactNode} from "react";
import DOMPurify from "dompurify";

export function parseHtmlDescription(description: string): ReactNode {
// Decode escaped HTML characters and add text wrap to pre tags in the question description
let decodedDescription = decode(description)
.replace(/<pre>/g, "<pre style=\"white-space: pre-wrap;\">");
decodedDescription = DOMPurify.sanitize(decodedDescription);
return htmr(decodedDescription);
}

0 comments on commit bbf9036

Please sign in to comment.