From e3ed08fac73677a8cb990fc0d761b2c6fa0b3c52 Mon Sep 17 00:00:00 2001 From: Amelia Vance Date: Wed, 28 Feb 2024 13:29:16 -0500 Subject: [PATCH 1/8] Add state input to the organization form --- .../OrganizationForm/OrganizationForm.tsx | 72 +++++++++-- frontend/src/constants/constants.js | 121 ++++++++++++++++++ frontend/src/types/organization.ts | 1 + 3 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 frontend/src/constants/constants.js diff --git a/frontend/src/components/OrganizationForm/OrganizationForm.tsx b/frontend/src/components/OrganizationForm/OrganizationForm.tsx index 6643a4f00..2087026aa 100644 --- a/frontend/src/components/OrganizationForm/OrganizationForm.tsx +++ b/frontend/src/components/OrganizationForm/OrganizationForm.tsx @@ -3,19 +3,23 @@ import * as orgFormStyles from './orgFormStyle'; import { Organization, OrganizationTag } from 'types'; import { Autocomplete, + Box, + Button, + Chip, + createFilterOptions, DialogTitle, DialogContent, - TextField, DialogActions, - Switch, - Button, FormControlLabel, - Box, - Chip, Grid, - createFilterOptions + MenuItem, + Select, + Switch, + TextField, + Typography } from '@mui/material'; - +import { SelectChangeEvent } from '@mui/material/Select'; +import { STATE_OPTIONS } from '../../constants/constants'; import { useAuthContext } from 'context'; const classes = orgFormStyles.classes; @@ -31,6 +35,7 @@ export interface OrganizationFormValues { ipBlocks: string; isPassive: boolean; tags: OrganizationTag[]; + state?: string | null | undefined; } export const OrganizationForm: React.FC<{ @@ -46,7 +51,8 @@ export const OrganizationForm: React.FC<{ rootDomains: organization ? organization.rootDomains.join(', ') : '', ipBlocks: organization ? organization.ipBlocks.join(', ') : '', isPassive: organization ? organization.isPassive : false, - tags: [] + tags: [], + state: organization ? organization.state : '' }); const { apiGet } = useAuthContext(); @@ -79,7 +85,20 @@ export const OrganizationForm: React.FC<{ [name]: value })); }; + const handleStateChange = (event: SelectChangeEvent) => { + setValues((values) => ({ + ...values, + [event.target.name]: event.target.value + })); + }; + const textFieldStyling = { + '& .MuiOutlinedInput-root': { + '&.Mui-focused fieldset': { + borderRadius: '0px' + } + } + }; return ( + Organization Name + Root Domains + IP Blocks + Organization State +
@@ -256,6 +305,7 @@ export const OrganizationForm: React.FC<{ ? [] : values.ipBlocks.split(',').map((ip) => ip.trim()), name: values.name, + state: values.state, isPassive: values.isPassive, tags: chosenTags, parent: parent ? parent.id : undefined diff --git a/frontend/src/constants/constants.js b/frontend/src/constants/constants.js new file mode 100644 index 000000000..ec161416a --- /dev/null +++ b/frontend/src/constants/constants.js @@ -0,0 +1,121 @@ +export const STATE_OPTIONS = [ + 'Alabama', + 'Alaska', + 'American Samoa', + 'Arizona', + 'Arkansas', + 'California', + 'Colorado', + 'Commonwealth Northern Mariana Islands', + 'Connecticut', + 'Delaware', + 'District of Columbia', + 'Federal States of Micronesia', + 'Florida', + 'Georgia', + 'Guam', + 'Hawaii', + 'Idaho', + 'Illinois', + 'Indiana', + 'Iowa', + 'Kansas', + 'Kentucky', + 'Louisiana', + 'Maine', + 'Maryland', + 'Massachusetts', + 'Michigan', + 'Minnesota', + 'Mississippi', + 'Missouri', + 'Montana', + 'Nebraska', + 'Nevada', + 'New Hampshire', + 'New Jersey', + 'New Mexico', + 'New York', + 'North Carolina', + 'North Dakota', + 'Ohio', + 'Oklahoma', + 'Oregon', + 'Pennsylvania', + 'Puerto Rico', + 'Republic of Marshall Islands', + 'Rhode Island', + 'South Carolina', + 'South Dakota', + 'Tennessee', + 'Texas', + 'Utah', + 'Vermont', + 'Virgin Islands', + 'Virginia', + 'Washington', + 'West Virginia', + 'Wisconsin', + 'Wyoming' +]; + +export const STATE_ABBREVIATED_OPTIONS = [ + 'AL', // Alabama + 'AK', // Alaska + 'AS', // American Samoa + 'AZ', // Arizona + 'AR', // Arkansas + 'CA', // California + 'CO', // Colorado + 'MP', // Commonwealth Northern Mariana Islands + 'CT', // Connecticut + 'DE', // Delaware + 'DC', // District of Columbia + 'FM', // Federal States of Micronesia + 'FL', // Florida + 'GA', // Georgia + 'GU', // Guam + 'HI', // Hawaii + 'ID', // Idaho + 'IL', // Illinois + 'IN', // Indiana + 'IA', // Iowa + 'KS', // Kansas + 'KY', // Kentucky + 'LA', // Louisiana + 'ME', // Maine + 'MD', // Maryland + 'MA', // Massachusetts + 'MI', // Michigan + 'MN', // Minnesota + 'MS', // Mississippi + 'MO', // Missouri + 'MT', // Montana + 'NE', // Nebraska + 'NV', // Nevada + 'NH', // New Hampshire + 'NJ', // New Jersey + 'NM', // New Mexico + 'NY', // New York + 'NC', // North Carolina + 'ND', // North Dakota + 'OH', // Ohio + 'OK', // Oklahoma + 'OR', // Oregon + 'PA', // Pennsylvania + 'PR', // Puerto Rico + 'MH', // Republic of Marshall Islands + 'RI', // Rhode Island + 'SC', // South Carolina + 'SD', // South Dakota + 'TN', // Tennessee + 'TX', // Texas + 'UT', // Utah + 'VT', // Vermont + 'VI', // Virgin Islands + 'VA', // Virginia + 'WA', // Washington + 'WV', // West Virginia + 'WI', // Wisconsin + 'WY' // Wyoming +]; diff --git a/frontend/src/types/organization.ts b/frontend/src/types/organization.ts index 396113de9..d4aded988 100644 --- a/frontend/src/types/organization.ts +++ b/frontend/src/types/organization.ts @@ -39,4 +39,5 @@ export interface OrganizationTag { tags: OrganizationTag[]; organizations: Organization[]; scans: Scan[]; + state: string; } From 951ca211bb95107cc657dd8f0cab3f2d7d1cecb2 Mon Sep 17 00:00:00 2001 From: Amelia Vance Date: Mon, 4 Mar 2024 11:54:18 -0500 Subject: [PATCH 2/8] Update Organization state field to stateName to reflect database --- .../OrganizationForm/OrganizationForm.tsx | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/OrganizationForm/OrganizationForm.tsx b/frontend/src/components/OrganizationForm/OrganizationForm.tsx index 2087026aa..7089ecbf9 100644 --- a/frontend/src/components/OrganizationForm/OrganizationForm.tsx +++ b/frontend/src/components/OrganizationForm/OrganizationForm.tsx @@ -35,7 +35,8 @@ export interface OrganizationFormValues { ipBlocks: string; isPassive: boolean; tags: OrganizationTag[]; - state?: string | null | undefined; + stateName?: string | null | undefined; + acronym?: string | null; } export const OrganizationForm: React.FC<{ @@ -52,7 +53,8 @@ export const OrganizationForm: React.FC<{ ipBlocks: organization ? organization.ipBlocks.join(', ') : '', isPassive: organization ? organization.isPassive : false, tags: [], - state: organization ? organization.state : '' + stateName: organization ? organization.stateName : '', + acronym: organization ? organization.acronym : '' }); const { apiGet } = useAuthContext(); @@ -125,6 +127,20 @@ export const OrganizationForm: React.FC<{ value={values.name} onChange={onTextChange} /> + Organization Acronym + Root Domains Organization State @@ -305,9 +322,10 @@ export const OrganizationForm: React.FC<{ ? [] : values.ipBlocks.split(',').map((ip) => ip.trim()), name: values.name, - state: values.state, + stateName: values.stateName, isPassive: values.isPassive, tags: chosenTags, + acronym: values.acronym, parent: parent ? parent.id : undefined }); if (!organization) setValues(defaultValues); From cecd966b696e67360ec31597a6814002f11a8980 Mon Sep 17 00:00:00 2001 From: Amelia Vance Date: Mon, 4 Mar 2024 11:58:07 -0500 Subject: [PATCH 3/8] Add TODO to fix tag selection issues in OrganizationForm.tsx --- frontend/src/components/OrganizationForm/OrganizationForm.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/OrganizationForm/OrganizationForm.tsx b/frontend/src/components/OrganizationForm/OrganizationForm.tsx index 7089ecbf9..84332e4d3 100644 --- a/frontend/src/components/OrganizationForm/OrganizationForm.tsx +++ b/frontend/src/components/OrganizationForm/OrganizationForm.tsx @@ -189,6 +189,7 @@ export const OrganizationForm: React.FC<{ ))} + {/* TODO: Fix Tag selection issues. */}
From b5183c7115ba91b9916745e88fcd8cb28bdd5cdf Mon Sep 17 00:00:00 2001 From: Amelia Vance Date: Mon, 4 Mar 2024 12:06:26 -0500 Subject: [PATCH 4/8] Update OrganiationForm layout --- .../components/OrganizationForm/OrganizationForm.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/OrganizationForm/OrganizationForm.tsx b/frontend/src/components/OrganizationForm/OrganizationForm.tsx index 84332e4d3..7f71098fa 100644 --- a/frontend/src/components/OrganizationForm/OrganizationForm.tsx +++ b/frontend/src/components/OrganizationForm/OrganizationForm.tsx @@ -110,7 +110,7 @@ export const OrganizationForm: React.FC<{ fullWidth > - Create new {parent ? 'Team' : 'Organization'} + Create New {parent ? 'Team' : 'Organization'} Organization Name @@ -190,9 +190,10 @@ export const OrganizationForm: React.FC<{ ))} {/* TODO: Fix Tag selection issues. */} -
- -
+ Tags + + Select an existing tag or add a new one. + {chosenTags && chosenTags.length > 0 && @@ -211,7 +212,6 @@ export const OrganizationForm: React.FC<{ > ))} - Select an existing tag or add a new one. -

-

Date: Mon, 4 Mar 2024 12:15:07 -0500 Subject: [PATCH 5/8] Fix linting issue --- frontend/src/components/OrganizationForm/OrganizationForm.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/components/OrganizationForm/OrganizationForm.tsx b/frontend/src/components/OrganizationForm/OrganizationForm.tsx index 7f71098fa..168f90dce 100644 --- a/frontend/src/components/OrganizationForm/OrganizationForm.tsx +++ b/frontend/src/components/OrganizationForm/OrganizationForm.tsx @@ -3,7 +3,6 @@ import * as orgFormStyles from './orgFormStyle'; import { Organization, OrganizationTag } from 'types'; import { Autocomplete, - Box, Button, Chip, createFilterOptions, From 9c27a3ef352178f88ac678e436d1e70a046a15c9 Mon Sep 17 00:00:00 2001 From: Amelia Vance Date: Mon, 4 Mar 2024 12:24:15 -0500 Subject: [PATCH 6/8] Remove unused field in types/organiation.ts --- frontend/src/types/organization.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/types/organization.ts b/frontend/src/types/organization.ts index d4aded988..396113de9 100644 --- a/frontend/src/types/organization.ts +++ b/frontend/src/types/organization.ts @@ -39,5 +39,4 @@ export interface OrganizationTag { tags: OrganizationTag[]; organizations: Organization[]; scans: Scan[]; - state: string; } From b14b5aa038e68361807b8c4be960ba2b30a3d657 Mon Sep 17 00:00:00 2001 From: Amelia Vance Date: Mon, 4 Mar 2024 12:29:34 -0500 Subject: [PATCH 7/8] Remove unused queryByText in header.spec.tsx --- frontend/src/components/__tests__/header.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/__tests__/header.spec.tsx b/frontend/src/components/__tests__/header.spec.tsx index c5c30ff4f..335595605 100644 --- a/frontend/src/components/__tests__/header.spec.tsx +++ b/frontend/src/components/__tests__/header.spec.tsx @@ -88,7 +88,7 @@ describe('Header component', () => { }); it('shows correct links for GLOBAL_ADMIN', () => { - const { getByText, queryByText } = render(
, { + const { getByText } = render(
, { authContext: { user: { ...testUser, userType: 'globalAdmin', isRegistered: true }, currentOrganization: { ...testOrganization } From 73d45bf60d6434f16ab421d597e7856326dc94f5 Mon Sep 17 00:00:00 2001 From: "Grayson, Matthew" Date: Mon, 4 Mar 2024 13:36:49 -0600 Subject: [PATCH 8/8] Update create organization endpoint to populate state and region. --- backend/src/api/organizations.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/api/organizations.ts b/backend/src/api/organizations.ts index cbae68f2e..371a81299 100644 --- a/backend/src/api/organizations.ts +++ b/backend/src/api/organizations.ts @@ -339,16 +339,17 @@ export const update = wrapHandler(async (event) => { */ export const create = wrapHandler(async (event) => { if (!isGlobalWriteAdmin(event)) return Unauthorized; - const body = await validateBody(NewOrganization, event.body); + const body = await validateBody(NewOrUpdatedOrganization, event.body); await connectToDatabase(); if ('tags' in body) { body.tags = await findOrCreateTags(body.tags); } - const organization = await Organization.create({ + const organization = Organization.create({ ...body, createdBy: { id: event.requestContext.authorizer!.id }, - parent: { id: body.parent } + parent: { id: body.parent }, + regionId: REGION_STATE_MAP[body.stateName!] ?? null }); const res = await organization.save(); return {