Merge pull request #1205 from ZeldaZach/fix_1173

Server Name Rules Information
This commit is contained in:
Zach 2015-07-04 19:37:50 -04:00
commit 31890450dc
7 changed files with 75 additions and 17 deletions

View file

@ -30,6 +30,10 @@
#include <QDateTime> #include <QDateTime>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QApplication> #include <QApplication>
#if QT_VERSION < 0x050000
// for Qt::escape()
#include <QtGui/qtextdocument.h>
#endif
#include "main.h" #include "main.h"
#include "window_main.h" #include "window_main.h"
@ -79,7 +83,7 @@ void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &even
break; break;
} }
case Event_ConnectionClosed::SERVER_SHUTDOWN: reasonStr = tr("Scheduled server shutdown."); break; case Event_ConnectionClosed::SERVER_SHUTDOWN: reasonStr = tr("Scheduled server shutdown."); break;
case Event_ConnectionClosed::USERNAMEINVALID: reasonStr = tr("Invalid username.\nYou may only use A-Z, a-z, 0-9, _, ., and - in your username."); break; case Event_ConnectionClosed::USERNAMEINVALID: reasonStr = tr("Invalid username."); break;
default: reasonStr = QString::fromStdString(event.reason_str()); default: reasonStr = QString::fromStdString(event.reason_str());
} }
QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr)); QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr));
@ -302,9 +306,10 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
QMessageBox::critical(this, tr("Error"), bannedStr); QMessageBox::critical(this, tr("Error"), bannedStr);
break; break;
} }
case Response::RespUsernameInvalid: case Response::RespUsernameInvalid: {
QMessageBox::critical(this, tr("Error"), tr("Invalid username.\nYou may only use A-Z, a-z, 0-9, _, ., and - in your username.")); QMessageBox::critical(this, tr("Error"), extractInvalidUsernameMessage(reasonStr));
break; break;
}
case Response::RespRegistrationRequired: case Response::RespRegistrationRequired:
if (QMessageBox::question(this, tr("Error"), tr("This server requires user registration. Do you want to register now?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { if (QMessageBox::question(this, tr("Error"), tr("This server requires user registration. Do you want to register now?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
actRegister(); actRegister();
@ -328,6 +333,41 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
actConnect(); actConnect();
} }
QString MainWindow::extractInvalidUsernameMessage(QString & in)
{
QString out = tr("Invalid username.") + "<br/>";
QStringList rules = in.split(QChar('|'));
if (rules.size() == 7)
{
out += tr("Your username must respect these rules:") + "<br><ul>";
out += "<li>" + tr("is %1 - %2 characters long").arg(rules.at(0)).arg(rules.at(1)) + "</li>";
out += "<li>" + tr("can %1 contain lowercase characters").arg((rules.at(2).toInt() > 0) ? "" : tr("NOT")) + "</li>";
out += "<li>" + tr("can %1 contain uppercase characters").arg((rules.at(3).toInt() > 0) ? "" : tr("NOT")) + "</li>";
out += "<li>" + tr("can %1 contain numeric characters").arg((rules.at(4).toInt() > 0) ? "" : tr("NOT")) + "</li>";
if (rules.at(6).size() > 0)
{
out += "<li>" + tr("can contain the following punctuation: %1").arg(
#if QT_VERSION < 0x050000
Qt::escape(rules.at(6))
#else
rules.at(6).toHtmlEscaped()
#endif
) + "</li>";
}
out += "<li>" + tr("first character can %1 be a punctuation mark").arg((rules.at(5).toInt() > 0) ? "" : tr("NOT")) + "</li>";
out += "</ul>";
}
else
{
out += tr("You may only use A-Z, a-z, 0-9, _, ., and - in your username.");
}
return out;
}
void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime) void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime)
{ {
switch (r) { switch (r) {
@ -358,9 +398,10 @@ void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quin
QMessageBox::critical(this, tr("Error"), bannedStr); QMessageBox::critical(this, tr("Error"), bannedStr);
break; break;
} }
case Response::RespUsernameInvalid: case Response::RespUsernameInvalid: {
QMessageBox::critical(this, tr("Error"), tr("Invalid username.\nYou may only use A-Z, a-z, 0-9, _, ., and - in your username.")); QMessageBox::critical(this, tr("Error"), extractInvalidUsernameMessage(reasonStr));
break; break;
}
case Response::RespRegistrationFailed: case Response::RespRegistrationFailed:
QMessageBox::critical(this, tr("Error"), tr("Registration failed for a technical problem on the server.")); QMessageBox::critical(this, tr("Error"), tr("Registration failed for a technical problem on the server."));
break; break;

View file

@ -109,6 +109,7 @@ public:
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
void changeEvent(QEvent *event); void changeEvent(QEvent *event);
QString extractInvalidUsernameMessage(QString & in);
}; };
#endif #endif

View file

@ -25,7 +25,7 @@ public:
virtual DeckList *getDeckFromDatabase(int /* deckId */, int /* userId */) { return 0; } virtual DeckList *getDeckFromDatabase(int /* deckId */, int /* userId */) { return 0; }
virtual qint64 startSession(const QString & /* userName */, const QString & /* address */) { return 0; } virtual qint64 startSession(const QString & /* userName */, const QString & /* address */) { return 0; }
virtual bool usernameIsValid(const QString & /*userName */) { return true; }; virtual bool usernameIsValid(const QString & /*userName */, QString & /* error */) { return true; };
public slots: public slots:
virtual void endSession(qint64 /* sessionId */ ) { } virtual void endSession(qint64 /* sessionId */ ) { }
public: public:

