Passwords: introduce password-checking

- Introduce a map 'passwordRequirements' in users.conf,
   which is a list of named requirements. There are only
   two settings right now, min and max length, but
   additional checks can easily be added in UsersPage.cpp
   by defining additional lambda's to check the given
   password string.
 - Add PasswordCheck instances as needed, with functions
   to check acceptability and to produce messages on rejection.
 - Documentation in the users.conf file itself.

 - In passing, refactor setting of pixmaps on labels.

FIXES #790
This commit is contained in:
Adriaan de Groot 2017-09-18 16:08:21 +02:00
parent c2a69ea943
commit d839f8e0b3
4 changed files with 189 additions and 42 deletions

View file

@ -28,7 +28,10 @@
#include <QWidget>
namespace Ui {
#include <functional>
namespace Ui
{
class Page_UserSetup;
}
@ -49,6 +52,8 @@ public:
void setAutologinDefault( bool checked );
void setReusePasswordDefault( bool checked );
void addPasswordCheck( const QString& key, const QVariant& value );
protected slots:
void onFullNameTextEdited( const QString& );
void fillSuggestions();
@ -65,6 +70,42 @@ signals:
private:
Ui::Page_UserSetup* ui;
/**
* Support for (dynamic) checks on the password's validity.
* This can be used to implement password requirements like
* "at least 6 characters". Function addPasswordCheck()
* instantiates these and adds them to the list of checks.
*/
class PasswordCheck
{
public:
/** Return true if the string is acceptable. */
using AcceptFunc = std::function<bool( const QString& )>;
using MessageFunc = std::function<QString()>;
/** Generate a @p message if @p filter returns true */
PasswordCheck( MessageFunc message, AcceptFunc filter );
/** Yields @p message if @p filter returns true */
PasswordCheck( const QString& message, AcceptFunc filter );
/** Null check, always returns empty */
PasswordCheck();
/** Applies this check to the given password string @p s
* and returns an empty string if the password is ok
* according to this filter. Returns a message describing
* what is wrong if not.
*/
QString filter( const QString& s ) const
{
return m_accept( s ) ? QString() : m_message();
}
private:
MessageFunc m_message;
AcceptFunc m_accept;
} ;
QVector<PasswordCheck> m_passwordChecks;
const QRegExp USERNAME_RX = QRegExp( "^[a-z_][a-z0-9_-]*[$]?$" );
const QRegExp HOSTNAME_RX = QRegExp( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" );
const int USERNAME_MAX_LENGTH = 31;