Skip to content

Commit

Permalink
Merge pull request #115 from EnriqueL8/validate_contract_api
Browse files Browse the repository at this point in the history
Add form validation for Contract API
  • Loading branch information
dechdev authored Apr 13, 2023
2 parents 6d6a428 + e72b214 commit af67200
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ We welcome contributions to the FireFly Project in many forms, and
there's always plenty to do!

Please visit the
[contributors guide](https://hyperledger.github.io/firefly/contributors/contributors.html) in the
[contributors guide](https://hyperledger.github.io/firefly/contributors/) in the
docs to learn how to make contributions to this exciting project.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ npm install
npm start
```

Note: If your Firefly instance is not exposed on port 5000 locally or running remotely, set the env FF_ENDPOINT to the location of your instance.

## Git repositories

There are multiple Git repos making up the Hyperledger FireFly project. Some others
Expand All @@ -54,4 +56,4 @@ Please adhere to this project's [Code of Conduct](CODE_OF_CONDUCT.md).

## License

Hyperledger Project source code files are made available under the Apache License, Version 2.0 (Apache-2.0), located in the [LICENSE](LICENSE) file.
Hyperledger Project source code files are made available under the Apache License, Version 2.0 (Apache-2.0), located in the [LICENSE](LICENSE) file.
37 changes: 35 additions & 2 deletions ui/src/components/Forms/Contracts/RegisterContractApiForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { BLOCKCHAIN_TYPE } from '../../../enums/enums';
import { IContractInterface } from '../../../interfaces/api';
import { DEFAULT_SPACING } from '../../../theme';
import { fetchCatcher } from '../../../utils/fetches';
import { isValidFFName, isValidAddress } from '../../../utils/regex';

export const RegisterContractApiForm: React.FC = () => {
const { blockchainPlugin, setJsonPayload, setPayloadMissingFields } =
Expand All @@ -32,9 +33,11 @@ export const RegisterContractApiForm: React.FC = () => {
>([]);
const [contractInterfaceIdx, setContractInterfaceIdx] = useState<number>(0);
const [name, setName] = useState<string>('');
const [nameError, setNameError] = useState<string>('');
const [chaincode, setChaincode] = useState<string>('');
const [channel, setChannel] = useState<string>('');
const [contractAddress, setContractAddress] = useState<string>('');
const [contractAddressError, setContractAddressError] = useState<string>('');

const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
Expand Down Expand Up @@ -133,7 +136,23 @@ export const RegisterContractApiForm: React.FC = () => {
fullWidth
required
label={t('name')}
onChange={(e) => setName(e.target.value)}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value;
if (newValue === '') {
setNameError(t(''));
} else if (!isValidFFName(newValue)) {
setNameError(
t('form.validation.invalidFFField', {
field: t('form.contracts.apiEndpointName'),
})
);
} else {
setNameError('');
}
setName(newValue);
}}
error={!!nameError}
helperText={nameError}
/>
</FormControl>
</Grid>
Expand All @@ -144,7 +163,21 @@ export const RegisterContractApiForm: React.FC = () => {
fullWidth
required
label={t('address')}
onChange={(e) => setContractAddress(e.target.value)}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value;
if (newValue === '') {
setContractAddressError(t(''));
} else if (!isValidAddress(newValue)) {
setContractAddressError(
t('form.validation.invalidAddress')
);
} else {
setContractAddressError('');
}
setContractAddress(newValue);
}}
error={!!contractAddressError}
helperText={contractAddressError}
/>
<FormHelperText id="address-helper-text">
{t('contractAddressHelperText')}
Expand Down
9 changes: 9 additions & 0 deletions ui/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@
"firstEventDescription": "The first event for this listener to index. Valid options are 'newest', 'oldest', or a specific block number.",
"followStepsInInstructions": "Follow steps outlined in the instructions",
"format": "format",
"form": {
"validation": {
"invalidFFField": "{{field}} must consist of alphanumeric characters, '-', '_', or '.', must start and end with an alphanumeric character, and be no more than 64 characters.",
"invalidAddress": "Not a valid ethereum address"
},
"contracts": {
"apiEndpointName": "API endpoint name"
}
},
"fromAddress": "From Address",
"fungible": "Fungible",
"github": "Github",
Expand Down
15 changes: 15 additions & 0 deletions ui/src/utils/regex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const ffNameRegex = /^[0-9a-zA-Z]([0-9a-zA-Z._-]{0,62}[0-9a-zA-Z])?$/;
const addressRegex = /^0x[a-fA-F0-9]{40}$/;

export const isValidFFName = (name: string) => {
// have to use a variable to store the return value before return it
// otherwise you'll see "jumpy" validation result when you use the function
// directly as the value of a react component
const result = ffNameRegex.test(name);
return result;
};

export const isValidAddress = (address: string) => {
const result = addressRegex.test(address);
return result;
};

0 comments on commit af67200

Please sign in to comment.