-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1831 from TryQuiet/feature/119
feature/Registered usernames that are duplicates or invalid should trigger aggressive warning modal
- Loading branch information
Showing
22 changed files
with
979 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
...s/widgets/possibleImpersonationAttackModal/PossibleImpersonationAttackModal.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import React from 'react' | ||
import Modal from '../../ui/Modal/Modal' | ||
import { Button, Grid, Typography } from '@mui/material' | ||
import { styled } from '@mui/material/styles' | ||
import WarnIcon from '../../../static/images/exclamationMark.svg' | ||
|
||
const PREFIX = 'PossibleImpersonationAttackModalComponent-' | ||
|
||
const classes = { | ||
bodyText: `${PREFIX}bodyText`, | ||
button: `${PREFIX}button`, | ||
image: `${PREFIX}image`, | ||
} | ||
|
||
const StyledGrid = styled(Grid)(({ theme }) => ({ | ||
[`& .${classes.bodyText}`]: { | ||
textAlign: 'center', | ||
width: '65%', | ||
margin: '24px 0 4px', | ||
}, | ||
[`& .${classes.image}`]: { | ||
width: '70px', | ||
height: '70px', | ||
margin: '30px 0 24px', | ||
}, | ||
[`& .${classes.button}`]: { | ||
marginTop: 16, | ||
textTransform: 'none', | ||
padding: '0 24px', | ||
height: 40, | ||
borderRadius: '8px', | ||
color: theme.palette.colors.white, | ||
backgroundColor: theme.palette.colors.quietBlue, | ||
'&:hover': { | ||
opacity: 0.7, | ||
backgroundColor: theme.palette.colors.quietBlue, | ||
}, | ||
}, | ||
})) | ||
|
||
export interface PossibleImpersonationAttackModalComponentProps { | ||
communityName: string | ||
leaveCommunity: () => void | ||
open: boolean | ||
handleClose: () => void | ||
} | ||
|
||
const PossibleImpersonationAttackModalComponent: React.FC<PossibleImpersonationAttackModalComponentProps> = ({ | ||
communityName, | ||
leaveCommunity, | ||
handleClose, | ||
open, | ||
}) => { | ||
return ( | ||
<Modal open={open} handleClose={handleClose} title={'Warning!'} isBold addBorder> | ||
<StyledGrid | ||
container | ||
item | ||
direction='column' | ||
justifyContent='flex-start' | ||
alignItems='center' | ||
data-testid={'possible-impersonation-attack-modal-component'} | ||
> | ||
<img className={classes.image} src={WarnIcon} /> | ||
<Typography variant='h4'>Possible impersonation attack</Typography> | ||
<Typography className={classes.bodyText} variant='body2'> | ||
The owner of <strong>{communityName}</strong> has registered an invalid username. Either something is very | ||
broken, the community owner is trying to impersonate other users, or the community owner has been hacked. | ||
<br /> | ||
<strong>This should never happen and we recommend leaving this community immediately!</strong> | ||
</Typography> | ||
<Button className={classes.button} data-testid='unregistered-button' onClick={leaveCommunity}> | ||
Leave community | ||
</Button> | ||
</StyledGrid> | ||
</Modal> | ||
) | ||
} | ||
|
||
export default PossibleImpersonationAttackModalComponent |
41 changes: 41 additions & 0 deletions
41
...s/widgets/possibleImpersonationAttackModal/PossibleImpersonationAttackModal.container.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { capitalizeFirstLetter } from '@quiet/common' | ||
import { communities, users } from '@quiet/state-manager' | ||
import React, { useEffect } from 'react' | ||
import { useSelector } from 'react-redux' | ||
import { clearCommunity } from '../../..' | ||
import { useModal } from '../../../containers/hooks' | ||
import { ModalName } from '../../../sagas/modals/modals.types' | ||
import PossibleImpersonationAttackModalComponent from './PossibleImpersonationAttackModal.component' | ||
|
||
const PossibleImpersonationAttackModalContainer = () => { | ||
const possibleImpersonationAttackModal = useModal(ModalName.possibleImpersonationAttackModal) | ||
|
||
const community = useSelector(communities.selectors.currentCommunity) | ||
const duplicateCerts = useSelector(users.selectors.duplicateCerts) | ||
|
||
let communityName = '...' | ||
|
||
if (community?.name) { | ||
communityName = capitalizeFirstLetter(community.name) | ||
} | ||
|
||
const leaveCommunity = async () => { | ||
await clearCommunity() | ||
} | ||
|
||
useEffect(() => { | ||
if (duplicateCerts) { | ||
possibleImpersonationAttackModal.handleOpen() | ||
} | ||
}, [duplicateCerts]) | ||
|
||
return ( | ||
<PossibleImpersonationAttackModalComponent | ||
communityName={communityName} | ||
leaveCommunity={leaveCommunity} | ||
{...possibleImpersonationAttackModal} | ||
/> | ||
) | ||
} | ||
|
||
export default PossibleImpersonationAttackModalContainer |
33 changes: 33 additions & 0 deletions
33
...nts/widgets/possibleImpersonationAttackModal/PossibleImpersonationAttackModal.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import React from 'react' | ||
import { ComponentStory, ComponentMeta } from '@storybook/react' | ||
import { withTheme } from '../../../storybook/decorators' | ||
import PossibleImpersonationAttackModalComponent, { | ||
PossibleImpersonationAttackModalComponentProps, | ||
} from './PossibleImpersonationAttackModal.component' | ||
|
||
const Template: ComponentStory<typeof PossibleImpersonationAttackModalComponent> = args => { | ||
return ( | ||
<div style={{ height: '800px', position: 'relative' }}> | ||
<PossibleImpersonationAttackModalComponent {...args} /> | ||
</div> | ||
) | ||
} | ||
|
||
export const Component = Template.bind({}) | ||
|
||
const args: PossibleImpersonationAttackModalComponentProps = { | ||
handleClose: function (): void {}, | ||
open: true, | ||
communityName: 'devteam', | ||
leaveCommunity: function (): void {}, | ||
} | ||
|
||
Component.args = args | ||
|
||
const component: ComponentMeta<typeof PossibleImpersonationAttackModalComponent> = { | ||
title: 'Components/PossibleImpersonationAttackModalComponent', | ||
decorators: [withTheme], | ||
component: PossibleImpersonationAttackModalComponent, | ||
} | ||
|
||
export default component |
147 changes: 147 additions & 0 deletions
147
...onents/widgets/possibleImpersonationAttackModal/PossibleImpersonationAttackModal.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import React from 'react' | ||
import theme from '../../../theme' | ||
import { ThemeProvider } from '@mui/material/styles' | ||
import { renderComponent } from '../../../testUtils/renderComponent' | ||
import PossibleImpersonationAttackModalComponent from './PossibleImpersonationAttackModal.component' | ||
|
||
describe('PossibleImpersonationAttackModal', () => { | ||
it('renderComponent', () => { | ||
const result = renderComponent( | ||
<ThemeProvider theme={theme}> | ||
<PossibleImpersonationAttackModalComponent | ||
handleClose={() => {}} | ||
open={true} | ||
communityName={'devteam'} | ||
leaveCommunity={() => {}} | ||
/> | ||
</ThemeProvider> | ||
) | ||
expect(result.baseElement).toMatchInlineSnapshot(` | ||
<body | ||
style="padding-right: 1024px; overflow: hidden;" | ||
> | ||
<div | ||
aria-hidden="true" | ||
/> | ||
<div | ||
class="MuiModal-root css-1vjugmr-MuiModal-root" | ||
role="presentation" | ||
zindex="1300" | ||
> | ||
<div | ||
aria-hidden="true" | ||
class="MuiBackdrop-root css-i9fmh8-MuiBackdrop-root-MuiModal-backdrop" | ||
style="opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;" | ||
/> | ||
<div | ||
data-testid="sentinelStart" | ||
tabindex="0" | ||
/> | ||
<div | ||
class="MuiGrid-root MuiGrid-container MuiGrid-direction-xs-column Modalcentered css-6gh8l0-MuiGrid-root" | ||
tabindex="-1" | ||
> | ||
<div | ||
class="MuiGrid-root MuiGrid-container MuiGrid-item Modalheader ModalheaderBorder css-lx31tv-MuiGrid-root" | ||
> | ||
<div | ||
class="MuiGrid-root MuiGrid-container MuiGrid-item MuiGrid-grid-xs-true css-1r61agb-MuiGrid-root" | ||
> | ||
<div | ||
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-true css-1vd824g-MuiGrid-root" | ||
> | ||
<h6 | ||
class="MuiTypography-root MuiTypography-subtitle1 MuiTypography-alignCenter Modaltitle Modalbold css-jxzupi-MuiTypography-root" | ||
style="margin-left: 36px;" | ||
> | ||
Warning! | ||
</h6> | ||
</div> | ||
<div | ||
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root" | ||
> | ||
<div | ||
class="MuiGrid-root MuiGrid-container MuiGrid-item Modalactions css-hoc6b0-MuiGrid-root" | ||
data-testid="ModalActions" | ||
> | ||
<button | ||
class="MuiButtonBase-root MuiIconButton-root IconButtonroot MuiIconButton-sizeMedium css-c8hoqc-MuiButtonBase-root-MuiIconButton-root" | ||
tabindex="0" | ||
type="button" | ||
> | ||
<svg | ||
aria-hidden="true" | ||
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root" | ||
data-testid="ClearIcon" | ||
focusable="false" | ||
viewBox="0 0 24 24" | ||
> | ||
<path | ||
d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" | ||
/> | ||
</svg> | ||
<span | ||
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root" | ||
/> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div | ||
class="MuiGrid-root MuiGrid-container MuiGrid-item ModalfullPage css-1h16bbz-MuiGrid-root" | ||
> | ||
<div | ||
class="MuiGrid-root MuiGrid-container MuiGrid-item Modalcontent css-1f064cs-MuiGrid-root" | ||
style="width: 600px;" | ||
> | ||
<div | ||
class="MuiGrid-root MuiGrid-container MuiGrid-item MuiGrid-direction-xs-column css-e4g1qd-MuiGrid-root" | ||
data-testid="possible-impersonation-attack-modal-component" | ||
> | ||
<img | ||
class="PossibleImpersonationAttackModalComponent-image" | ||
src="test-file-stub" | ||
/> | ||
<h4 | ||
class="MuiTypography-root MuiTypography-h4 css-ajdqea-MuiTypography-root" | ||
> | ||
Possible impersonation attack | ||
</h4> | ||
<p | ||
class="MuiTypography-root MuiTypography-body2 PossibleImpersonationAttackModalComponent-bodyText css-16d47hw-MuiTypography-root" | ||
> | ||
The owner of | ||
<strong> | ||
devteam | ||
</strong> | ||
has registered an invalid username. Either something is very broken, the community owner is trying to impersonate other users, or the community owner has been hacked. | ||
<br /> | ||
<strong> | ||
This should never happen and we recommend leaving this community immediately! | ||
</strong> | ||
</p> | ||
<button | ||
class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeMedium MuiButton-textSizeMedium MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeMedium MuiButton-textSizeMedium PossibleImpersonationAttackModalComponent-button css-1skytee-MuiButtonBase-root-MuiButton-root" | ||
data-testid="unregistered-button" | ||
tabindex="0" | ||
type="button" | ||
> | ||
Leave community | ||
<span | ||
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root" | ||
/> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div | ||
data-testid="sentinelEnd" | ||
tabindex="0" | ||
/> | ||
</div> | ||
</body> | ||
`) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.