View file

@ -388,7 +388,12 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
} }
case NotLoggedIn: return Response::RespWrongPassword; case NotLoggedIn: return Response::RespWrongPassword;
case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession; case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession;
case UsernameInvalid: return Response::RespUsernameInvalid; case UsernameInvalid: {
Response_Login *re = new Response_Login;
re->set_denied_reason_str(reasonStr.toStdString());
rc.setResponseExtension(re);
return Response::RespUsernameInvalid;
}
case RegistrationRequired: return Response::RespRegistrationRequired; case RegistrationRequired: return Response::RespRegistrationRequired;
case UserIsInactive: return Response::RespAccountNotActivated; case UserIsInactive: return Response::RespAccountNotActivated;
default: authState = res; default: authState = res;

View file

@ -118,24 +118,29 @@ bool Servatrice_DatabaseInterface::execSqlQuery(QSqlQuery *query)
return false; return false;
} }
bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user) bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user, QString & error)
{ {
int maxNameLength = settingsCache->value("users/maxnamelength", 12).toInt();
int minNameLength = settingsCache->value("users/minnamelength", 6).toInt(); int minNameLength = settingsCache->value("users/minnamelength", 6).toInt();
int maxNameLength = settingsCache->value("users/maxnamelength", 12).toInt();
bool allowLowercase = settingsCache->value("users/allowlowercase", true).toBool();
bool allowUppercase = settingsCache->value("users/allowuppercase", true).toBool();
bool allowNumerics = settingsCache->value("users/allownumerics", true).toBool();
bool allowPunctuationPrefix = settingsCache->value("users/allowpunctuationprefix", false).toBool();
QString allowedPunctuation = settingsCache->value("users/allowedpunctuation", "_").toString();
error = QString("%1|%2|%3|%4|%5|%6|%7").arg(minNameLength).arg(maxNameLength).arg(allowLowercase).arg(allowUppercase).arg(allowNumerics).arg(allowPunctuationPrefix).arg(allowedPunctuation);
if (user.length() < minNameLength || user.length() > maxNameLength) if (user.length() < minNameLength || user.length() > maxNameLength)
return false; return false;
bool allowPunctuationPrefix = settingsCache->value("users/allowpunctuationprefix", false).toBool();
QString allowedPunctuation = settingsCache->value("users/allowedpunctuation", "_").toString();
if (!allowPunctuationPrefix && allowedPunctuation.contains(user.at(0))) if (!allowPunctuationPrefix && allowedPunctuation.contains(user.at(0)))
return false; return false;
QString regEx("["); QString regEx("[");
if (settingsCache->value("users/allowlowercase", true).toBool()) if (allowLowercase)
regEx.append("a-z"); regEx.append("a-z");
if (settingsCache->value("users/allowuppercase", true).toBool()) if (allowUppercase)
regEx.append("A-Z"); regEx.append("A-Z");
if(settingsCache->value("users/allownumerics", true).toBool()) if(allowNumerics)
regEx.append("0-9"); regEx.append("0-9");
regEx.append(QRegExp::escape(allowedPunctuation)); regEx.append(QRegExp::escape(allowedPunctuation));
regEx.append("]+"); regEx.append("]+");
@ -242,7 +247,7 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
if (!checkSql()) if (!checkSql())
return UnknownUser; return UnknownUser;
if (!usernameIsValid(user)) if (!usernameIsValid(user, reasonStr))
return UsernameInvalid; return UsernameInvalid;
if (checkUserIsBanned(handler->getAddress(), user, reasonStr, banSecondsLeft)) if (checkUserIsBanned(handler->getAddress(), user, reasonStr, banSecondsLeft))

View file

@ -62,7 +62,7 @@ public:
void lockSessionTables(); void lockSessionTables();
void unlockSessionTables(); void unlockSessionTables();
bool userSessionExists(const QString &userName); bool userSessionExists(const QString &userName);
bool usernameIsValid(const QString &user); bool usernameIsValid(const QString &user, QString & error);
bool checkUserIsBanned(const QString &ipAddress, const QString &userName, QString &banReason, int &banSecondsRemaining); bool checkUserIsBanned(const QString &ipAddress, const QString &userName, QString &banReason, int &banSecondsRemaining);
bool getRequireRegistration(); bool getRequireRegistration();

View file

@ -789,8 +789,14 @@ Response::ResponseCode ServerSocketInterface::cmdRegisterAccount(const Command_R
} }
// TODO: Move this method outside of the db interface // TODO: Move this method outside of the db interface
if (!sqlInterface->usernameIsValid(userName)) QString errorString;
if (!sqlInterface->usernameIsValid(userName, errorString))
{
Response_Register *re = new Response_Register;
re->set_denied_reason_str(errorString.toStdString());
rc.setResponseExtension(re);
return Response::RespUsernameInvalid; return Response::RespUsernameInvalid;
}
if(sqlInterface->userExists(userName)) if(sqlInterface->userExists(userName))
return Response::RespUserAlreadyExists; return Response::RespUserAlreadyExists;