From 35dff4d12c0aa39324c15761541b74e129004b4d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 4 Aug 2020 22:16:48 +0200 Subject: [PATCH] [users] Migrate reuse-password and password-strength to Config - add the "reuse user password for root" setting to Config, make the UI page follow that setting. - add the require-strong-password default and toggle settings to Config; this is not well-checked yet. On the widget / UI side, connect checkboxes only if they are visible; refactor reuse-user-password-for-root settings. --- src/modules/users/Config.cpp | 27 ++++++++++ src/modules/users/Config.h | 26 ++++++++++ src/modules/users/UsersPage.cpp | 77 +++++++++++++++-------------- src/modules/users/UsersPage.h | 5 +- src/modules/users/UsersViewStep.cpp | 5 -- 5 files changed, 95 insertions(+), 45 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index e0174e74e..823b9fb99 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -343,6 +343,27 @@ Config::setAutoLogin( bool b ) } } +void +Config::setReuseUserPasswordForRoot( bool reuse ) +{ + if ( reuse != m_reuseUserPasswordForRoot ) + { + m_reuseUserPasswordForRoot = reuse; + emit reuseUserPasswordForRootChanged( reuse ); + } +} + +void +Config::setRequireStrongPasswords( bool strong ) +{ + if ( strong != m_requireStrongPasswords ) + { + m_requireStrongPasswords = strong; + emit requireStrongPasswordsChanged( strong ); + } +} + + STATICTEST void setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroups ) { @@ -377,4 +398,10 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) m_writeRootPassword = CalamaresUtils::getBool( configurationMap, "setRootPassword", true ); Calamares::JobQueue::instance()->globalStorage()->insert( "setRootPassword", m_writeRootPassword ); + + m_reuseUserPasswordForRoot = CalamaresUtils::getBool( configurationMap, "doReusePassword", false ); + + m_permitWeakPasswords = CalamaresUtils::getBool( configurationMap, "allowWeakPasswords", false ); + m_requireStrongPasswords + = !m_permitWeakPasswords || !CalamaresUtils::getBool( configurationMap, "allowWeakPasswordsDefault", false ); } diff --git a/src/modules/users/Config.h b/src/modules/users/Config.h index b84dc5aaf..8c30dad4c 100644 --- a/src/modules/users/Config.h +++ b/src/modules/users/Config.h @@ -42,6 +42,14 @@ class Config : public QObject Q_PROPERTY( QString hostName READ hostName WRITE setHostName NOTIFY hostNameChanged ) Q_PROPERTY( QString hostNameStatus READ hostNameStatus NOTIFY hostNameStatusChanged ) + Q_PROPERTY( bool writeRootPassword READ writeRootPassword CONSTANT ) + Q_PROPERTY( bool reuseUserPasswordForRoot READ reuseUserPasswordForRoot WRITE setReuseUserPasswordForRoot NOTIFY + reuseUserPasswordForRootChanged ) + + Q_PROPERTY( bool permitWeakPasswords READ permitWeakPasswords CONSTANT ) + Q_PROPERTY( bool requireStrongPasswords READ requireStrongPasswords WRITE setRequireStrongPasswords NOTIFY + requireStrongPasswordsChanged ) + public: Config( QObject* parent = nullptr ); ~Config(); @@ -76,6 +84,12 @@ public: bool doAutoLogin() const { return m_doAutoLogin; } /// Should the root password be written (if false, no password is set and the root account is disabled for login) bool writeRootPassword() const { return m_writeRootPassword; } + /// Should the user's password be used for root, too? (if root is written at all) + bool reuseUserPasswordForRoot() const { return m_reuseUserPasswordForRoot; } + /// Show UI to change the "require strong password" setting? + bool permitWeakPasswords() const { return m_permitWeakPasswords; } + /// Current setting for "require strong password"? + bool requireStrongPasswords() const { return m_requireStrongPasswords; } const QStringList& defaultGroups() const { return m_defaultGroups; } @@ -109,6 +123,11 @@ public Q_SLOTS: /// Sets the autologin flag void setAutoLogin( bool b ); + /// Set to true to use the user password, unchanged, for root too + void setReuseUserPasswordForRoot( bool reuse ); + /// Change setting for "require strong password" + void setRequireStrongPasswords( bool strong ); + signals: void userShellChanged( const QString& ); void autologinGroupChanged( const QString& ); @@ -119,6 +138,8 @@ signals: void hostNameChanged( const QString& ); void hostNameStatusChanged( const QString& ); void autoLoginChanged( bool ); + void reuseUserPasswordForRootChanged( bool ); + void requireStrongPasswordsChanged( bool ); private: QStringList m_defaultGroups; @@ -129,7 +150,12 @@ private: QString m_loginName; QString m_hostName; bool m_doAutoLogin = false; + bool m_writeRootPassword = true; + bool m_reuseUserPasswordForRoot = false; + + bool m_permitWeakPasswords = false; + bool m_requireStrongPasswords = true; bool m_customLoginName = false; bool m_customHostName = false; diff --git a/src/modules/users/UsersPage.cpp b/src/modules/users/UsersPage.cpp index c4502256a..9054d60e7 100644 --- a/src/modules/users/UsersPage.cpp +++ b/src/modules/users/UsersPage.cpp @@ -105,6 +105,12 @@ UsersPage::UsersPage( Config* config, QWidget* parent ) { ui->setupUi( this ); + ui->checkBoxReusePassword->setVisible( m_config->writeRootPassword() ); + ui->checkBoxReusePassword->setChecked( m_config->reuseUserPasswordForRoot() ); + + ui->checkBoxValidatePassword->setVisible( m_config->permitWeakPasswords() ); + ui->checkBoxValidatePassword->setChecked( m_config->requireStrongPasswords() ); + // Connect signals and slots connect( ui->textBoxUserPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged ); connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged ); @@ -115,21 +121,7 @@ UsersPage::UsersPage( Config* config, QWidget* parent ) onRootPasswordTextChanged( ui->textBoxRootPassword->text() ); checkReady( isReady() ); } ); - connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( const int checked ) { - /* When "reuse" is checked, hide the fields for explicitly - * entering the root password. However, if we're going to - * disable the root password anyway, hide them all regardless of - * the checkbox -- so when writeRoot is false, checked needs - * to be true, to hide them all. - */ - const bool visible = m_config->writeRootPassword() ? !checked : false; - ui->labelChooseRootPassword->setVisible( visible ); - ui->labelRootPassword->setVisible( visible ); - ui->labelRootPasswordError->setVisible( visible ); - ui->textBoxRootPassword->setVisible( visible ); - ui->textBoxVerifiedRootPassword->setVisible( visible ); - checkReady( isReady() ); - } ); + connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, &UsersPage::onReuseUserPasswordChanged ); connect( ui->textBoxFullName, &QLineEdit::textEdited, config, &Config::setFullName ); connect( config, &Config::fullNameChanged, this, &UsersPage::onFullNameTextEdited ); @@ -147,13 +139,25 @@ UsersPage::UsersPage( Config* config, QWidget* parent ) } ); connect( config, &Config::autoLoginChanged, ui->checkBoxDoAutoLogin, &QCheckBox::setChecked ); - ui->checkBoxReusePassword->setVisible( m_config->writeRootPassword() ); - ui->checkBoxReusePassword->setChecked( true ); - ui->checkBoxValidatePassword->setChecked( true ); + if ( m_config->writeRootPassword() ) + { + connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( int checked ) { + m_config->setReuseUserPasswordForRoot( checked != Qt::Unchecked ); + } ); + connect( config, &Config::reuseUserPasswordForRootChanged, ui->checkBoxReusePassword, &QCheckBox::setChecked ); + } - setPasswordCheckboxVisible( false ); + if ( m_config->permitWeakPasswords() ) + { + connect( ui->checkBoxValidatePassword, &QCheckBox::stateChanged, this, [this]( int checked ) { + m_config->setRequireStrongPasswords( checked != Qt::Unchecked ); + } ); + connect( config, &Config::requireStrongPasswordsChanged, ui->checkBoxValidatePassword, &QCheckBox::setChecked ); + } CALAMARES_RETRANSLATE_SLOT( &UsersPage::retranslate ); + + onReuseUserPasswordChanged( m_config->reuseUserPasswordForRoot() ); } UsersPage::~UsersPage() @@ -335,25 +339,26 @@ UsersPage::onRootPasswordTextChanged( const QString& ) emit checkReady( isReady() ); } - -void -UsersPage::setPasswordCheckboxVisible( bool visible ) -{ - ui->checkBoxValidatePassword->setVisible( visible ); -} - -void -UsersPage::setValidatePasswordDefault( bool checked ) -{ - ui->checkBoxValidatePassword->setChecked( checked ); - emit checkReady( isReady() ); -} - void -UsersPage::setReusePasswordDefault( bool checked ) +UsersPage::onReuseUserPasswordChanged( const int checked ) { - ui->checkBoxReusePassword->setChecked( checked ); - emit checkReady( isReady() ); + /* When "reuse" is checked, hide the fields for explicitly + * entering the root password. However, if we're going to + * disable the root password anyway, hide them all regardless of + * the checkbox -- so when writeRoot is false, visible needs + * to be false, to hide them all. + * + * In principle this is only connected when writeRootPassword is @c true, + * but it is **always** called at least once in the constructor + * to set up initial visibility. + */ + const bool visible = m_config->writeRootPassword() ? !checked : false; + ui->labelChooseRootPassword->setVisible( visible ); + ui->labelRootPassword->setVisible( visible ); + ui->labelRootPasswordError->setVisible( visible ); + ui->textBoxRootPassword->setVisible( visible ); + ui->textBoxVerifiedRootPassword->setVisible( visible ); + checkReady( isReady() ); } void diff --git a/src/modules/users/UsersPage.h b/src/modules/users/UsersPage.h index b8cb0f06a..5e0909b54 100644 --- a/src/modules/users/UsersPage.h +++ b/src/modules/users/UsersPage.h @@ -50,10 +50,6 @@ public: void onActivate(); - void setPasswordCheckboxVisible( bool visible ); - void setValidatePasswordDefault( bool checked ); - void setReusePasswordDefault( bool checked ); - /** @brief Process entries in the passwordRequirements config entry * * Called once for each item in the config entry, which should @@ -73,6 +69,7 @@ protected slots: void reportHostNameStatus( const QString& ); void onPasswordTextChanged( const QString& ); void onRootPasswordTextChanged( const QString& ); + void onReuseUserPasswordChanged( const int ); signals: void checkReady( bool ); diff --git a/src/modules/users/UsersViewStep.cpp b/src/modules/users/UsersViewStep.cpp index 39d06b64a..092826d24 100644 --- a/src/modules/users/UsersViewStep.cpp +++ b/src/modules/users/UsersViewStep.cpp @@ -174,8 +174,6 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap ) (void)this->widget(); using CalamaresUtils::getBool; - m_widget->setReusePasswordDefault( getBool( configurationMap, "doReusePassword", false ) ); - if ( configurationMap.contains( "passwordRequirements" ) && configurationMap.value( "passwordRequirements" ).type() == QVariant::Map ) { @@ -187,9 +185,6 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap ) } } - m_widget->setPasswordCheckboxVisible( getBool( configurationMap, "allowWeakPasswords", false ) ); - m_widget->setValidatePasswordDefault( !getBool( configurationMap, "allowWeakPasswordsDefault", false ) ); - using Action = SetHostNameJob::Action; QString hostnameActionString = CalamaresUtils::getString( configurationMap, "setHostname" );