mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Enforce passphrase confirmation match on the restore and create wallet flows (#3474)
* fix: enforce passphrase confirmation in restore passphrase bottom sheet The confirm-passphrase field in AddPassphraseBottomSheet already had a validator comparing it to the first field, but the fields were not inside a Form and nothing ever called validate(), so the validator never ran. Tapping "Restore" restored the wallet with the first field's value even when the confirmation did not match, defeating the typo check. Wrap both fields in a Form and validate it before completing the restore, matching the existing pattern in advanced_privacy_settings_page.dart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019DtLNfYw1H81p7zZrkNDXM * Validate passphrase confirmation when the passphrase field is empty --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b50ceb2462
commit
f6566e3baf
@@ -360,11 +360,9 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
|
||||
|
||||
widget.nodeViewModel.save();
|
||||
}
|
||||
if (passphraseController.text.isNotEmpty) {
|
||||
if (_passphraseFormKey.currentState != null &&
|
||||
!_passphraseFormKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
if (_passphraseFormKey.currentState != null &&
|
||||
!_passphraseFormKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
widget.seedTypeViewModel.setPassphrase(passphraseController.text);
|
||||
|
||||
@@ -20,6 +20,7 @@ class AddPassphraseBottomSheet extends StatefulWidget {
|
||||
class _AddPassphraseBottomSheetState extends State<AddPassphraseBottomSheet> {
|
||||
late final TextEditingController passphraseController;
|
||||
late final TextEditingController confirmPassphraseController;
|
||||
final _passphraseFormKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -112,51 +113,60 @@ class _AddPassphraseBottomSheetState extends State<AddPassphraseBottomSheet> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
BaseTextFormField(
|
||||
key: ValueKey('add_passphrase_bottom_sheet_widget_passphrase_textfield_key'),
|
||||
controller: passphraseController,
|
||||
obscureText: obscurePassphrase,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12),
|
||||
hintText: S.of(context).required_passphrase,
|
||||
suffixIcon: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
obscurePassphrase = !obscurePassphrase;
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
obscurePassphrase ? Icons.visibility_off : Icons.visibility,
|
||||
size: 24,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
BaseTextFormField(
|
||||
key: ValueKey('add_passphrase_bottom_sheet_widget_confirm_passphrase_textfield_key'),
|
||||
controller: confirmPassphraseController,
|
||||
obscureText: obscurePassphrase,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12),
|
||||
hintText: S.of(context).confirm_passphrase,
|
||||
suffixIcon: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
obscurePassphrase = !obscurePassphrase;
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
obscurePassphrase ? Icons.visibility_off : Icons.visibility,
|
||||
size: 24,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
validator: (text) {
|
||||
if (text == passphraseController.text) {
|
||||
return null;
|
||||
}
|
||||
Form(
|
||||
key: _passphraseFormKey,
|
||||
child: Column(
|
||||
children: [
|
||||
BaseTextFormField(
|
||||
key: ValueKey('add_passphrase_bottom_sheet_widget_passphrase_textfield_key'),
|
||||
controller: passphraseController,
|
||||
obscureText: obscurePassphrase,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12),
|
||||
hintText: S.of(context).required_passphrase,
|
||||
suffixIcon: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
obscurePassphrase = !obscurePassphrase;
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
obscurePassphrase ? Icons.visibility_off : Icons.visibility,
|
||||
size: 24,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
BaseTextFormField(
|
||||
key: ValueKey(
|
||||
'add_passphrase_bottom_sheet_widget_confirm_passphrase_textfield_key',
|
||||
),
|
||||
controller: confirmPassphraseController,
|
||||
obscureText: obscurePassphrase,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12),
|
||||
hintText: S.of(context).confirm_passphrase,
|
||||
suffixIcon: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
obscurePassphrase = !obscurePassphrase;
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
obscurePassphrase ? Icons.visibility_off : Icons.visibility,
|
||||
size: 24,
|
||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
validator: (text) {
|
||||
if (text == passphraseController.text) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return S.of(context).passphrases_doesnt_match;
|
||||
},
|
||||
return S.of(context).passphrases_doesnt_match;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
@@ -184,6 +194,11 @@ class _AddPassphraseBottomSheetState extends State<AddPassphraseBottomSheet> {
|
||||
child: PrimaryButton(
|
||||
key: ValueKey('add_passphrase_bottom_sheet_widget_restore_button_key'),
|
||||
onPressed: () {
|
||||
if (_passphraseFormKey.currentState != null &&
|
||||
!_passphraseFormKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.pop(context);
|
||||
widget.onRestoreButtonPressed(passphraseController.text);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user