Skip to content

Commit

Permalink
add more validation to asset symbol and form
Browse files Browse the repository at this point in the history
  • Loading branch information
olaszakos committed Nov 18, 2024
1 parent a9efabc commit 90f13c6
Show file tree
Hide file tree
Showing 8 changed files with 31 additions and 14 deletions.
12 changes: 2 additions & 10 deletions apps/wallet/src/components/assets/AssetForm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,15 @@ describe('AssetForm', () => {
},
});

// has not emitted "valid" event
expect(wrapper.emitted('valid')).toBeUndefined();
await wrapper.vm.$nextTick();
expect(wrapper.emitted('valid')).toEqual([[false]]);

// fill out metadata for ICP
await wrapper
.find('input[name="metadata_ledger_canister_id"]')
.setValue('ryjl3-tyaaa-aaaaa-aaaba-cai');

expect(wrapper.emitted('valid')).toEqual([[false]]);

await wrapper
.find('input[name="metadata_index_canister_id"]')
.setValue('qhbym-qaaaa-aaaaa-aaafq-cai');

await wrapper.vm.$nextTick();

// has emitted "valid" event with value true
expect(wrapper.emitted('valid')).toEqual([[false], [true]]);
});
});
8 changes: 4 additions & 4 deletions apps/wallet/src/components/assets/AssetForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
density="comfortable"
:disabled="isViewMode"
:prepend-icon="mdiTextBox"
:rules="[requiredRule]"
:rules="[requiredRule, maxLengthRule(64, $t('terms.name'))]"
/>
<VTextField
v-model="model.symbol"
Expand All @@ -60,7 +60,7 @@
density="comfortable"
:disabled="isViewMode"
:prepend-icon="mdiTag"
:rules="[requiredRule]"
:rules="[requiredRule, validSymbolRule]"
/>
<VTextField
v-model="decimals"
Expand All @@ -71,7 +71,7 @@
density="comfortable"
:disabled="isViewMode || !!model.id"
:prepend-icon="mdiDecimal"
:rules="[requiredRule]"
:rules="[requiredRule, numberRangeRule({ min: 0, max: 18 })]"
/>

<MetadataField
Expand All @@ -93,7 +93,7 @@ import BlockchainAutocomplete from '~/components/inputs/BlockchainAutocomplete.v
import MetadataField from '~/components/inputs/MetadataField.vue';
import { Asset } from '~/generated/station/station.did';
import { VFormValidation } from '~/types/helper.types';
import { requiredRule } from '~/utils/form.utils';
import { maxLengthRule, numberRangeRule, requiredRule, validSymbolRule } from '~/utils/form.utils';
import StandardsAutocomplete from '../inputs/StandardsAutocomplete.vue';
import InternetComputerNativeStandardForm from './standards/InternetComputerNativeStandardForm.vue';
import { BlockchainStandard } from '~/types/chain.types';
Expand Down
1 change: 1 addition & 0 deletions apps/wallet/src/locales/en.locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ export default {
invalidDecimalPlaces: 'This field must have a maximum of {decimals} decimal places.',
isHex: 'This field must be a valid hexadecimal value.',
validAddress: 'This field must be a valid address.',
validSymbol: 'Symbol must be 1-32 alphanumeric characters.',
},
},
navigation: {
Expand Down
1 change: 1 addition & 0 deletions apps/wallet/src/locales/fr.locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,7 @@ export default {
invalidDecimalPlaces: 'Ce champ doit contenir un maximum de {decimals} décimales.',
isHex: 'Ce champ doit contenir une valeur hexadécimale valide.',
validAddress: 'Ce champ doit contenir une adresse valide.',
validSymbol: 'Le symbole doit contenir entre 1 et 32 charactères alphanumériques.',
},
},
navigation: {
Expand Down
1 change: 1 addition & 0 deletions apps/wallet/src/locales/pt.locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ export default {
invalidDecimalPlaces: 'Este campo deve ter no máximo {decimals} casas decimais.',
isHex: 'Este campo deve conter um valor hexadecimal válido.',
validAddress: 'Este campo deve conter um endereço válido.',
validSymbol: 'O símbolo deve ter de 1 a 32 caracteres alfanuméricos.',
},
},
navigation: {
Expand Down
14 changes: 14 additions & 0 deletions apps/wallet/src/utils/form.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,20 @@ export const maxLengthRule = (max: number, field: string) => {
};
};

export const validSymbolRule = (value: unknown): string | boolean => {
const hasValue = !!value;
if (!hasValue) {
// this rule only applies if there is a value
return true;
}

if (typeof value !== 'string') {
throw new Error('validSymbolRule only applies to strings');
}

return /^[a-zA-Z0-9]{1,32}$/.test(value) ? true : i18n.global.t('forms.rules.validSymbol');
};

export const uniqueRule = (
existing: unknown[],
errorMessage: string = i18n.global.t('forms.rules.duplicate'),
Expand Down
4 changes: 4 additions & 0 deletions core/station/impl/src/errors/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub enum AssetError {
/// Invalid symbol length.
#[error(r#"Symbol must be between {min_length} and {max_length}."#)]
InvalidSymbolLength { min_length: u16, max_length: u16 },
/// Invalid symbol.
#[error(r#"Symbol must contain only alphanumeric characters."#)]
InvalidSymbol,
/// The given blockchain is unknown to the system.
#[error(r#"The given blockchain is unknown to the system."#)]
UnknownBlockchain { blockchain: String },
Expand Down Expand Up @@ -71,6 +74,7 @@ impl DetailableError for AssetError {
details.insert("max_length".to_string(), max_length.to_string());
Some(details)
}
AssetError::InvalidSymbol => Some(details),
AssetError::InvalidSymbolLength {
min_length,
max_length,
Expand Down
4 changes: 4 additions & 0 deletions core/station/impl/src/models/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ fn validate_symbol(symbol: &str) -> ModelValidatorResult<AssetError> {
});
}

if !symbol.chars().all(|c| c.is_ascii_alphanumeric()) {
return Err(AssetError::InvalidSymbol);
}

Ok(())
}

Expand Down

0 comments on commit 90f13c6

Please sign in to comment.