(Feature) - #1991 Prevent that a Safe adds itself as an owner (#2026)

* Uses addressIsNotSafe on replaceOwner modal and addNewOwnerModal

* Update method name from addressIsNotSafe to addressIsNotCurrentSafe
This commit is contained in:
Agustin Pane 2021-03-16 06:42:42 -03:00 committed by GitHub
parent 61125fb937
commit 8f16c4f18d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 6 deletions

View File

@ -10,6 +10,8 @@ import {
uniqueAddress, uniqueAddress,
differentFrom, differentFrom,
ADDRESS_REPEATED_ERROR, ADDRESS_REPEATED_ERROR,
addressIsNotCurrentSafe,
OWNER_ADDRESS_IS_SAFE_ADDRESS_ERROR,
} from 'src/components/forms/validator' } from 'src/components/forms/validator'
describe('Forms > Validators', () => { describe('Forms > Validators', () => {
@ -179,6 +181,22 @@ describe('Forms > Validators', () => {
}) })
}) })
describe('addressIsNotSafe validator', () => {
it('Returns undefined if the given `address` it not the given `safeAddress`', async () => {
const address = '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
const safeAddress = '0x2D6F2B448b0F711Eb81f2929566504117d67E44F'
expect(addressIsNotCurrentSafe(safeAddress)(address)).toBeUndefined()
})
it('Returns an error message if the given `address` is the same as the `safeAddress`', async () => {
const address = '0x2D6F2B448b0F711Eb81f2929566504117d67E44F'
const safeAddress = '0x2D6F2B448b0F711Eb81f2929566504117d67E44F'
expect(addressIsNotCurrentSafe(safeAddress)(address)).toEqual(OWNER_ADDRESS_IS_SAFE_ADDRESS_ERROR)
})
})
describe('differentFrom validator', () => { describe('differentFrom validator', () => {
const getDifferentFromErrMsg = (diffValue: string): string => `Value should be different than ${diffValue}` const getDifferentFromErrMsg = (diffValue: string): string => `Value should be different than ${diffValue}`

View File

@ -92,12 +92,16 @@ export const minMaxLength = (minLen: number, maxLen: number) => (value: string):
value.length >= +minLen && value.length <= +maxLen ? undefined : `Should be ${minLen} to ${maxLen} symbols` value.length >= +minLen && value.length <= +maxLen ? undefined : `Should be ${minLen} to ${maxLen} symbols`
export const ADDRESS_REPEATED_ERROR = 'Address already introduced' export const ADDRESS_REPEATED_ERROR = 'Address already introduced'
export const OWNER_ADDRESS_IS_SAFE_ADDRESS_ERROR = 'Cannot use Safe itself as owner.'
export const uniqueAddress = (addresses: string[] | List<string> = []) => (address?: string): string | undefined => { export const uniqueAddress = (addresses: string[] | List<string> = []) => (address?: string): string | undefined => {
const addressExists = addresses.some((addressFromList) => sameAddress(addressFromList, address)) const addressExists = addresses.some((addressFromList) => sameAddress(addressFromList, address))
return addressExists ? ADDRESS_REPEATED_ERROR : undefined return addressExists ? ADDRESS_REPEATED_ERROR : undefined
} }
export const addressIsNotCurrentSafe = (safeAddress: string) => (address?: string): string | undefined =>
sameAddress(safeAddress, address) ? OWNER_ADDRESS_IS_SAFE_ADDRESS_ERROR : undefined
export const composeValidators = (...validators: Validator[]) => (value: unknown): ValidatorReturnType => export const composeValidators = (...validators: Validator[]) => (value: unknown): ValidatorReturnType =>
validators.reduce( validators.reduce(
(error: string | undefined, validator: GenericValidatorType): ValidatorReturnType => error || validator(value), (error: string | undefined, validator: GenericValidatorType): ValidatorReturnType => error || validator(value),

View File

@ -11,14 +11,20 @@ import AddressInput from 'src/components/forms/AddressInput'
import Field from 'src/components/forms/Field' import Field from 'src/components/forms/Field'
import GnoForm from 'src/components/forms/GnoForm' import GnoForm from 'src/components/forms/GnoForm'
import TextField from 'src/components/forms/TextField' import TextField from 'src/components/forms/TextField'
import { composeValidators, minMaxLength, required, uniqueAddress } from 'src/components/forms/validator' import {
addressIsNotCurrentSafe,
composeValidators,
minMaxLength,
required,
uniqueAddress,
} from 'src/components/forms/validator'
import Block from 'src/components/layout/Block' import Block from 'src/components/layout/Block'
import Button from 'src/components/layout/Button' import Button from 'src/components/layout/Button'
import Col from 'src/components/layout/Col' import Col from 'src/components/layout/Col'
import Hairline from 'src/components/layout/Hairline' import Hairline from 'src/components/layout/Hairline'
import Paragraph from 'src/components/layout/Paragraph' import Paragraph from 'src/components/layout/Paragraph'
import Row from 'src/components/layout/Row' import Row from 'src/components/layout/Row'
import { safeOwnersAddressesListSelector } from 'src/logic/safe/store/selectors' import { safeOwnersAddressesListSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
export const ADD_OWNER_NAME_INPUT_TEST_ID = 'add-owner-name-input' export const ADD_OWNER_NAME_INPUT_TEST_ID = 'add-owner-name-input'
export const ADD_OWNER_ADDRESS_INPUT_TEST_ID = 'add-owner-address-testid' export const ADD_OWNER_ADDRESS_INPUT_TEST_ID = 'add-owner-address-testid'
@ -43,7 +49,9 @@ export const OwnerForm = ({ onClose, onSubmit }: OwnerFormProps): React.ReactEle
onSubmit(values) onSubmit(values)
} }
const owners = useSelector(safeOwnersAddressesListSelector) const owners = useSelector(safeOwnersAddressesListSelector)
const safeAddress = useSelector(safeParamAddressFromStateSelector)
const ownerDoesntExist = uniqueAddress(owners) const ownerDoesntExist = uniqueAddress(owners)
const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
return ( return (
<> <>
@ -98,7 +106,7 @@ export const OwnerForm = ({ onClose, onSubmit }: OwnerFormProps): React.ReactEle
placeholder="Owner address*" placeholder="Owner address*"
testId={ADD_OWNER_ADDRESS_INPUT_TEST_ID} testId={ADD_OWNER_ADDRESS_INPUT_TEST_ID}
text="Owner address*" text="Owner address*"
validators={[ownerDoesntExist]} validators={[ownerDoesntExist, ownerAddressIsNotSafeAddress]}
/> />
</Col> </Col>
<Col center="xs" className={classes} middle="xs" xs={1}> <Col center="xs" className={classes} middle="xs" xs={1}>

View File

@ -10,7 +10,13 @@ import AddressInput from 'src/components/forms/AddressInput'
import Field from 'src/components/forms/Field' import Field from 'src/components/forms/Field'
import GnoForm from 'src/components/forms/GnoForm' import GnoForm from 'src/components/forms/GnoForm'
import TextField from 'src/components/forms/TextField' import TextField from 'src/components/forms/TextField'
import { composeValidators, minMaxLength, required, uniqueAddress } from 'src/components/forms/validator' import {
addressIsNotCurrentSafe,
composeValidators,
minMaxLength,
required,
uniqueAddress,
} from 'src/components/forms/validator'
import Identicon from 'src/components/Identicon' import Identicon from 'src/components/Identicon'
import Block from 'src/components/layout/Block' import Block from 'src/components/layout/Block'
import Button from 'src/components/layout/Button' import Button from 'src/components/layout/Button'
@ -19,7 +25,7 @@ import Hairline from 'src/components/layout/Hairline'
import Paragraph from 'src/components/layout/Paragraph' import Paragraph from 'src/components/layout/Paragraph'
import Row from 'src/components/layout/Row' import Row from 'src/components/layout/Row'
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
import { safeOwnersAddressesListSelector } from 'src/logic/safe/store/selectors' import { safeOwnersAddressesListSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
import { styles } from './style' import { styles } from './style'
import { getExplorerInfo } from 'src/config' import { getExplorerInfo } from 'src/config'
@ -40,7 +46,9 @@ const OwnerForm = ({ classes, onClose, onSubmit, ownerAddress, ownerName }) => {
onSubmit(values) onSubmit(values)
} }
const owners = useSelector(safeOwnersAddressesListSelector) const owners = useSelector(safeOwnersAddressesListSelector)
const safeAddress = useSelector(safeParamAddressFromStateSelector)
const ownerDoesntExist = uniqueAddress(owners) const ownerDoesntExist = uniqueAddress(owners)
const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
return ( return (
<> <>
@ -126,7 +134,7 @@ const OwnerForm = ({ classes, onClose, onSubmit, ownerAddress, ownerName }) => {
placeholder="Owner address*" placeholder="Owner address*"
testId={REPLACE_OWNER_ADDRESS_INPUT_TEST_ID} testId={REPLACE_OWNER_ADDRESS_INPUT_TEST_ID}
text="Owner address*" text="Owner address*"
validators={[ownerDoesntExist]} validators={[ownerDoesntExist, ownerAddressIsNotSafeAddress]}
/> />
</Col> </Col>
<Col center="xs" className={classes} middle="xs" xs={1}> <Col center="xs" className={classes} middle="xs" xs={1}>