more validation work

This commit is contained in:
fmtabbara
2021-09-02 10:10:18 +01:00
parent f043639ad2
commit bd7d788741
5 changed files with 181 additions and 53 deletions
@@ -41,7 +41,7 @@ export const BalanceCard = () => {
{balanceError}
</Alert>
) : (
<Typography>{balance?.printableBalance}</Typography>
<Typography>{balance?.printable_balance}</Typography>
)}
</div>
</CardContent>
+85 -51
View File
@@ -11,15 +11,9 @@ import {
import { useTheme } from '@material-ui/styles'
import { useForm } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import * as Yup from 'yup'
import { EnumNodeType } from '../../types/global'
import { NodeTypeSelector } from '../../components/NodeTypeSelector'
import {
isValidHostname,
validateAmount,
validateKey,
validateVersion,
} from '../../utils'
import { validationSchema } from './validationSchema'
type TBondNodeFormProps = {
// minimumBond: Coin
@@ -27,74 +21,80 @@ type TBondNodeFormProps = {
}
type TBondFormFields = {
nodeType: EnumNodeType
identityKey: string
sphinxKey: string
amount: string
host: string
version: string
location?: string
mixPort: number
verlocPort: number
clientsPort: number
httpApiPort: number
}
const validationSchema = Yup.object().shape({
identityKey: Yup.string()
.required('An indentity key is required')
.test('valid-id-key', 'A valid identity key is required', function (value) {
return validateKey(value || '')
}),
sphinxKey: Yup.string()
.required('A sphinx key is required')
.test(
'valid-sphinx-key',
'A valid sphinx key is required',
function (value) {
return validateKey(value || '')
}
),
amount: Yup.string()
.required('An amount is required')
.test(
'valid-amount',
'A valid amount is required (min 100 punks)',
function (value) {
return validateAmount(value || '', '100000000')
// minimum amount needs to come from the backend - replace when available
}
),
const defaultPorts = {
mixPort: 1789,
verlocPort: 1790,
httpApiPort: 8000,
clientsPort: 9000,
}
host: Yup.string()
.required('A host is required')
.test('valid-amount', 'A valid host is required', function (value) {
return !!value ? isValidHostname(value) : false
}),
version: Yup.string()
.required('A version is required')
.test('valid-version', 'A valid version is required', function (value) {
return !!value ? validateVersion(value) : false
}),
})
const defaultValues = {
nodeType: EnumNodeType.Mixnode,
identityKey: '',
sphinxKey: '',
amount: '',
host: '',
version: '',
location: undefined,
...defaultPorts,
}
export const BondNodeForm = () => {
const [advancedShown, setAdvancedShown] = React.useState(false)
const [nodeType, setNodeType] = useState(EnumNodeType.Mixnode)
const {
reset,
register,
handleSubmit,
setValue,
watch,
formState: { errors },
} = useForm<TBondFormFields>({ resolver: yupResolver(validationSchema) })
} = useForm<TBondFormFields>({
resolver: yupResolver(validationSchema),
defaultValues,
})
const theme: Theme = useTheme()
console.log(errors)
const watchNodeType = watch('nodeType', EnumNodeType.Mixnode)
const onSubmit = (data: TBondFormFields) => console.log(data)
const theme: Theme = useTheme()
return (
<form>
<div style={{ padding: theme.spacing(3, 5) }}>
<Grid container spacing={3}>
<Grid item xs={12}>
<NodeTypeSelector
nodeType={nodeType}
setNodeType={(nodeType) => setNodeType(nodeType)}
nodeType={watchNodeType}
setNodeType={(nodeType) => {
setValue('nodeType', nodeType)
// reset(
// {
// // location:
// // nodeType === EnumNodeType.Mixnode ? undefined : '',
// ...defaultPorts,
// },
// {
// keepErrors: true,
// keepDirty: true,
// keepValues: true,
// }
// )
}}
/>
</Grid>
<Grid item xs={12}>
@@ -158,14 +158,17 @@ export const BondNodeForm = () => {
{/* if it's a gateway - get location */}
<Grid item xs={6}>
{nodeType === EnumNodeType.Gateway && (
{watchNodeType === EnumNodeType.Gateway && (
<TextField
{...register('location')}
variant="outlined"
required
id="location"
name="location"
label="Location"
fullWidth
error={!!errors.location}
helperText={errors.location?.message}
/>
)}
</Grid>
@@ -191,6 +194,13 @@ export const BondNodeForm = () => {
checked={advancedShown}
onChange={() => {
setAdvancedShown((shown) => {
if (shown) {
reset(defaultPorts, {
keepErrors: true,
keepDirty: true,
keepValues: true,
})
}
return !shown
})
}}
@@ -204,43 +214,66 @@ export const BondNodeForm = () => {
<>
<Grid item xs={12} sm={4}>
<TextField
{...register('mixPort', { valueAsNumber: true })}
variant="outlined"
id="mixPort"
name="mixPort"
label="Mix Port"
fullWidth
error={!!errors.mixPort}
helperText={
errors.mixPort?.message && 'A valid port value is required'
}
/>
</Grid>
{nodeType === EnumNodeType.Mixnode ? (
{watchNodeType === EnumNodeType.Mixnode ? (
<>
<Grid item xs={12} sm={4}>
<TextField
{...register('verlocPort', { valueAsNumber: true })}
variant="outlined"
id="verlocPort"
name="verlocPort"
label="Verloc Port"
fullWidth
error={!!errors.verlocPort}
helperText={
errors.verlocPort?.message &&
'A valid port value is required'
}
/>
</Grid>
<Grid item xs={12} sm={4}>
<TextField
{...register('httpApiPort', { valueAsNumber: true })}
variant="outlined"
id="httpApiPort"
name="httpApiPort"
label="HTTP API Port"
fullWidth
error={!!errors.httpApiPort}
helperText={
errors.httpApiPort?.message &&
'A valid port value is required'
}
/>
</Grid>
</>
) : (
<Grid item xs={12} sm={4}>
<TextField
{...register('clientsPort', { valueAsNumber: true })}
variant="outlined"
id="clientsPort"
name="clientsPort"
label="client WS API Port"
fullWidth
error={!!errors.clientsPort}
helperText={
errors.clientsPort?.message &&
'A valid port value is required'
}
/>
</Grid>
)}
@@ -259,6 +292,7 @@ export const BondNodeForm = () => {
}}
>
<Button
disabled={Object.keys(errors).length > 0}
variant="contained"
color="primary"
type="submit"
@@ -0,0 +1,86 @@
import * as Yup from 'yup'
import {
isValidHostname,
validateAmount,
validateKey,
validateLocation,
validateRawPort,
validateVersion,
} from '../../utils'
export const validationSchema = Yup.object().shape({
identityKey: Yup.string()
.required('An indentity key is required')
.test('valid-id-key', 'A valid identity key is required', function (value) {
return validateKey(value || '')
}),
sphinxKey: Yup.string()
.required('A sphinx key is required')
.test(
'valid-sphinx-key',
'A valid sphinx key is required',
function (value) {
return validateKey(value || '')
}
),
amount: Yup.string()
.required('An amount is required')
.test(
'valid-amount',
'A valid amount is required (min 100 punks)',
function (value) {
return validateAmount(value || '', '100000000')
// minimum amount needs to come from the backend - replace when available
}
),
host: Yup.string()
.required('A host is required')
.test('valid-host', 'A valid host is required', function (value) {
return !!value ? isValidHostname(value) : false
}),
version: Yup.string()
.required('A version is required')
.test('valid-version', 'A valid version is required', function (value) {
return !!value ? validateVersion(value) : false
}),
location: Yup.lazy((value) => {
console.log('LOCATION = ' + value)
if (!!value) {
return Yup.string()
.required('A location is required')
.test(
'valid-location',
'A valid version is required',
function (value) {
return !!value ? validateLocation(value) : false
}
)
}
return Yup.mixed().notRequired()
}),
mixPort: Yup.number()
.required('A mixport is required')
.test('valid-mixport', 'A valid mixport is required', function (value) {
return !!value ? validateRawPort(value) : false
}),
verlocPort: Yup.number()
.required('A verloc port is required')
.test('valid-verloc', 'A valid verloc port is required', function (value) {
return !!value ? validateRawPort(value) : false
}),
httpApiPort: Yup.number()
.required('A http-api port is required')
.test('valid-http', 'A valid http-api port is required', function (value) {
return !!value ? validateRawPort(value) : false
}),
clientsPort: Yup.number()
.required('A clients port is required')
.test(
'valid-clients',
'A valid clients port is required',
function (value) {
return !!value ? validateRawPort(value) : false
}
),
})
+1 -1
View File
@@ -16,7 +16,7 @@ export type TNodeOwnership = {
export type TBalance = {
amount: string
demon: EnumDemon
printableBalance: string
printable_balance: string
}
export type TClientDetails = {
+8
View File
@@ -78,3 +78,11 @@ export const validateVersion = (version: string): boolean => {
return false
}
}
export const validateLocation = (location: string): boolean => {
// right now only perform the stupid check of whether the user copy-pasted the tooltip... (with or without brackets)
return !location.trim().includes('physical location of your node')
}
export const validateRawPort = (rawPort: number): boolean =>
!isNaN(rawPort) && rawPort >= 1 && rawPort <= 65535