From b0524166661613a51ab60546ae65e4a5abcc07c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Tinkl?= Date: Tue, 15 Oct 2024 12:45:50 +0200 Subject: [PATCH] fix(PasswordView): Password instructions missing max length requirement - set the pass max length to 100 (via `Constants`, not with a hardcoded regexp) - delay the validation until the user hits the limit - clear the categories (lower/upper/num/sym) info if the password is cleared too - update the error messages according to latest Figma designs Fixes #16239 --- storybook/pages/PasswordViewPage.qml | 4 +++ .../StatusPasswordStrengthIndicator.qml | 8 ++--- .../shared/views/PasswordConfirmationView.qml | 3 +- ui/imports/shared/views/PasswordView.qml | 34 ++++++++++--------- ui/imports/utils/Constants.qml | 1 + 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/storybook/pages/PasswordViewPage.qml b/storybook/pages/PasswordViewPage.qml index 768f240521..264084a63e 100644 --- a/storybook/pages/PasswordViewPage.qml +++ b/storybook/pages/PasswordViewPage.qml @@ -53,6 +53,7 @@ SplitView { Switch { id: createNewPassword text: "Create new password" + checked: true } Switch { @@ -63,9 +64,12 @@ SplitView { Switch { id: titleVisibleSwitch text: "Title visible" + checked: true } } } } // category: Views + +// https://www.figma.com/design/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=41014-22302&node-type=frame&t=0JUvGJPEhU9e9QB9-0 diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusPasswordStrengthIndicator.qml b/ui/StatusQ/src/StatusQ/Controls/StatusPasswordStrengthIndicator.qml index f20ff80521..d8c58f95e6 100644 --- a/ui/StatusQ/src/StatusQ/Controls/StatusPasswordStrengthIndicator.qml +++ b/ui/StatusQ/src/StatusQ/Controls/StatusPasswordStrengthIndicator.qml @@ -1,5 +1,5 @@ -import QtQuick 2.14 -import QtQuick.Controls 2.14 +import QtQuick 2.15 +import QtQuick.Controls 2.15 import StatusQ.Core.Theme 0.1 import StatusQ.Core 0.1 @@ -42,7 +42,7 @@ StatusProgressBar { id: control /*! - \qmlproperty string StatusPasswordStrengthIndicator::strength + \qmlproperty int StatusPasswordStrengthIndicator::strength This property holds the password strength value. Possible values are: \list \li StatusPasswordStrengthIndicator.Strength.None @@ -53,7 +53,7 @@ StatusProgressBar { \li StatusPasswordStrengthIndicator.Strength.Great \endlist */ - property var strength + property int strength /*! \qmlproperty string StatusPasswordStrengthIndicator::labelVeryWeak This property holds the text shown when the strength is StatusPasswordStrengthIndicator.Strength.VeryWeak. diff --git a/ui/imports/shared/views/PasswordConfirmationView.qml b/ui/imports/shared/views/PasswordConfirmationView.qml index 4c9bce0e9b..b47c75548e 100644 --- a/ui/imports/shared/views/PasswordConfirmationView.qml +++ b/ui/imports/shared/views/PasswordConfirmationView.qml @@ -74,7 +74,8 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter placeholderText: qsTr("Confirm your password (again)") echoMode: showPassword ? TextInput.Normal : TextInput.Password - validator: RegExpValidator { regExp: /^[!-~]{0,64}$/ } // That incudes NOT extended ASCII printable characters less space and a maximum of 64 characters allowed + validator: RegExpValidator { regExp: /^[!-~]+$/ } // That includes NOT extended ASCII printable characters less space + maximumLength: Constants.maxPasswordLength // a maximum of 100 characters allowed rightPadding: showHideCurrentIcon.width + showHideCurrentIcon.anchors.rightMargin + Style.current.padding / 2 onTextChanged: { errorTxt.text = "" diff --git a/ui/imports/shared/views/PasswordView.qml b/ui/imports/shared/views/PasswordView.qml index 20d9b8596e..9b8f410e21 100644 --- a/ui/imports/shared/views/PasswordView.qml +++ b/ui/imports/shared/views/PasswordView.qml @@ -1,10 +1,7 @@ -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 -import shared.panels 1.0 -import shared.controls 1.0 -import shared.stores 1.0 import utils 1.0 import StatusQ.Controls 0.1 @@ -16,7 +13,8 @@ import StatusQ.Popups 0.1 ColumnLayout { id: root - property bool ready: newPswInput.text.length >= Constants.minPasswordLength && newPswInput.text === confirmPswInput.text && errorTxt.text === "" + readonly property bool ready: newPswInput.text.length >= Constants.minPasswordLength && newPswInput.text === confirmPswInput.text && errorTxt.text === "" + property bool createNewPsw: true property string title: createNewPsw ? qsTr("Create a password") : qsTr("Change your password") property bool titleVisible: true @@ -86,14 +84,15 @@ ColumnLayout { property bool containsNumbers: false property bool containsSymbols: false - readonly property var validatorRegexp: /^[!-~]{0,64}$/ - readonly property string validatorErrMessage: qsTr("Only letters, numbers, underscores and hyphens allowed") + readonly property var validatorRegexp: /^[!-~]+$/ + readonly property string validatorErrMessage: qsTr("Only ASCII letters, numbers, and symbols are allowed") + readonly property string passTooLongErrMessage: qsTr("Maximum %n character(s)", "", Constants.maxPasswordLength) // Password strength categorization / validation function lowerCaseValidator(text) { return (/[a-z]/.test(text)) } function upperCaseValidator(text) { return (/[A-Z]/.test(text)) } function numbersValidator(text) { return (/\d/.test(text)) } - // That incudes NOT extended ASCII printable symbols less space: + // That includes NOT extended ASCII printable symbols less space: function symbolsValidator(text) { return (/[!-\/:-@[-`{-~]/.test(text)) } function validateCharacterSet(text) { @@ -101,6 +100,10 @@ ColumnLayout { errorTxt.text = d.validatorErrMessage return false } + if(text.length > Constants.maxPasswordLength) { + errorTxt.text = d.passTooLongErrMessage + return false + } return true } @@ -125,15 +128,15 @@ ColumnLayout { // 3 rules to validate: // * Password is in pwnd passwords database if(isInPwndDatabase()) - errorTxt.text = qsTr("This password has been pwned and shouldn't be used") + errorTxt.text = qsTr("Password pwned, shouldn't be used") // * Common password else if(isCommonPassword()) - errorTxt.text = qsTr("This password is a common word and shouldn't be used") + errorTxt.text = qsTr("Common password, shouldn't be used") // * Password too short else if(isTooShort()) - errorTxt.text = qsTr("Password must be at least %n character(s) long", "", Constants.minPasswordLength) + errorTxt.text = qsTr("Minimum %n character(s)", "", Constants.minPasswordLength) } function isInPwndDatabase() { @@ -262,13 +265,13 @@ ColumnLayout { // Update strength indicator: strengthInditactor.strength = d.convertStrength(root.passwordStrengthScoreFunction(newPswInput.text)) - if(!d.validateCharacterSet(text)) return - d.containsLower = d.lowerCaseValidator(text) d.containsUpper = d.upperCaseValidator(text) d.containsNumbers = d.numbersValidator(text) d.containsSymbols = d.symbolsValidator(text) + if(!d.validateCharacterSet(text)) return + if (text.length === confirmPswInput.text.length) { root.checkPasswordMatches(false) } @@ -306,7 +309,6 @@ ColumnLayout { Rectangle { Layout.fillWidth: true - Layout.fillHeight: true Layout.minimumHeight: 80 border.color: Theme.palette.baseColor2 border.width: 1 diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 5f83be9190..e72c259abc 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -1046,6 +1046,7 @@ QtObject { readonly property string wrongDerivationPathError: "error parsing derivation path" readonly property int minPasswordLength: 10 + readonly property int maxPasswordLength: 100 readonly property QtObject suggestedRoutesExtraParamsProperties: QtObject { readonly property string packId: "packID"