[users] Apply validation to the passwords config knows about
- avoid update loops by checking values before emitting *Changed() - check validity of user and root passwords when asked - if root isn't going to be written, or re-uses the user password, defer to those status checks.
This commit is contained in:
parent
e145bf68f1
commit
1dcf56761f
@ -381,7 +381,7 @@ Config::setRequireStrongPasswords( bool strong )
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Config::isPasswordAcceptable( const QString& password, QString& message )
|
Config::isPasswordAcceptable( const QString& password, QString& message ) const
|
||||||
{
|
{
|
||||||
bool failureIsFatal = requireStrongPasswords();
|
bool failureIsFatal = requireStrongPasswords();
|
||||||
|
|
||||||
@ -402,23 +402,58 @@ Config::isPasswordAcceptable( const QString& password, QString& message )
|
|||||||
void
|
void
|
||||||
Config::setUserPassword( const QString& s )
|
Config::setUserPassword( const QString& s )
|
||||||
{
|
{
|
||||||
|
if ( s != m_userPassword )
|
||||||
|
{
|
||||||
m_userPassword = s;
|
m_userPassword = s;
|
||||||
// TODO: check new password status
|
// TODO: check new password status
|
||||||
emit userPasswordChanged( s );
|
emit userPasswordChanged( s );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Config::setUserPasswordSecondary( const QString& s )
|
Config::setUserPasswordSecondary( const QString& s )
|
||||||
{
|
{
|
||||||
|
if ( s != m_userPasswordSecondary )
|
||||||
|
{
|
||||||
m_userPasswordSecondary = s;
|
m_userPasswordSecondary = s;
|
||||||
// TODO: check new password status
|
// TODO: check new password status
|
||||||
emit userPasswordSecondaryChanged( s );
|
emit userPasswordSecondaryChanged( s );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPair< Config::PasswordValidity, QString >
|
||||||
|
Config::passwordStatus( const QString& pw1, const QString& pw2 ) const
|
||||||
|
{
|
||||||
|
if ( pw1 != pw2 )
|
||||||
|
{
|
||||||
|
return qMakePair( PasswordValidity::Invalid, tr( "Your passwords do not match!" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString message;
|
||||||
|
bool ok = isPasswordAcceptable( pw1, message );
|
||||||
|
return qMakePair( ok ? PasswordValidity::Valid : PasswordValidity::Weak, message );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Config::userPasswordValidity() const
|
||||||
|
{
|
||||||
|
auto p = passwordStatus( m_userPassword, m_userPasswordSecondary );
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
Config::userPasswordStatus() const
|
||||||
|
{
|
||||||
|
auto p = passwordStatus( m_userPassword, m_userPasswordSecondary );
|
||||||
|
return p.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Config::setRootPassword( const QString& s )
|
Config::setRootPassword( const QString& s )
|
||||||
{
|
{
|
||||||
if ( writeRootPassword() )
|
if ( writeRootPassword() && s != m_rootPassword )
|
||||||
{
|
{
|
||||||
m_rootPassword = s;
|
m_rootPassword = s;
|
||||||
// TODO: check new password status
|
// TODO: check new password status
|
||||||
@ -429,7 +464,7 @@ Config::setRootPassword( const QString& s )
|
|||||||
void
|
void
|
||||||
Config::setRootPasswordSecondary( const QString& s )
|
Config::setRootPasswordSecondary( const QString& s )
|
||||||
{
|
{
|
||||||
if ( writeRootPassword() )
|
if ( writeRootPassword() && s != m_rootPasswordSecondary )
|
||||||
{
|
{
|
||||||
m_rootPasswordSecondary = s;
|
m_rootPasswordSecondary = s;
|
||||||
// TODO: check new password status
|
// TODO: check new password status
|
||||||
@ -437,28 +472,62 @@ Config::setRootPasswordSecondary( const QString& s )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Config::rootPassword() const
|
QString
|
||||||
|
Config::rootPassword() const
|
||||||
{
|
{
|
||||||
if ( writeRootPassword() )
|
if ( writeRootPassword() )
|
||||||
{
|
{
|
||||||
if ( reuseUserPasswordForRoot() )
|
if ( reuseUserPasswordForRoot() )
|
||||||
|
{
|
||||||
return userPassword();
|
return userPassword();
|
||||||
|
}
|
||||||
return m_rootPassword;
|
return m_rootPassword;
|
||||||
}
|
}
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Config::rootPasswordSecondary() const
|
QString
|
||||||
|
Config::rootPasswordSecondary() const
|
||||||
{
|
{
|
||||||
if ( writeRootPassword() )
|
if ( writeRootPassword() )
|
||||||
{
|
{
|
||||||
if ( reuseUserPasswordForRoot() )
|
if ( reuseUserPasswordForRoot() )
|
||||||
|
{
|
||||||
return userPasswordSecondary();
|
return userPasswordSecondary();
|
||||||
|
}
|
||||||
return m_rootPasswordSecondary;
|
return m_rootPasswordSecondary;
|
||||||
}
|
}
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Config::rootPasswordValidity() const
|
||||||
|
{
|
||||||
|
if ( writeRootPassword() && !reuseUserPasswordForRoot() )
|
||||||
|
{
|
||||||
|
auto p = passwordStatus( m_rootPassword, m_rootPasswordSecondary );
|
||||||
|
return p.first;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return userPasswordValidity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
Config::rootPasswordStatus() const
|
||||||
|
{
|
||||||
|
if ( writeRootPassword() && !reuseUserPasswordForRoot() )
|
||||||
|
{
|
||||||
|
auto p = passwordStatus( m_rootPassword, m_rootPasswordSecondary );
|
||||||
|
return p.second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return userPasswordStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
STATICTEST void
|
STATICTEST void
|
||||||
setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroups )
|
setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroups )
|
||||||
|
@ -62,9 +62,14 @@ class Config : public QObject
|
|||||||
Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
|
Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
|
||||||
Q_PROPERTY( QString userPasswordSecondary READ userPasswordSecondary WRITE setUserPasswordSecondary NOTIFY
|
Q_PROPERTY( QString userPasswordSecondary READ userPasswordSecondary WRITE setUserPasswordSecondary NOTIFY
|
||||||
userPasswordSecondaryChanged )
|
userPasswordSecondaryChanged )
|
||||||
|
Q_PROPERTY( int userPasswordValidity READ userPasswordValidity NOTIFY userPasswordStatusChanged STORED false )
|
||||||
|
Q_PROPERTY( QString userPasswordStatus READ userPasswordStatus NOTIFY userPasswordStatusChanged STORED false )
|
||||||
|
|
||||||
Q_PROPERTY( QString rootPassword READ rootPassword WRITE setRootPassword NOTIFY rootPasswordChanged )
|
Q_PROPERTY( QString rootPassword READ rootPassword WRITE setRootPassword NOTIFY rootPasswordChanged )
|
||||||
Q_PROPERTY( QString rootPasswordSecondary READ rootPasswordSecondary WRITE setRootPasswordSecondary NOTIFY
|
Q_PROPERTY( QString rootPasswordSecondary READ rootPasswordSecondary WRITE setRootPasswordSecondary NOTIFY
|
||||||
rootPasswordSecondaryChanged )
|
rootPasswordSecondaryChanged )
|
||||||
|
Q_PROPERTY( int rootPasswordValidity READ rootPasswordValidity NOTIFY rootPasswordStatusChanged STORED false )
|
||||||
|
Q_PROPERTY( QString rootPasswordStatus READ rootPasswordStatus NOTIFY rootPasswordStatusChanged STORED false )
|
||||||
|
|
||||||
Q_PROPERTY( bool writeRootPassword READ writeRootPassword CONSTANT )
|
Q_PROPERTY( bool writeRootPassword READ writeRootPassword CONSTANT )
|
||||||
Q_PROPERTY( bool reuseUserPasswordForRoot READ reuseUserPasswordForRoot WRITE setReuseUserPasswordForRoot NOTIFY
|
Q_PROPERTY( bool reuseUserPasswordForRoot READ reuseUserPasswordForRoot WRITE setReuseUserPasswordForRoot NOTIFY
|
||||||
@ -75,6 +80,27 @@ class Config : public QObject
|
|||||||
requireStrongPasswordsChanged )
|
requireStrongPasswordsChanged )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/** @brief Validity (status) of a password
|
||||||
|
*
|
||||||
|
* Valid passwords are:
|
||||||
|
* - primary and secondary are equal **and**
|
||||||
|
* - all the password-strength checks pass
|
||||||
|
* Weak passwords:
|
||||||
|
* - primary and secondary are equal **and**
|
||||||
|
* - not all the checks pass **and**
|
||||||
|
* - permitWeakPasswords is @c true **and**
|
||||||
|
* - requireStrongPasswords is @c false
|
||||||
|
* Invalid passwords (all other cases):
|
||||||
|
* - the primary and secondary values are not equal **or**
|
||||||
|
* - not all the checks pass and weak passwords are not permitted
|
||||||
|
*/
|
||||||
|
enum PasswordValidity
|
||||||
|
{
|
||||||
|
Valid = 0,
|
||||||
|
Weak = 1,
|
||||||
|
Invalid = 2
|
||||||
|
};
|
||||||
|
|
||||||
Config( QObject* parent = nullptr );
|
Config( QObject* parent = nullptr );
|
||||||
~Config();
|
~Config();
|
||||||
|
|
||||||
@ -128,16 +154,21 @@ public:
|
|||||||
* If the password is not acceptable, sets @p message to something
|
* If the password is not acceptable, sets @p message to something
|
||||||
* non-empty and returns @c false.
|
* non-empty and returns @c false.
|
||||||
*/
|
*/
|
||||||
bool isPasswordAcceptable( const QString& password, QString& message );
|
bool isPasswordAcceptable( const QString& password, QString& message ) const;
|
||||||
|
|
||||||
// The user enters a password (and again in a separate UI element)
|
// The user enters a password (and again in a separate UI element)
|
||||||
QString userPassword() const { return m_userPassword; }
|
QString userPassword() const { return m_userPassword; }
|
||||||
QString userPasswordSecondary() const { return m_userPasswordSecondary; }
|
QString userPasswordSecondary() const { return m_userPasswordSecondary; }
|
||||||
|
int userPasswordValidity() const;
|
||||||
|
QString userPasswordStatus() const;
|
||||||
|
|
||||||
// The root password **may** be entered in the UI, or may be suppressed
|
// The root password **may** be entered in the UI, or may be suppressed
|
||||||
// entirely when writeRootPassword is off, or may be equal to
|
// entirely when writeRootPassword is off, or may be equal to
|
||||||
// the user password when reuseUserPasswordForRoot is on.
|
// the user password when reuseUserPasswordForRoot is on.
|
||||||
QString rootPassword() const;
|
QString rootPassword() const;
|
||||||
QString rootPasswordSecondary() const;
|
QString rootPasswordSecondary() const;
|
||||||
|
int rootPasswordValidity() const;
|
||||||
|
QString rootPasswordStatus() const;
|
||||||
|
|
||||||
static const QStringList& forbiddenLoginNames();
|
static const QStringList& forbiddenLoginNames();
|
||||||
static const QStringList& forbiddenHostNames();
|
static const QStringList& forbiddenHostNames();
|
||||||
@ -193,11 +224,15 @@ signals:
|
|||||||
void requireStrongPasswordsChanged( bool );
|
void requireStrongPasswordsChanged( bool );
|
||||||
void userPasswordChanged( const QString& );
|
void userPasswordChanged( const QString& );
|
||||||
void userPasswordSecondaryChanged( const QString& );
|
void userPasswordSecondaryChanged( const QString& );
|
||||||
|
void userPasswordStatusChanged( int, QString& );
|
||||||
void rootPasswordChanged( const QString& );
|
void rootPasswordChanged( const QString& );
|
||||||
void rootPasswordSecondaryChanged( const QString& );
|
void rootPasswordSecondaryChanged( const QString& );
|
||||||
|
void rootPasswordStatusChanged( int, QString& );
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QPair< PasswordValidity, QString > passwordStatus( const QString&, const QString& ) const;
|
||||||
|
|
||||||
QStringList m_defaultGroups;
|
QStringList m_defaultGroups;
|
||||||
QString m_userShell;
|
QString m_userShell;
|
||||||
QString m_autologinGroup;
|
QString m_autologinGroup;
|
||||||
|
@ -248,8 +248,11 @@ UsersPage::reportHostNameStatus( const QString& status )
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UsersPage::checkPasswordAcceptance( const QString& pw1, const QString& pw2, QLabel* badge, QLabel* message )
|
UsersPage::checkPasswordAcceptance( Password p, QLabel* badge, QLabel* message )
|
||||||
{
|
{
|
||||||
|
QString pw1 = p == Password::User ? m_config->userPassword() : m_config->rootPassword();
|
||||||
|
QString pw2 = p == Password::User ? m_config->userPasswordSecondary() : m_config->rootPasswordSecondary();
|
||||||
|
|
||||||
if ( pw1 != pw2 )
|
if ( pw1 != pw2 )
|
||||||
{
|
{
|
||||||
labelError( badge, message, tr( "Your passwords do not match!" ), Badness::Fatal );
|
labelError( badge, message, tr( "Your passwords do not match!" ), Badness::Fatal );
|
||||||
@ -278,9 +281,7 @@ UsersPage::checkPasswordAcceptance( const QString& pw1, const QString& pw2, QLab
|
|||||||
void
|
void
|
||||||
UsersPage::onPasswordTextChanged( const QString& )
|
UsersPage::onPasswordTextChanged( const QString& )
|
||||||
{
|
{
|
||||||
m_readyPassword = checkPasswordAcceptance( ui->textBoxUserPassword->text(),
|
m_readyPassword = checkPasswordAcceptance( Password::User, ui->labelUserPassword,
|
||||||
ui->textBoxUserVerifiedPassword->text(),
|
|
||||||
ui->labelUserPassword,
|
|
||||||
ui->labelUserPasswordError );
|
ui->labelUserPasswordError );
|
||||||
|
|
||||||
emit checkReady( isReady() );
|
emit checkReady( isReady() );
|
||||||
@ -289,9 +290,7 @@ UsersPage::onPasswordTextChanged( const QString& )
|
|||||||
void
|
void
|
||||||
UsersPage::onRootPasswordTextChanged( const QString& )
|
UsersPage::onRootPasswordTextChanged( const QString& )
|
||||||
{
|
{
|
||||||
m_readyRootPassword = checkPasswordAcceptance( ui->textBoxRootPassword->text(),
|
m_readyRootPassword = checkPasswordAcceptance( Password::Root, ui->labelRootPassword,
|
||||||
ui->textBoxVerifiedRootPassword->text(),
|
|
||||||
ui->labelRootPassword,
|
|
||||||
ui->labelRootPasswordError );
|
ui->labelRootPasswordError );
|
||||||
emit checkReady( isReady() );
|
emit checkReady( isReady() );
|
||||||
}
|
}
|
||||||
|
@ -60,13 +60,15 @@ signals:
|
|||||||
void checkReady( bool );
|
void checkReady( bool );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// @brief Which password are we talking about? (for checkPasswordAcceptance())
|
||||||
|
enum class Password { Root, User };
|
||||||
/** @brief Is the password acceptable?
|
/** @brief Is the password acceptable?
|
||||||
*
|
*
|
||||||
* Checks the two copies of the password and places error messages in the
|
* Checks the two copies of the password and places error messages in the
|
||||||
* given QLabels. Returns true (and clears the error messages) if the
|
* given QLabels. Returns true (and clears the error messages) if the
|
||||||
* password is acceptable.
|
* password is acceptable.
|
||||||
*/
|
*/
|
||||||
bool checkPasswordAcceptance( const QString& pw1, const QString& pw2, QLabel* badge, QLabel* message );
|
bool checkPasswordAcceptance( Password p, QLabel* badge, QLabel* message );
|
||||||
|
|
||||||
void retranslate();
|
void retranslate();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user