[users] Move login validation to Config object

- add a loginNameStatus which is a QString (empty if things are ok)
  stating what's wrong with the loginName, if anything.
main
Adriaan de Groot 5 years ago
parent a564d7a753
commit 40d7d1baac

@ -28,6 +28,10 @@
#include <QFile>
#include <QRegExp>
#include <QRegExpValidator>
static const QRegExp USERNAME_RX( "^[a-z_][a-z0-9_-]*[$]?$" );
static constexpr const int USERNAME_MAX_LENGTH = 31;
Config::Config( QObject* parent )
: QObject( parent )
@ -49,7 +53,7 @@ Config::setUserShell( const QString& shell )
}
static inline void
setGS( const QString& key, const QString& group )
insertInGlobalStorage( const QString& key, const QString& group )
{
auto* gs = Calamares::JobQueue::instance()->globalStorage();
if ( !gs || group.isEmpty() )
@ -62,14 +66,14 @@ setGS( const QString& key, const QString& group )
void
Config::setAutologinGroup( const QString& group )
{
setGS( QStringLiteral( "autologinGroup" ), group );
insertInGlobalStorage( QStringLiteral( "autologinGroup" ), group );
emit autologinGroupChanged( group );
}
void
Config::setSudoersGroup( const QString& group )
{
setGS( QStringLiteral( "sudoersGroup" ), group );
insertInGlobalStorage( QStringLiteral( "sudoersGroup" ), group );
emit sudoersGroupChanged( group );
}
@ -82,7 +86,53 @@ Config::setLoginName( const QString& login )
m_customLoginName = !login.isEmpty();
m_loginName = login;
emit loginNameChanged( login );
emit loginNameStatusChanged( loginNameStatus() );
}
}
const QStringList&
Config::forbiddenLoginNames()
{
static QStringList forbidden { "root" };
return forbidden;
}
QString
Config::loginNameStatus() const
{
// An empty login is "ok", even if it isn't really
if ( m_loginName.isEmpty() )
{
return QString();
}
QRegExpValidator validateEntireLoginName( USERNAME_RX );
QRegExpValidator validateFirstLetter( QRegExp( "[a-z_].*" ) ); // anchors are implicit in QRegExpValidator
int pos = -1;
if ( m_loginName.length() > USERNAME_MAX_LENGTH )
{
return tr( "Your username is too long." );
}
QString login( m_loginName ); // make a copy because validate() doesn't take const&
if ( validateFirstLetter.validate( login, pos ) == QValidator::Invalid )
{
return tr( "Your username must start with a lowercase letter or underscore." );
}
if ( validateEntireLoginName.validate( login, pos ) == QValidator::Invalid )
{
return tr( "Only lowercase letters, numbers, underscore and hyphen are allowed." );
}
for ( const QString& badName : forbiddenLoginNames() )
{
if ( 0 == QString::compare( badName, m_loginName, Qt::CaseSensitive ) )
{
return tr( "'%1' is not allowed as user name." ).arg( badName );
}
}
return QString();
}
void
@ -133,7 +183,6 @@ guessProductName()
static QString
makeLoginNameSuggestion( const QStringList& parts )
{
static const QRegExp USERNAME_RX( "^[a-z_][a-z0-9_-]*[$]?$" );
if ( parts.isEmpty() || parts.first().isEmpty() )
{
return QString();
@ -199,6 +248,7 @@ Config::setFullName( const QString& name )
{
m_loginName = login;
emit loginNameChanged( login );
emit loginNameStatusChanged( loginNameStatus() );
}
}
if ( !m_customHostName )

@ -35,6 +35,7 @@ class Config : public QObject
Q_PROPERTY( QString fullName READ fullName WRITE setFullName NOTIFY fullNameChanged )
Q_PROPERTY( QString loginName READ loginName WRITE setLoginName NOTIFY loginNameChanged )
Q_PROPERTY( QString loginNameStatus READ loginNameStatus NOTIFY loginNameStatusChanged )
Q_PROPERTY( QString hostName READ hostName WRITE setHostName NOTIFY hostNameChanged )
@ -60,10 +61,14 @@ public:
QString fullName() const { return m_fullName; }
/// The login name of the user
QString loginName() const { return m_loginName; }
/// Status message about login -- empty for "ok"
QString loginNameStatus() const;
/// The host name (name for the system)
QString hostName() const { return m_hostName; }
static const QStringList& forbiddenLoginNames();
public Q_SLOTS:
/** @brief Sets the user's shell if possible
*
@ -94,6 +99,7 @@ signals:
void sudoersGroupChanged( const QString& );
void fullNameChanged( const QString& );
void loginNameChanged( const QString& );
void loginNameStatusChanged( const QString& );
void hostNameChanged( const QString& );
private:

@ -46,7 +46,6 @@
#include <QRegExp>
#include <QRegExpValidator>
static const QRegExp USERNAME_RX( "^[a-z_][a-z0-9_-]*[$]?$" );
static const QRegExp HOSTNAME_RX( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" );
static constexpr const int USERNAME_MAX_LENGTH = 31;
static constexpr const int HOSTNAME_MIN_LENGTH = 2;
@ -129,7 +128,7 @@ UsersPage::UsersPage( Config* config, QWidget* parent )
connect( ui->textBoxLoginName, &QLineEdit::textEdited, config, &Config::setLoginName );
connect( config, &Config::loginNameChanged, ui->textBoxLoginName, &QLineEdit::setText );
connect( config, &Config::loginNameChanged, this, &UsersPage::validateUsernameText );
connect( config, &Config::loginNameStatusChanged, this, &UsersPage::reportLoginNameStatus );
setWriteRootPassword( true );
ui->checkBoxReusePassword->setChecked( true );
@ -277,55 +276,31 @@ UsersPage::onFullNameTextEdited( const QString& textRef )
checkReady( isReady() );
}
void
UsersPage::validateUsernameText( const QString& textRef )
UsersPage::reportLoginNameStatus( const QString& status )
{
QString text( textRef );
QRegExpValidator val_whole( USERNAME_RX );
QRegExpValidator val_start( QRegExp( "[a-z_].*" ) ); // anchors are implicit in QRegExpValidator
int pos = -1;
if ( text.isEmpty() )
{
ui->labelUsernameError->clear();
ui->labelUsername->clear();
m_readyUsername = false;
}
else if ( text.length() > USERNAME_MAX_LENGTH )
{
labelError( ui->labelUsername, ui->labelUsernameError, tr( "Your username is too long." ) );
m_readyUsername = false;
}
else if ( val_start.validate( text, pos ) == QValidator::Invalid )
{
labelError( ui->labelUsername,
ui->labelUsernameError,
tr( "Your username must start with a lowercase letter or underscore." ) );
m_readyUsername = false;
}
else if ( val_whole.validate( text, pos ) == QValidator::Invalid )
if ( status.isEmpty() )
{
labelError( ui->labelUsername,
ui->labelUsernameError,
tr( "Only lowercase letters, numbers, underscore and hyphen are allowed." ) );
m_readyUsername = false;
}
else if ( 0 == QString::compare( "root", text, Qt::CaseSensitive ) )
{
labelError( ui->labelUsername, ui->labelUsernameError, tr( "'root' is not allowed as user name." ) );
m_readyUsername = false;
if ( m_config->loginName().isEmpty() )
{
ui->labelUsernameError->clear();
ui->labelUsername->clear();
m_readyUsername = false;
}
else
{
labelOk( ui->labelUsername, ui->labelUsernameError );
m_readyUsername = true;
}
}
else
{
labelOk( ui->labelUsername, ui->labelUsernameError );
m_readyUsername = true;
labelError( ui->labelUsername, ui->labelUsernameError, status );
m_readyUsername = false;
}
emit checkReady( isReady() );
}
void
UsersPage::validateHostnameText( const QString& textRef )
{

@ -72,7 +72,7 @@ public:
protected slots:
void onFullNameTextEdited( const QString& );
void validateUsernameText( const QString& );
void reportLoginNameStatus( const QString& );
void validateHostnameText( const QString& );
void onPasswordTextChanged( const QString& );
void onRootPasswordTextChanged( const QString& );

Loading…
Cancel
Save