Index: leahi.qrc
===================================================================
diff -u -r934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- leahi.qrc (.../leahi.qrc) (revision 934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f)
+++ leahi.qrc (.../leahi.qrc) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -102,6 +102,8 @@
resources/images/backspace.png
resources/images/Vitals.png
resources/images/Vitals_Red.png
+ resources/images/check_green.png
+ resources/images/eye_closed.png
sources/gui/qml/components/MainMenu.qml
@@ -162,6 +164,7 @@
sources/gui/qml/components/AlarmButtonRow.qml
sources/gui/qml/components/BaseComboBox.qml
sources/gui/qml/components/VitalsButton.qml
+ sources/gui/qml/components/PasswordRequirements.qml
sources/gui/qml/compounds/PressureRangeSlider.qml
Index: sources/gui/qml/components/PasswordRequirements.qml
===================================================================
diff -u
--- sources/gui/qml/components/PasswordRequirements.qml (revision 0)
+++ sources/gui/qml/components/PasswordRequirements.qml (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -0,0 +1,62 @@
+import QtQuick 2.12
+
+import "qrc:/globals"
+import "qrc:/components"
+
+Item { id: _root
+ property string password : ""
+
+ readonly property string checkGreen : "qrc:/images/iCheckGreen"
+ readonly property int titlePixelSize : 25
+ readonly property int delegatePixelSize : 22
+
+ Text { id: passwordRequirementsLabel
+ anchors.top : parent.top
+ font {
+ pixelSize : _root.titlePixelSize
+ weight : Font.Medium
+ }
+ width : parent.width
+ height : Variables.contentHeight
+ horizontalAlignment : Text.AlignLeft
+ verticalAlignment : Text.AlignVCenter
+ wrapMode : Text.Wrap
+ color : Colors.textMain
+ text : qsTr("The password must contain at least the following:")
+ }
+
+ Column { id: contentColumn
+ anchors.top : passwordRequirementsLabel.bottom
+ anchors.topMargin : Variables.defaultMargin
+ spacing : 5
+ width : _root.width
+ height : _root.height
+
+ Repeater {
+ model: [
+ { name: qsTr("Upper Case"), source: vSettings.passwordContainsUpperCase (_root.password) ? _root.checkGreen : "" },
+ { name: qsTr("Lower Case"), source: vSettings.passwordContainsLowerCase (_root.password) ? _root.checkGreen : "" },
+ { name: qsTr("Digits"), source: vSettings.passwordContainsDigit (_root.password) ? _root.checkGreen : "" },
+ { name: qsTr("Symbols"), source: vSettings.passwordContainsSymbol (_root.password) ? _root.checkGreen : "" },
+ { name: qsTr("Character Limit"), source: vSettings.passwordContainsCharacterLimit(_root.password) ? _root.checkGreen : "" }
+ ]
+
+ delegate: Text { id: _delegate
+ font.pixelSize : _root.delegatePixelSize
+ color : Colors.textMain
+ text : modelData.name
+ width : parent.width / 2
+
+ Image { id: _indicator
+ anchors {
+ right : parent.right
+ verticalCenter : parent.verticalCenter
+ }
+ source : modelData.source
+ sourceSize.width : parent.height - 5
+ sourceSize.height : parent.height - 5
+ }
+ }
+ }
+ }
+}
Index: sources/gui/qml/pages/UserConfirmation.qml
===================================================================
diff -u -r934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- sources/gui/qml/pages/UserConfirmation.qml (.../UserConfirmation.qml) (revision 934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f)
+++ sources/gui/qml/pages/UserConfirmation.qml (.../UserConfirmation.qml) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -14,7 +14,7 @@
*/
// Qt
-import QtQuick 2.12
+import QtQuick 2.15
// Project
@@ -27,8 +27,12 @@
* \brief Contains the message for user information or password entry for user to confirm.
*/
SettingsBase { id: _root
- objectName : "UserConfirmation" // SquishQt testability
+ objectName : "UserConfirmation" // SquishQt testability
+ confirmEnabled : ! passwordChangeMode ||
+ (vSettings.isPasswordHighStrength(_root.passwordUpdated) &&
+ _root.passwordUpdated === _root.passwordConfirm)
+
property bool isPassword : false
property bool passwordChangeMode : false
readonly property string passwordCurrent : _passwordCurrent.textInput.text
@@ -37,53 +41,77 @@
property int passwordLengthMax : 30
property alias message : _message.text
- function clearPasswordCurrnet() { _passwordCurrent.textInput.text = "" }
+ readonly property string hidePassword : "qrc:/images/iEyeClosed"
+ readonly property string showPassword : "qrc:/images/iEye"
+
+ function clearPasswordCurrent() { _passwordCurrent.textInput.text = "" }
function clearPasswordUpdated() { _passwordUpdated.textInput.text = "" }
function clearPasswordReEntry() { _passwordConfirm.textInput.text = "" }
function clearPasswords () {
- clearPasswordCurrnet()
+ clearPasswordCurrent()
clearPasswordUpdated()
clearPasswordReEntry()
}
firstFocusInput : isPassword ? _passwordCurrent : undefined
- contentItem: Column {
+ contentItem: Item {
visible: isPassword
- PasswordEntry { id: _passwordCurrent
- label.text : ! passwordChangeMode ? "" : qsTr("Current")
- label.width : ! passwordChangeMode ? 0 : labelWidth
- lengthMax : passwordLengthMax
- nextInput : _passwordUpdated
- anchors {
- top : parent.top
- topMargin : Variables.defaultMargin * 5
- horizontalCenter : parent.horizontalCenter
+ Column { id: _passwordEntries
+ anchors.horizontalCenter : parent.horizontalCenter
+ anchors.horizontalCenterOffset : passwordChangeMode ? Variables.defaultMargin * -4 : 0
+ width : parent.width / 2.5
+
+ PasswordEntry { id: _passwordCurrent
+ visible : ! passwordChangeMode
+ label.text : ""
+ label.width : 0
+ lengthMax : passwordLengthMax
+ nextInput : _passwordUpdated
+ anchors {
+ top : parent.top
+ topMargin : passwordChangeMode ? Variables.defaultMargin * 2 : Variables.defaultMargin * 5
+ horizontalCenter : parent.horizontalCenter
+ }
}
- }
- PasswordEntry { id: _passwordUpdated
- visible : passwordChangeMode
- label.text : qsTr("New")
- nextInput : _passwordConfirm
- lengthMax : passwordLengthMax
- anchors {
- top : _passwordCurrent.bottom
- horizontalCenter : parent.horizontalCenter
+ PasswordEntry { id: _passwordUpdated
+ visible : passwordChangeMode
+ label.text : qsTr("New")
+ nextInput : _passwordConfirm
+ lengthMax : passwordLengthMax
+ anchors {
+ top : _passwordCurrent.bottom
+ horizontalCenter : parent.horizontalCenter
+ }
}
+
+ PasswordEntry { id: _passwordConfirm
+ visible : passwordChangeMode
+ label.text : qsTr("Confirm")
+ lengthMax : passwordLengthMax
+ anchors {
+ top : _passwordUpdated.bottom
+ horizontalCenter : parent.horizontalCenter
+ }
+ }
}
- PasswordEntry { id: _passwordConfirm
- visible : passwordChangeMode
- label.text : qsTr("Confirm")
- lengthMax : passwordLengthMax
+ PasswordRequirements {id: _passwordRequirements
anchors {
- top : _passwordUpdated.bottom
- horizontalCenter : parent.horizontalCenter
+ top : parent.top
+ topMargin : Variables.defaultMargin * 2
+ left : _passwordEntries.right
+ leftMargin : Variables.defaultMargin * 2
}
+ visible : passwordChangeMode
+ height : parent.height / 2
+ width : parent.width / 4
+ password : passwordUpdated
}
}
+
component PasswordEntry : Item {
property alias textInput : _passwordEntry.textInput
property alias nextInput : _passwordEntry.nextInput
@@ -95,23 +123,31 @@
label.width : labelWidth
TextEntry { id: _passwordEntry
- clip : true
- textInput .width : 450
+ clip : true
+ textInput .width : 450
textInput.inputMethodHints : Qt.ImhNone
textInput.echoMode : TextInput.Password
anchors.horizontalCenter : parent.horizontalCenter
+
+ onTextChanged: {
+ // Replace non-ASCII characters as they are typed in
+ var filtered = text.replace(/[^\x00-\x7F]/g, "")
+ if (text !== filtered) { text = filtered } // revert invalid characters
+ }
}
Image {
visible : _passwordEntry.visible
anchors.left : _passwordEntry.right
anchors.leftMargin : Variables.minVGap
anchors.verticalCenter : _passwordEntry.verticalCenter
- width : Variables.iconsDiameter
- height : Variables.iconsDiameter
- source : "qrc:/images/iEye"
+ width : 35
+ height : 35
- MouseArea {
+ source : _mouseArea.pressed ? _root.showPassword : _root.hidePassword
+ fillMode : Image.PreserveAspectFit
+
+ MouseArea { id: _mouseArea
anchors.fill: parent
anchors.margins: -20
onPressed : _passwordEntry.textInput.echoMode = TextInput.Normal
Index: sources/gui/qml/pages/settings/SettingsDecommission.qml
===================================================================
diff -u -r934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- sources/gui/qml/pages/settings/SettingsDecommission.qml (.../SettingsDecommission.qml) (revision 934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f)
+++ sources/gui/qml/pages/settings/SettingsDecommission.qml (.../SettingsDecommission.qml) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -38,12 +38,12 @@
backEnabled : vDevice.decommissionEnabled
onConfirmClicked : {
- _confirmDialog.titleText = _root.title
+ _confirmDialog.titleText = _headerBar.titleText
_confirmDialog.open()
}
Connections { target: _confirmDialog
function onAccepted() {
- if ( _confirmDialog.titleText == _root.title ) { // use the title as the indication of what has been confirmed and if that is related to this function.
+ if ( _confirmDialog.titleText === _headerBar.titleText ) { // use the title as the indication of what has been confirmed and if that is related to this function.
vDevice.decommission = "" // Need to set to something (ie: emtpy string) to trigger CPP code
}
}
Index: sources/gui/qml/pages/settings/SettingsFactoryReset.qml
===================================================================
diff -u -r934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- sources/gui/qml/pages/settings/SettingsFactoryReset.qml (.../SettingsFactoryReset.qml) (revision 934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f)
+++ sources/gui/qml/pages/settings/SettingsFactoryReset.qml (.../SettingsFactoryReset.qml) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -38,12 +38,12 @@
backEnabled : vDevice.factoryResetEnabled
onConfirmClicked : {
- _confirmDialog.titleText = _root.title
+ _confirmDialog.titleText = _headerBar.titleText
_confirmDialog.open()
}
Connections { target: _confirmDialog
function onAccepted() {
- if ( _confirmDialog.titleText == _root.title ) { // use the title as the indication of what has been confirmed and if that is related to this function.
+ if ( _confirmDialog.titleText === _headerBar.titleText ) { // use the title as the indication of what has been confirmed and if that is related to this function.
vDevice.factoryReset = "" // Need to set to something (ie: emtpy string) to trigger CPP code
}
}
Index: sources/gui/qml/pages/settings/SettingsLocalization.qml
===================================================================
diff -u -rbeadb6f68cff8bc50f255f83203ec201a5468dc1 -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- sources/gui/qml/pages/settings/SettingsLocalization.qml (.../SettingsLocalization.qml) (revision beadb6f68cff8bc50f255f83203ec201a5468dc1)
+++ sources/gui/qml/pages/settings/SettingsLocalization.qml (.../SettingsLocalization.qml) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -44,20 +44,19 @@
}
onConfirmClicked : {
- _confirmDialog.titleText = _root.title
+ _confirmDialog.titleText = _headerBar.titleText
_confirmDialog.open()
}
Connections { target: _confirmDialog
function onAccepted() {
- if ( _confirmDialog.titleText == _root.title ) { // use the title as the indication of what has been confirmed and if that is related to this function.
+ if ( _confirmDialog.titleText === _headerBar.titleText ) { // use the title as the indication of what has been confirmed and if that is related to this function.
vLocalization.doAdjustment(_settingsLanguageCombo.currentIndex)
}
}
}
Connections { target: _settingsLanguageCombo
-
function onCurrentIndexChanged() {
vLocalization.notification = ""
}
Index: sources/gui/qml/pages/settings/SettingsServicePassword.qml
===================================================================
diff -u -r934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- sources/gui/qml/pages/settings/SettingsServicePassword.qml (.../SettingsServicePassword.qml) (revision 934354462a353ff5e7fc2ddfe6f3a8f0121a8f3f)
+++ sources/gui/qml/pages/settings/SettingsServicePassword.qml (.../SettingsServicePassword.qml) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -47,12 +47,6 @@
// if not accepted return
if ( ! isPassword_Accepted ) return
- // if accepted save the password
- if ( passwordChangeMode ) vSettings.updateServicePassword(passwordUpdated)
-
- // ask HD to go to service mode
- vAdjustmentServiceMode.doAdjustment()
-
// clear the screen
_root.notificationText = ""
clearPasswords()
@@ -64,15 +58,27 @@
if ( vTDOpMode.service ) gotoServiceMode(true)
}
- // TODO: Add logic here to check for which user is trying to log in
function checkPassword() {
- if ( ! vSettings.isServicePasswordMatch( passwordCurrent ) ) { _root.notificationText = qsTr("Incorrect password" ); return false }
+ let servicePasswordCheck = false
+ let user1PasswordCheck = false // does nothing right now
- if ( ! passwordChangeMode ) { _root.notificationText = "" ; return true }
+ if ( vSettings.isServicePasswordMatch( passwordCurrent ) || passwordChangeMode ){ handleServicePassword(); servicePasswordCheck = true }
- if ( passwordConfirm != passwordUpdated ) { _root.notificationText = qsTr("Mismatch Passwords" ); return false }
- if ( ! vSettings.isPasswordValid(passwordUpdated ) ) { _root.notificationText = qsTr("Invalid Password" ); return false }
+ // TODO: Add other password match checks for other users
+// if ( vSettings.isUser1PasswordMatch( passwordCurrent ) || passwordChangeMode ){ handleUser1Password(); user1PasswordCheck = true }
- _root.notificationText = "" ; return true
+ // check all password check if any are successful
+ let allPasswordCheck = servicePasswordCheck || user1PasswordCheck
+ _root.notificationText = allPasswordCheck ? "" : qsTr("Incorrect password")
+
+ return allPasswordCheck
}
+
+ function handleServicePassword() {
+ // if accepted save the password
+ if ( passwordChangeMode ) vSettings.updateServicePassword(passwordUpdated)
+
+ // ask TD to go to service mode
+ vAdjustmentServiceMode.doAdjustment()
+ }
}
Index: sources/view/settings/VSettings.cpp
===================================================================
diff -u -ra5760947d3ed0d2748ba023a1c25e3c6aa0b1de1 -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- sources/view/settings/VSettings.cpp (.../VSettings.cpp) (revision a5760947d3ed0d2748ba023a1c25e3c6aa0b1de1)
+++ sources/view/settings/VSettings.cpp (.../VSettings.cpp) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -225,47 +225,69 @@
}
/*!
- * \brief VSettings::isPasswordValid
- * \details Validates the passed string for conforming to the
- * - at least one capital letter,
- * - at least one digit,
- * - at least one symbol
- * rule
- * \param vPassword - the string to check
- * \returns true if string pass conforms, false otherwise
+ * \brief Return whether the password has the minimum character limit
+ * \param[in] password password to check
+ * \return true if the password contains requirement
*/
-bool View::VSettings::isPasswordValid(const QString &vPassword) {
- int minLen = 10 ; // in the SRS the max is required to be 12 which seems incorrect and I didn't set it here.
- QString pla = "(?=.*[%1])" ; // positive look ahead
- QString regSntnc = "^%1$" ; // regular expression sentence with has a start/end
- QString regUpper = "A-Z" ;
- QString regLower = "a-z" ;
- QString regDigit = "0-9" ;
- QString regSymbl = "!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_`{\\|}~";
- QString rln = "[%1]{%2,}" ;
+bool View::VSettings::passwordContainsCharacterLimit(const QString &vPassword) const
+{
+ return vPassword.size() >= 10;
+}
- // "^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{\|}~])[A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{\|}~]{10,}$"
- // !"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_`{\\|}~
- QString regStr = regSntnc.arg(
- pla.arg(regUpper) +
- pla.arg(regLower) +
- pla.arg(regDigit) +
- pla.arg(regSymbl) +
- rln.arg(regUpper +
- regLower +
- regDigit +
- regSymbl)
- .arg(minLen )
- );
- QRegularExpression passwordRegex(regStr);
- bool ok;
+/*!
+ * \brief Return whether the password has a upper case letter
+ * \param[in] password password to check
+ * \return true if the password contains requirement
+ */
+bool View::VSettings::passwordContainsUpperCase(const QString &vPassword) const
+{
+ static const QRegularExpression upperCaseLetter("[A-Z]");
+ return vPassword.contains(upperCaseLetter);
+}
- //DEBUG: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
- //DEBUG: vPassword = "Ab0!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
- ok = passwordRegex.match(vPassword).hasMatch();
- return ok;
+/*!
+ * \brief Return whether the password has a lower case letter
+ * \param[in] password password to check
+ * \return true if the password contains requirement
+ */
+bool View::VSettings::passwordContainsLowerCase(const QString &vPassword) const
+{
+ static const QRegularExpression lowerCaseLetter("[a-z]");
+ return vPassword.contains(lowerCaseLetter);
}
+/*!
+ * \brief Return whether the password has a digit
+ * \param[in] password password to check
+ * \return true if the password contains requirement
+ */
+bool View::VSettings::passwordContainsDigit(const QString &vPassword) const
+{
+ static const QRegularExpression number("[0-9]");
+ return vPassword.contains(number);
+}
+
+bool View::VSettings::passwordContainsSymbol(const QString &vPassword) const
+{
+ static const QRegularExpression symbol(
+ QStringLiteral("[%1]").arg(QRegularExpression::escape("{}[],.<>;:'\"?/|\\`~!@#$%^&*()_-+=")));
+ return vPassword.contains(symbol);
+}
+
+/*!
+ * \brief Return whether the password is high strength.
+ * \param[in] password password to check
+ * \return true if the password is high strength and false otherwise.
+ */
+bool View::VSettings::isPasswordHighStrength(const QString &vPassword) const
+{
+ return passwordContainsUpperCase(vPassword) &&
+ passwordContainsLowerCase(vPassword) &&
+ passwordContainsDigit(vPassword) &&
+ passwordContainsSymbol(vPassword) &&
+ passwordContainsCharacterLimit(vPassword);
+}
+
QString View::VSettings::hashedPassword(const QString &vPassword, bool vIsService)
{
bool ok;
Index: sources/view/settings/VSettings.h
===================================================================
diff -u -ra5760947d3ed0d2748ba023a1c25e3c6aa0b1de1 -r88a09dc4b26cfdd5fd111d20adfb9cb60697186c
--- sources/view/settings/VSettings.h (.../VSettings.h) (revision a5760947d3ed0d2748ba023a1c25e3c6aa0b1de1)
+++ sources/view/settings/VSettings.h (.../VSettings.h) (revision 88a09dc4b26cfdd5fd111d20adfb9cb60697186c)
@@ -85,7 +85,12 @@
QString hashedPassword (const QString &vPassword, bool vIsService);
public slots:
- bool isPasswordValid (const QString &vPassword);
+ bool isPasswordHighStrength (const QString &vPassword) const;
+ bool passwordContainsCharacterLimit (const QString &vPassword) const;
+ bool passwordContainsUpperCase (const QString &vPassword) const;
+ bool passwordContainsLowerCase (const QString &vPassword) const;
+ bool passwordContainsDigit (const QString &vPassword) const;
+ bool passwordContainsSymbol (const QString &vPassword) const;
bool isServicePasswordMatch (const QString &vPassword);
void updateServicePassword (const QString &vPassword);