Skip to content

Commit d38e9cc

Browse files
authored
Merge pull request #662 from hack4impact-uiuc/security-updates
Security updates
2 parents 6f94dbf + fb297f0 commit d38e9cc

11 files changed

Lines changed: 2258 additions & 2964 deletions

File tree

apps/backend/package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,24 @@
55
"@aws-sdk/client-cognito-identity-provider": "^3.496.0",
66
"@aws-sdk/client-s3": "^3.496.0",
77
"aws-sdk-mock": "^5.1.0",
8-
"axios": "^1.6.0",
8+
"axios": "^1.18.1",
99
"body-parser": "^1.19.0",
1010
"cors": "^2.8.5",
1111
"express": "^4.17.1",
1212
"express-async-errors": "^3.1.1",
1313
"express-fileupload": "^1.2.0",
1414
"helmet": "^7.1.0",
1515
"join-images": "^1.1.5",
16-
"lodash": "^4.17.21",
16+
"lodash": "^4.18.1",
1717
"loglevel": "^1.7.1",
1818
"mongodb-memory-server": "^7.4.0",
1919
"mongoose": "^6.0.6",
2020
"mongoose-encryption": "^2.1.0",
2121
"node-2fa": "^2.0.2",
22-
"omit-deep-lodash": "^1.1.5",
2322
"pad": "^3.2.0",
2423
"pdf2pic": "^3.1.3",
2524
"supertest": "^6.1.3",
26-
"twilio": "^3.71.1"
25+
"twilio": "^6.0.2"
2726
},
2827
"devDependencies": {
2928
"@3dp4me/types": "workspace:*",
@@ -35,10 +34,14 @@
3534
"@types/lodash": "^4.14.202",
3635
"@types/node": "^20.9.4",
3736
"@types/pad": "^1.0.2",
37+
"canvas": "^3.2.3",
38+
"cross-env": "^7.0.3",
39+
"dotenv": "^17.4.2",
3840
"eslint-config-3dp4me": "workspace:*",
3941
"exceljs": "^4.4.0",
4042
"jest": "^27.0.6",
4143
"node-loader": "^2.1.0",
44+
"omit-deep-lodash": "^1.1.5",
4245
"rimraf": "^5.0.5",
4346
"ts-loader": "^9.5.1",
4447
"typescript": "^5.3.3",

apps/backend/src/middleware/authentication.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ export const requireRole =
4141
// If there isn't a user, authenticate
4242
if (!req.user) {
4343
return requireAuthentication(req, res, () => {
44-
requireRole(role)
45-
next()
44+
requireRole(role)(req, res, next)
4645
})
4746
}
4847
if (!req.user.roles.includes(role)) return sendResponse(res, 403, ERR_NOT_APPROVED)

apps/frontend/package.json

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,19 @@
1919
"@emotion/styled": "^11.14.1",
2020
"@mui/icons-material": "^6.4.5",
2121
"@mui/material": "^6.4.5",
22-
"@sweetalert/with-react": "^0.1.1",
2322
"@tanstack/react-query": "^5.17.19",
2423
"@vis.gl/react-google-maps": "^1.4.2",
25-
"Chip": "link:@mui/material/Chip",
2624
"aws-amplify": "4.2.11",
27-
"axios": "^1.6.0",
25+
"axios": "^1.18.1",
2826
"date-fns": "^3.3.0",
2927
"js-file-download": "^0.4.12",
30-
"lodash": "^4.17.21",
31-
"lodash.omit": "^4.5.0",
28+
"lodash": "^4.18.1",
3229
"mic-recorder-to-mp3": "^2.2.2",
3330
"object-hash": "^3.0.0",
3431
"react": "^18.2.0",
3532
"react-app-rewired": "^2.2.1",
3633
"react-code-input": "^3.10.1",
37-
"react-datepicker": "^4.25.0",
34+
"react-datepicker": "^9.1.0",
3835
"react-dom": "^18.2.0",
3936
"react-html5-camera-photo": "^1.5.5",
4037
"react-image-gallery": "^1.2.7",
@@ -45,7 +42,7 @@
4542
"react-promise-tracker": "^2.1.0",
4643
"react-router-dom": "^5.2.0",
4744
"react-scripts": "^5.0.1",
48-
"react-signature-canvas": "^1.0.6",
45+
"react-signature-canvas": "1.1.0-alpha.2",
4946
"react-switch": "^6.0.0",
5047
"signature_pad": "^2.3.2",
5148
"styled-components": "^6.1.8",
@@ -57,18 +54,12 @@
5754
"@babel/core": "^7.23.3",
5855
"@babel/preset-env": "^7.23.3",
5956
"@babel/preset-react": "^7.23.3",
60-
"@rollup/plugin-commonjs": "^25.0.7",
61-
"@rollup/plugin-image": "^3.0.3",
62-
"@rollup/plugin-json": "^6.0.1",
63-
"@rollup/plugin-node-resolve": "^15.2.3",
64-
"@rollup/plugin-typescript": "^11.1.5",
6557
"@types/jest": "^29.5.8",
6658
"@types/lodash": "^4.14.202",
67-
"@types/lodash.omit": "^4.5.9",
6859
"@types/node": "^20.9.4",
6960
"@types/object-hash": "^3.0.6",
7061
"@types/react": "^18.2.37",
71-
"@types/react-datepicker": "^4.19.3",
62+
"@types/react-datepicker": "^7.0.0",
7263
"@types/react-dom": "^18.2.15",
7364
"@types/react-html5-camera-photo": "^1.5.3",
7465
"@types/react-image-gallery": "^1.2.4",
@@ -83,17 +74,9 @@
8374
"css-loader": "^6.8.1",
8475
"dotenv-webpack": "^8.0.1",
8576
"eslint-config-3dp4me": "workspace:*",
86-
"file-loader": "^6.2.0",
8777
"html-webpack-plugin": "^5.5.3",
88-
"image-webpack-loader": "^8.1.0",
89-
"react-app-env": "^1.2.3",
9078
"react-app-rewired": "^2.2.1",
9179
"rimraf": "^5.0.5",
92-
"rollup": "^4.5.0",
93-
"rollup-plugin-babel": "^4.4.0",
94-
"rollup-plugin-postcss": "^4.0.2",
95-
"rollup-plugin-terser": "^7.0.2",
96-
"rollup-plugin-visualizer": "^5.9.2",
9780
"sass": "^1.69.5",
9881
"sass-loader": "^13.3.2",
9982
"source-map-explorer": "^2.5.3",

apps/frontend/rollup.config.mjs

Lines changed: 0 additions & 39 deletions
This file was deleted.

apps/frontend/src/components/ControlledSignatureCanvas/ControlledSignatureCanvas.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
import { Nullish, Signature, SignaturePoint } from '@3dp4me/types'
2-
import omit from 'lodash.omit'
2+
import omit from 'lodash/omit'
33
import { FC, useEffect, useRef, useState } from 'react'
44
import ReactSignatureCanvas from 'react-signature-canvas'
5+
import SignaturePad from 'signature_pad'
56

67
interface ControlledSignatureCanvasProps {
78
value: Nullish<Signature>
9+
width: number
10+
height: number
811
}
912

1013
/**
1114
* This library doesn't work great for "controlled" canvases. So we just encapsulate it here so that
1215
* we can make it mount and unmout on every value update
1316
* @returns
1417
*/
15-
export const ControlledSignatureCanvas: FC<ControlledSignatureCanvasProps> = ({ value }) => {
18+
export const ControlledSignatureCanvas: FC<ControlledSignatureCanvasProps> = ({
19+
value,
20+
width,
21+
height,
22+
}) => {
1623
const sigCanvas = useRef<ReactSignatureCanvas | null>(null)
1724
const [doesCanvasHaveData, setDoesCanvasHaveData] = useState(false)
1825

@@ -31,7 +38,7 @@ export const ControlledSignatureCanvas: FC<ControlledSignatureCanvasProps> = ({
3138
)
3239

3340
setDoesCanvasHaveData(true)
34-
setImmediate(() => sigCanvas.current?.fromData(data as any))
41+
setTimeout(() => sigCanvas.current?.fromData(data as SignaturePad.Point[][]), 0)
3542
}, [value, sigCanvas.current, doesCanvasHaveData])
3643

3744
/**
@@ -67,5 +74,13 @@ export const ControlledSignatureCanvas: FC<ControlledSignatureCanvasProps> = ({
6774
return formattedData
6875
}
6976

70-
return <ReactSignatureCanvas ref={sigCanvas} clearOnResize={false} />
77+
// Giving the canvas explicit dimensions makes the library skip its own
78+
// offsetWidth-based resize on mount, which reads 0 if layout hasn't settled
79+
return (
80+
<ReactSignatureCanvas
81+
ref={sigCanvas}
82+
clearOnResize={false}
83+
canvasProps={{ width, height }}
84+
/>
85+
)
7186
}

apps/frontend/src/components/Fields/DateField.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ registerLocale(LANGUAGES.AR, arSA)
2323
const DateField = ({ displayName, isDisabled, fieldId, value, onChange }: DateFieldProps) => {
2424
const selectedLang = useTranslations()[1]
2525

26-
const sendChanges = (date: Date) => {
27-
onChange(fieldId, date.toString())
26+
const sendChanges = (date: Date | null) => {
27+
onChange(fieldId, date?.toString() || '')
2828
}
2929

3030
const className = isDisabled ? 'input-field datepicker' : 'active-input datepicker'

apps/frontend/src/components/Fields/FieldGroup/FieldGroupTable.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ const CellEditContainer = styled(TableCell)`
6363
width: 100%;
6464
}
6565
66+
.react-datepicker-popper {
67+
z-index: 10;
68+
}
69+
6670
// Take full width for date picker
6771
.react-datepicker-wrapper {
6872
width: 100%;

apps/frontend/src/components/Fields/SignatureField.tsx

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import './SignatureField.scss'
55
import { Nullish, Path, PathValue, Signature, TranslatedString } from '@3dp4me/types'
66
import Button from '@mui/material/Button'
77
import hash from 'object-hash'
8-
import { useState } from 'react'
8+
import { useLayoutEffect, useRef, useState } from 'react'
99

1010
import { useTranslations } from '../../hooks/useTranslations'
1111
import { ControlledSignatureCanvas } from '../ControlledSignatureCanvas/ControlledSignatureCanvas'
@@ -31,6 +31,23 @@ const SignatureField = <T extends string>({
3131
const [isModalOpen, setIsModalOpen] = useState(false)
3232
const [isDocumentVisible, setIsDocumentVisible] = useState(false)
3333
const translations = useTranslations()[0]
34+
const sigContainerRef = useRef<HTMLDivElement | null>(null)
35+
const [canvasWidth, setCanvasWidth] = useState(0)
36+
37+
// Watch the container's size so the canvas gets a real width even if the
38+
// container had no layout (width 0) when this component first mounted
39+
useLayoutEffect(() => {
40+
const container = sigContainerRef.current
41+
if (!container) return undefined
42+
43+
const observer = new ResizeObserver(() =>
44+
setTimeout(() => setCanvasWidth(container.offsetWidth), 0)
45+
)
46+
observer.observe(container)
47+
return () => {
48+
observer.disconnect()
49+
}
50+
}, [])
3451

3552
/**
3653
* Saves signature data points along with the canvas width and height so that
@@ -89,9 +106,15 @@ const SignatureField = <T extends string>({
89106
onSave={onNewSignature}
90107
isOpen={isModalOpen}
91108
/>
92-
<div className="sig-container">
93-
{/* We need to keep changing the key to force a rerender */}
94-
<ControlledSignatureCanvas key={hashSignature(value)} value={value} />
109+
<div className="sig-container" ref={sigContainerRef}>
110+
{canvasWidth > 0 && (
111+
<ControlledSignatureCanvas
112+
key={hashSignature(value, canvasWidth)}
113+
value={value}
114+
width={canvasWidth}
115+
height={canvasWidth / 2}
116+
/>
117+
)}
95118
<div className="sig-ctl-container">
96119
<Button
97120
className="sig-ctl-button doc-btn"
@@ -115,10 +138,10 @@ const SignatureField = <T extends string>({
115138
)
116139
}
117140

118-
const hashSignature = (sig: Nullish<Signature>): string => {
141+
const hashSignature = (sig: Nullish<Signature>, width: number): string => {
119142
if (!sig) return hash(Math.random())
120143

121-
return hash(JSON.stringify(sig))
144+
return hash(JSON.stringify(sig) + width.toString())
122145
}
123146

124147
export default SignatureField

apps/frontend/webpack.config.mjs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import Dotenv from "dotenv-webpack";
2-
// const path = require("path")
3-
import path from "path";
4-
// import { Configuration } from "webpack";
52
import CopyWebpackPlugin from "copy-webpack-plugin";
63
import HtmlWebpackPlugin from "html-webpack-plugin";
7-
import nodeExternals from "webpack-node-externals"
84

95
const config = {
106
mode: "production",
@@ -34,15 +30,7 @@ const config = {
3430

3531
{
3632
test: /\.(gif|png|jpe?g|svg)$/i,
37-
use: [
38-
'file-loader',
39-
{
40-
loader: 'image-webpack-loader',
41-
options: {
42-
disable: true,
43-
},
44-
},
45-
],
33+
type: 'asset/resource',
4634
},
4735

4836
{ test: /\.([cm]?ts|tsx)$/, loader: "ts-loader", exclude: /node_modules/ },

0 commit comments

Comments
 (0)