Add email registration restriction (#2350)

* Add ability to limit number of account registrations with same email address

This commit adds server side functionality that will allow operators to
limit the number of accounts that can be registered to the server with
the same email address.

* Updated ini wording

Updated configuration file wording for better description.
This commit is contained in:
woogerboy21 2017-01-07 11:26:23 -05:00 committed by GitHub
parent 3e39432ccc
commit a85b0dcbba
8 changed files with 37 additions and 2 deletions

View file

@ -444,7 +444,7 @@ void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quin
QMessageBox::critical(this, tr("Registration denied"), tr("It's mandatory to specify a valid email address when registering."));
break;
case Response::RespTooManyRequests:
QMessageBox::critical(this, tr("Registration denied"), tr("Too many registration attempts from your IP address."));
QMessageBox::critical(this, tr("Registration denied"), tr("Too many registration attempts, please try again later or contact the server operator for further details."));
break;
case Response::RespPasswordTooShort:
QMessageBox::critical(this, tr("Registration denied"), tr("Password too short."));

View file

@ -45,6 +45,7 @@ public:
enum LogMessage_TargetType { MessageTargetRoom, MessageTargetGame, MessageTargetChat, MessageTargetIslRoom };
virtual void logMessage(const int /* senderId */, const QString & /* senderName */, const QString & /* senderIp */, const QString & /* logMessage */, LogMessage_TargetType /* targetType */, const int /* targetId */, const QString & /* targetName */) { };
bool checkUserIsBanned(Server_ProtocolHandler *session, QString &banReason, int &banSecondsRemaining);
virtual int checkNumberOfUserAccounts(const QString & /* email */) { return 0; };
virtual bool changeUserPassword(const QString & /* user */, const QString & /* oldPassword */, const QString & /* newPassword */) { return true; };
virtual QChar getGenderChar(ServerInfo_User_Gender const & /* gender */) { return QChar('u'); };
};

View file

@ -140,6 +140,10 @@ disallowedregexp=""
; account activated. Default true.
;requireemailactivation=true
; Set this number to the maximum number of accounts any one user can use to create new accounts
; using the same email address. 0 = Unlimited number of accounts (default).
;maxaccountsperemail=0
[smtp]
; Enable the internal smtp client to send registration emails. If you would like to

View file

@ -242,6 +242,7 @@ bool Servatrice::initServer()
if (getRegistrationEnabled()) {
qDebug() << "Require email address to register: " << getRequireEmailForRegistrationEnabled();
qDebug() << "Require email activation via token: " << getRequireEmailActivationEnabled();
if (getMaxAccountsPerEmail()) { qDebug() << "Maximum number of accounts per email: " << getMaxAccountsPerEmail(); } else { qDebug() << "Maximum number of accounts per email: unlimited"; }
qDebug() << "Enable Internal SMTP Client: " << getEnableInternalSMTPClient();
if (!getEnableInternalSMTPClient())
{
@ -836,6 +837,10 @@ bool Servatrice::getEnableLogQuery() const {
return settingsCache->value("logging/enablelogquery", false).toBool();
}
int Servatrice::getMaxAccountsPerEmail() const {
return settingsCache->value("registration/maxaccountsperemail", 0).toInt();
}
bool Servatrice::getEnableInternalSMTPClient() const {
return settingsCache->value("smtp/enableinternalsmtpclient", true).toBool();
}

View file

@ -207,6 +207,7 @@ public:
int getMaxTcpUserLimit() const;
int getMaxWebSocketUserLimit() const;
int getUsersWithAddress(const QHostAddress &address) const;
int getMaxAccountsPerEmail() const;
QList<AbstractServerSocketInterface *> getUsersWithAddressAsList(const QHostAddress &address) const;
void incTxBytes(quint64 num);
void incRxBytes(quint64 num);

View file

@ -1109,3 +1109,22 @@ QList<ServerInfo_ChatMessage> Servatrice_DatabaseInterface::getMessageLogHistory
return results;
}
int Servatrice_DatabaseInterface::checkNumberOfUserAccounts(const QString &email)
{
if (!checkSql())
return 0;
QSqlQuery *query = prepareQuery("SELECT count(email) FROM {prefix}_users WHERE email = :user_email");
query->bindValue(":user_email", email);
if (!execSqlQuery(query)) {
qDebug("Failed to identify the number of users accounts for users email address: SQL Error");
return 0;
}
if (query->next())
return query->value(0).toInt();
return 0;
}

View file

@ -69,7 +69,7 @@ public:
bool userSessionExists(const QString &userName);
bool usernameIsValid(const QString &user, QString & error);
bool checkUserIsBanned(const QString &ipAddress, const QString &userName, const QString &clientId, QString &banReason, int &banSecondsRemaining);
int checkNumberOfUserAccounts(const QString &email);
bool registerUser(const QString &userName, const QString &realName, ServerInfo_User_Gender const &gender,
const QString &password, const QString &emailAddress, const QString &country, QString &token, bool active = false);
bool activateUser(const QString &userName, const QString &token);

View file

@ -906,6 +906,11 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
if(sqlInterface->userExists(userName))
return Response::RespUserAlreadyExists;
if (servatrice->getMaxAccountsPerEmail() && !(sqlInterface->checkNumberOfUserAccounts(emailAddress) < servatrice->getMaxAccountsPerEmail()))
{
return Response::RespTooManyRequests;
}
QString banReason;
int banSecondsRemaining;
if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, clientId, banReason, banSecondsRemaining))