Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security UI Fixes #233

Merged
merged 8 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions app/src/components/security/SecuritiesDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ const SecuritiesDialog = (props: ISecuritiesDialogProps) => {
dialogContext.setSnackbar({
snackbarMessage: (
<Typography variant="body2" component="div">
{ApplySecurityRulesI18N.applySecuritySuccess(
patch.stagedForApply.length,
patch.stagedForRemove.length,
props.submissionFeatureIds.length
)}
{ApplySecurityRulesI18N.applySecuritySuccess(props.submissionFeatureIds.length)}
</Typography>
),
open: true
Expand All @@ -61,7 +57,7 @@ const SecuritiesDialog = (props: ISecuritiesDialogProps) => {
return (
<EditDialog<IPatchFeatureSecurityRules>
isLoading={isLoading}
dialogTitle={hasSecurity ? 'Edit Security Reasons' : ' Add Security Reasons'}
dialogTitle={hasSecurity ? 'Edit Security' : ' Add Security'}
open={props.open}
dialogSaveButtonLabel="APPLY"
onCancel={props.onClose}
Expand Down
13 changes: 10 additions & 3 deletions app/src/components/security/SecurityRuleActionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
variant="outlined"
sx={{
display: 'flex',
px: 2,
py: 1.5,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
p: 2,
background: grey[100]
}}>
<SecurityRuleCard {...rest} />
Expand All @@ -30,7 +29,15 @@
<Icon path={mdiClose} size={1} />
</IconButton>
) : (
<Button variant={props.action === 'remove' ? 'contained' : 'outlined'} color="error" onClick={() => onRemove()}>
<Button
variant={props.action === 'remove' ? 'contained' : 'outlined'}
color="error"
sx={{
width: '6rem',
fontWeight: 700,
letterSpacing: '0.02rem'
}}
onClick={() => onRemove()}>

Check warning on line 40 in app/src/components/security/SecurityRuleActionCard.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleActionCard.tsx#L40

Added line #L40 was not covered by tests
Remove
</Button>
)}
Expand Down
67 changes: 34 additions & 33 deletions app/src/components/security/SecurityRuleCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box, Typography } from '@mui/material';
import { Stack } from '@mui/system';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';

export interface ISecurityRuleCardProps {
key?: string | number;
Expand All @@ -11,46 +11,47 @@

const SecurityRuleCard = (props: ISecurityRuleCardProps) => {
return (
<Box>
<Typography variant="body2" color="textSecondary">
<Stack gap={0.75} mt={-0.25}>
<Typography variant="body2" component="div" color="textSecondary" textTransform="uppercase">
{props.category}
</Typography>
<Typography
variant="body1"
fontWeight={700}
gutterBottom
sx={{
display: '-webkit-box',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
{props.title}
</Typography>
<Typography
variant="body2"
color="textSecondary"
sx={{
display: '-webkit-box',
maxWidth: '92ch',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
{props.description}
</Typography>
<Stack>
<Typography
variant="body1"
fontWeight={700}
sx={{
display: '-webkit-box',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
{props.title}
</Typography>
<Typography
variant="body1"
color="textSecondary"
sx={{
display: '-webkit-box',
maxWidth: '92ch',
WebkitLineClamp: '2',
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}>
{props.description}
</Typography>
</Stack>
{props.featureMembers && props.featureMembers?.length && (
<Stack component="ul" mt={1} pl={0} mb={0} display="flex" flexDirection="row" gap={2}>
<Stack component="ul" flexDirection="row" gap={2} mt={0.75} mb={0} p={0}>
{props.featureMembers.map((featureMember) => (
<Typography variant="body2" color="textSecondary" sx={{ display: 'block' }} component="li">
<Typography component="li" variant="body2" color="textSecondary" fontWeight={700} sx={{ display: 'block' }}>

Check warning on line 48 in app/src/components/security/SecurityRuleCard.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleCard.tsx#L48

Added line #L48 was not covered by tests
{featureMember}
</Typography>
))}
</Stack>
)}
</Box>
</Stack>
);
};

Expand Down
114 changes: 57 additions & 57 deletions app/src/components/security/SecurityRuleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
return ruleGroups;
}, [])
);
}, [initialAppliedSecurityRules, submissionFeatureGroupsDataLoader.data]);

Check warning on line 100 in app/src/components/security/SecurityRuleForm.tsx

View workflow job for this annotation

GitHub Actions / Running Linter and Formatter

React Hook useMemo has missing dependencies: 'allSecurityRules' and 'formikProps.initialValues.submissionFeatureIds'. Either include them or remove the dependency array

const toggleStageApply = (securityRule: ISecurityRuleAndCategory) => {
if (
Expand Down Expand Up @@ -144,13 +144,11 @@
sx={{
maxWidth: '72ch'
}}>
Specify reasons why this information should be secured.
Manage security rules for features in this submission.
</Typography>

<Box mt={3}>
<Box mb={2}>
<Typography component="legend">Add Security Rules</Typography>
</Box>
<Box component="fieldset" mt={3}>
<Typography component="legend">Add Security Rules</Typography>
<Autocomplete
value={null}
id={'autocomplete-security-rule-search'}
Expand Down Expand Up @@ -209,10 +207,11 @@
renderOption={(renderProps, renderOption) => {
return (
<ListItem
disablePadding
divider
sx={{
px: 2,
py: '12px !important'
py: '12px !important',
px: 2
}}
{...renderProps}>
<SecurityRuleCard
Expand All @@ -224,61 +223,62 @@
);
}}
/>
<Stack component={TransitionGroup} gap={1} my={1}>
{formikProps.values.stagedForApply.map((applyingRule) => {
return (

Check warning on line 228 in app/src/components/security/SecurityRuleForm.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleForm.tsx#L228

Added line #L228 was not covered by tests
<Collapse key={applyingRule.security_rule_id}>
<SecurityRuleActionCard
action={'apply'}
title={applyingRule.name}
category={applyingRule.category_name}
description={applyingRule.description}
onRemove={() => toggleStageApply(applyingRule)}

Check warning on line 235 in app/src/components/security/SecurityRuleForm.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleForm.tsx#L235

Added line #L235 was not covered by tests
/>
</Collapse>
);
})}
</Stack>
</Box>

<Stack component={TransitionGroup} gap={1} my={1}>
{formikProps.values.stagedForApply.map((applyingRule) => {
return (
<Collapse key={applyingRule.security_rule_id}>
<SecurityRuleActionCard
action={'apply'}
title={applyingRule.name}
category={applyingRule.category_name}
description={applyingRule.description}
onRemove={() => toggleStageApply(applyingRule)}
/>
</Collapse>
);
})}
</Stack>

<Box my={2}>
<Box component="fieldset" mt={3}>
<Typography component="legend">Manage Existing Security</Typography>
<Typography variant="body2">
These rules have already been applied to one or more of the selected features.
<Typography variant="body1" color="textSecondary" sx={{ mt: -0.5 }}>
Manage security rules have already been applied.
curtisupshall marked this conversation as resolved.
Show resolved Hide resolved
</Typography>
</Box>
<Stack component={TransitionGroup} gap={1}>
{groupedAppliedSecurityRules.map((group: IAppliedSecurityRuleGroup) => {
const cardAction = formikProps.values.stagedForRemove.some(
(removingRule) => removingRule.security_rule_id === group.securityRule.security_rule_id
)
? 'remove'
: 'persist';

return (
<Collapse key={group.securityRule.security_rule_id}>
<SecurityRuleActionCard
action={cardAction}
title={group.securityRule.name}
category={group.securityRule.category_name}
description={group.securityRule.description}
featureMembers={group.appliedFeatureGroups.map(
(featureGroup) =>
`${p(featureGroup.numFeatures, featureGroup.displayName)} (${featureGroup.numFeatures})`
)}
onRemove={() => toggleStageRemove(group.securityRule)}
/>
</Collapse>
);
})}
</Stack>
{hasNoSecuritySelected && (
<Alert severity="error" sx={{ marginTop: 1 }}>
<AlertTitle>Open access to all records</AlertTitle>
All users will have unrestricted access to records that have been included in this submission.
</Alert>
)}
<Stack component={TransitionGroup} gap={1} mt={3}>
{groupedAppliedSecurityRules.map((group: IAppliedSecurityRuleGroup) => {
const cardAction = formikProps.values.stagedForRemove.some(
(removingRule) => removingRule.security_rule_id === group.securityRule.security_rule_id

Check warning on line 252 in app/src/components/security/SecurityRuleForm.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleForm.tsx#L252

Added line #L252 was not covered by tests
)
? 'remove'
: 'persist';

return (

Check warning on line 257 in app/src/components/security/SecurityRuleForm.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleForm.tsx#L257

Added line #L257 was not covered by tests
<Collapse key={group.securityRule.security_rule_id}>
<SecurityRuleActionCard
action={cardAction}
title={group.securityRule.name}
category={group.securityRule.category_name}
description={group.securityRule.description}
featureMembers={group.appliedFeatureGroups.map(
(featureGroup) =>
`${p(featureGroup.numFeatures, featureGroup.displayName)} (${featureGroup.numFeatures})`

Check warning on line 266 in app/src/components/security/SecurityRuleForm.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleForm.tsx#L266

Added line #L266 was not covered by tests
)}
onRemove={() => toggleStageRemove(group.securityRule)}

Check warning on line 268 in app/src/components/security/SecurityRuleForm.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/components/security/SecurityRuleForm.tsx#L268

Added line #L268 was not covered by tests
/>
</Collapse>
);
})}
</Stack>

{hasNoSecuritySelected && (
<Alert severity="error">
<AlertTitle>No security applied</AlertTitle>
All users will have unrestricted access to records that have been included in this submission.
</Alert>
)}
</Box>
</Box>
</form>
);
Expand Down
15 changes: 4 additions & 11 deletions app/src/constants/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,15 @@ export const DeleteSystemUserI18N = {
};

export const ApplySecurityRulesI18N = {
applySecuritySuccess: (numApplied: number, numRemoved: number, featureCount: number) => {
const appliedRemoved = [
numApplied > 0 && `applied ${numApplied} ${p(numApplied, 'security rule')}`,
numRemoved > 0 && `removed ${numRemoved} ${p(numRemoved, 'security rule')}`
]
.filter(Boolean)
.join(' and ');

return `Successfully ${appliedRemoved} for ${featureCount} ${p(featureCount, 'feature')}.`;
applySecuritySuccess: (featureCount: number) => {
return `Updated security for ${featureCount} ${p(featureCount, 'feature')}.`;
},

applySecurityRulesErrorTitle: 'Error Applying Security',
applySecurityRulesErrorTitle: 'Error applying security rules',
applySecurityRulesErrorText:
'An error occurred while applying security to features, please try again. If the problem persists, please contact your system administrator',
unApplySecurityRulesSuccess: (submissionCount: number) => `Successfully unsecured: ${submissionCount} features`,
unapplySecurityRulesErrorTitle: 'Error Unsecuring Features',
unapplySecurityRulesErrorTitle: 'Error unsecuring features',
unapplySecurityRulesErrorText:
'Failed to unsecure the selected features, please try again. If the problem persists, please contact your system administrator'
};
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ export const SubmissionDataGrid = (props: ISubmissionDataGridProps) => {
alignItems="center"
gap={1}
sx={{
color: 'text.secondary'
color: 'error.main'
}}>
<Icon path={mdiLockOpenOutline} size={0.75} />
<Typography component="span" sx={{ textTransform: 'uppercase' }}>
Unsecured
<Typography component="span" textTransform="uppercase">
Unsecuredasdfasdfsd
curtisupshall marked this conversation as resolved.
Show resolved Hide resolved
</Typography>
</Stack>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,18 @@ const useSubmissionDataGridColumns = (featureTypeName: string): GridColDef[] =>
renderCell: (params) => {
if (params.value.length > 0) {
return (
<Stack flexDirection="row" alignItems="center" gap={1}>
<Stack flexDirection="row" alignItems="center" gap={1} color="error.main">
<Icon path={mdiLock} size={0.75} />
<Typography component="span" sx={{ textTransform: 'uppercase' }}>
<Typography variant="body2" component="span" fontWeight={700} textTransform="uppercase">
Secured
</Typography>
</Stack>
);
}
return (
<Stack
flexDirection="row"
alignItems="center"
gap={1}
sx={{
color: 'text.secondary'
}}>
<Stack flexDirection="row" alignItems="center" gap={1} color="error.main">
<Icon path={mdiLockOpenOutline} size={0.75} />
<Typography component="span" sx={{ textTransform: 'uppercase' }}>
<Typography variant="body2" component="span" fontWeight={700} textTransform="uppercase">
Unsecured
</Typography>
</Stack>
Expand Down
Loading