Simpler forgot password functionality (#2393)

* Simpler forgot password functionality (Server/Client)
This commit is contained in:
woogerboy21 2017-02-15 17:41:40 -05:00 committed by Zach H
parent b64eab204c
commit 0cfa6863d5
36 changed files with 1190 additions and 173 deletions

View file

@ -252,6 +252,12 @@ bool Servatrice::initServer()
}
}
qDebug() << "Forgot password enabled: " << getEnableForgotPassword();
if (getEnableForgotPassword()) {
qDebug() << "Forgot password token life (in minutes): " << getForgotPasswordTokenLife();
qDebug() << "Forgot password challenge on: " << getEnableForgotPasswordChallenge();
}
if (getDBTypeString() == "mysql") {
databaseType = DatabaseMySql;
} else {
@ -542,28 +548,51 @@ void Servatrice::statusUpdate()
query->bindValue(":rx", rx);
servatriceDatabaseInterface->execSqlQuery(query);
// send activation emails
if (getRegistrationEnabled() && getRequireEmailActivationEnabled() && getEnableInternalSMTPClient())
if (getRegistrationEnabled() && getEnableInternalSMTPClient())
{
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_activation_emails a left join {prefix}_users b on a.name = b.name");
if (!servatriceDatabaseInterface->execSqlQuery(query))
return;
if (getRequireEmailActivationEnabled())
{
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_activation_emails a left join {prefix}_users b on a.name = b.name");
if (!servatriceDatabaseInterface->execSqlQuery(query))
return;
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("delete from {prefix}_activation_emails where name = :name");
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("delete from {prefix}_activation_emails where name = :name");
while (query->next()) {
const QString userName = query->value(0).toString();
const QString emailAddress = query->value(1).toString();
const QString token = query->value(2).toString();
while (query->next()) {
const QString userName = query->value(0).toString();
const QString emailAddress = query->value(1).toString();
const QString token = query->value(2).toString();
if(smtpClient->enqueueActivationTokenMail(userName, emailAddress, token))
{
queryDelete->bindValue(":name", userName);
servatriceDatabaseInterface->execSqlQuery(queryDelete);
}
}
if (smtpClient->enqueueActivationTokenMail(userName, emailAddress, token))
{
queryDelete->bindValue(":name", userName);
servatriceDatabaseInterface->execSqlQuery(queryDelete);
}
}
}
smtpClient->sendAllEmails();
if (getEnableForgotPassword())
{
QSqlQuery *query = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from {prefix}_forgot_password a left join {prefix}_users b on a.name = b.name where a.emailed = 0");
if (!servatriceDatabaseInterface->execSqlQuery(query))
return;
QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery("update {prefix}_forgot_password set emailed = 1 where name = :name");
while (query->next()) {
const QString userName = query->value(0).toString();
const QString emailAddress = query->value(1).toString();
const QString token = query->value(2).toString();
if (smtpClient->enqueueForgotPasswordTokenMail(userName, emailAddress, token))
{
queryDelete->bindValue(":name", userName);
servatriceDatabaseInterface->execSqlQuery(queryDelete);
}
}
}
smtpClient->sendAllEmails();
}
}
@ -847,6 +876,18 @@ bool Servatrice::getEnableInternalSMTPClient() const {
return settingsCache->value("smtp/enableinternalsmtpclient", true).toBool();
}
bool Servatrice::getEnableForgotPassword() const {
return settingsCache->value("forgotpassword/enable", false).toBool();
}
int Servatrice::getForgotPasswordTokenLife() const {
return settingsCache->value("forgotpassword/tokenlife", 60).toInt();
}
bool Servatrice::getEnableForgotPasswordChallenge() const {
return settingsCache->value("forgotpassword/enablechallenge", false).toBool();
}
QString Servatrice::getEmailBlackList() const {
return settingsCache->value("registration/emailproviderblacklist").toString();
}

View file

@ -154,7 +154,6 @@ private:
QString getRoomsMethodString() const;
QString getISLNetworkSSLCertFile() const;
QString getISLNetworkSSLKeyFile() const;
int getServerStatusUpdateTime() const;
int getNumberOfTCPPools() const;
int getServerTCPPort() const;
@ -192,6 +191,8 @@ public:
bool getRequireEmailForRegistrationEnabled() const;
bool getRequireEmailActivationEnabled() const;
bool getEnableLogQuery() const;
bool getEnableForgotPassword() const;
bool getEnableForgotPasswordChallenge() const;
int getIdleClientTimeout() const;
int getServerID() const;
int getMaxGameInactivityTime() const;
@ -209,6 +210,7 @@ public:
int getMaxWebSocketUserLimit() const;
int getUsersWithAddress(const QHostAddress &address) const;
int getMaxAccountsPerEmail() const;
int getForgotPasswordTokenLife() const;
QList<AbstractServerSocketInterface *> getUsersWithAddressAsList(const QHostAddress &address) const;
void incTxBytes(quint64 num);
void incRxBytes(quint64 num);

View file

@ -176,9 +176,9 @@ bool Servatrice_DatabaseInterface::registerUser(const QString &userName, const Q
token = active ? QString() : PasswordHasher::generateActivationToken();
QSqlQuery *query = prepareQuery("insert into {prefix}_users "
"(name, realname, gender, password_sha512, email, country, registrationDate, active, token) "
"values "
"(:userName, :realName, :gender, :password_sha512, :email, :country, UTC_TIMESTAMP(), :active, :token)");
"(name, realname, gender, password_sha512, email, country, registrationDate, active, token, admin, avatar_bmp, clientid, privlevel, privlevelStartDate, privlevelEndDate) "
"values "
"(:userName, :realName, :gender, :password_sha512, :email, :country, UTC_TIMESTAMP(), :active, :token, 0, '', '', 'NONE', UTC_TIMESTAMP(), UTC_TIMESTAMP())");
query->bindValue(":userName", userName);
query->bindValue(":realName", realName);
query->bindValue(":gender", getGenderChar(gender));
@ -831,41 +831,43 @@ void Servatrice_DatabaseInterface::logMessage(const int senderId, const QString
execSqlQuery(query);
}
bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, const QString &oldPassword, const QString &newPassword)
bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, const QString &oldPassword, const QString &newPassword, const bool &force = false)
{
if(server->getAuthenticationMethod() != Servatrice::AuthenticationSql)
return true;
return false;
if (!checkSql())
return true;
return false;
QString error;
if (!usernameIsValid(user, error))
return true;
return false;
QSqlQuery *passwordQuery = prepareQuery("select password_sha512 from {prefix}_users where name = :name");
passwordQuery->bindValue(":name", user);
if (!execSqlQuery(passwordQuery)) {
qDebug("Change password denied: SQL error");
return true;
if (!force) {
if (!execSqlQuery(passwordQuery)) {
qDebug("Change password denied: SQL error");
return false;
}
if (!passwordQuery->next())
return false;
const QString correctPassword = passwordQuery->value(0).toString();
if (correctPassword != PasswordHasher::computeHash(oldPassword, correctPassword.left(16)))
return false;
}
if (!passwordQuery->next())
return true;
const QString correctPassword = passwordQuery->value(0).toString();
if (correctPassword != PasswordHasher::computeHash(oldPassword, correctPassword.left(16)))
return true;
QString passwordSha512 = PasswordHasher::computeHash(newPassword, PasswordHasher::generateRandomSalt());
passwordQuery = prepareQuery("update {prefix}_users set password_sha512=:password where name = :name");
passwordQuery->bindValue(":password", passwordSha512);
passwordQuery->bindValue(":name", user);
if (!execSqlQuery(passwordQuery)) {
qDebug("Change password denied: SQL error");
if (execSqlQuery(passwordQuery))
return true;
}
return false;
}
@ -1128,3 +1130,91 @@ int Servatrice_DatabaseInterface::checkNumberOfUserAccounts(const QString &email
return 0;
}
bool Servatrice_DatabaseInterface::addForgotPassword(const QString &user)
{
if (!checkSql())
return false;
if (!updateUserToken(PasswordHasher::generateActivationToken(), user))
return false;
QSqlQuery *query = prepareQuery("insert into {prefix}_forgot_password (name,requestDate) values (:username,NOW())");
query->bindValue(":username", user);
if (execSqlQuery(query))
return true;
return false;
}
bool Servatrice_DatabaseInterface::removeForgotPassword(const QString &user)
{
if (!checkSql())
return false;
QSqlQuery *query = prepareQuery("delete from {prefix}_forgot_password where name = :username");
query->bindValue(":username", user);
if (execSqlQuery(query))
return true;
return false;
}
bool Servatrice_DatabaseInterface::doesForgotPasswordExist(const QString &user)
{
if (!checkSql())
return false;
QSqlQuery *query = prepareQuery("select count(name) from {prefix}_forgot_password where name = :user_name AND requestDate > (now() - interval :minutes minute)");
query->bindValue(":user_name", user);
query->bindValue(":minutes", QString::number(server->getForgotPasswordTokenLife()));
if (!execSqlQuery(query))
return false;
if (query->next())
if (query->value("count(name)").toInt() > 0)
return true;
return false;
}
bool Servatrice_DatabaseInterface::updateUserToken(const QString & token, const QString &user)
{
if (!checkSql())
return false;
if (token.isEmpty() || user.isEmpty())
return false;
QSqlQuery *query = prepareQuery("update {prefix}_users set token = :token where name = :user_name");
query->bindValue(":user_name", user);
query->bindValue(":token", token);
if (execSqlQuery(query))
return true;
return false;
}
bool Servatrice_DatabaseInterface::validateTableColumnStringData(const QString &table, const QString &column, const QString &_user, const QString &_datatocheck)
{
if (!checkSql())
return false;
if (table.isEmpty() || column.isEmpty() ||_user.isEmpty() || _datatocheck.isEmpty())
return false;
QString formatedQuery = QString("select %1 from %2 where name = :user_name").arg(column).arg(table);
QSqlQuery *query = prepareQuery(formatedQuery);
query->bindValue(":user_name", _user);
if (!execSqlQuery(query))
return false;
if (query->next())
if (query->value(column).toString() == _datatocheck)
return true;
return false;
}

View file

@ -9,7 +9,7 @@
#include "server.h"
#include "server_database_interface.h"
#define DATABASE_SCHEMA_VERSION 20
#define DATABASE_SCHEMA_VERSION 21
class Servatrice;
@ -70,19 +70,22 @@ public:
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 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);
void updateUsersClientID(const QString &userName, const QString &userClientID);
void updateUsersLastLoginData(const QString &userName, const QString &clientVersion);
void logMessage(const int senderId, const QString &senderName, const QString &senderIp, const QString &logMessage,
LogMessage_TargetType targetType, const int targetId, const QString &targetName);
bool changeUserPassword(const QString &user, const QString &oldPassword, const QString &newPassword);
void logMessage(const int senderId, const QString &senderName, const QString &senderIp, const QString &logMessage, LogMessage_TargetType targetType, const int targetId, const QString &targetName);
bool changeUserPassword(const QString &user, const QString &oldPassword, const QString &newPassword, const bool &force);
QChar getGenderChar(ServerInfo_User_Gender const &gender);
QList<ServerInfo_Ban> getUserBanHistory(const QString userName);
bool addWarning(const QString userName, const QString adminName, const QString warningReason, const QString clientID);
QList<ServerInfo_Warning> getUserWarnHistory(const QString userName);
QList<ServerInfo_ChatMessage> getMessageLogHistory(const QString &user, const QString &ipaddress, const QString &gamename, const QString &gameid, const QString &message, bool &chat, bool &game, bool &room, int &range, int &maxresults);
bool addForgotPassword(const QString &user);
bool removeForgotPassword(const QString &user);
bool doesForgotPasswordExist(const QString &user);
bool updateUserToken(const QString &token, const QString &user);
bool validateTableColumnStringData(const QString &table, const QString &column, const QString &_user, const QString &_datatocheck);
};
#endif

View file

@ -62,6 +62,7 @@
#include "pb/response_warn_history.pb.h"
#include "pb/response_warn_list.pb.h"
#include "pb/response_viewlog_history.pb.h"
#include "pb/response_forgotpasswordrequest.pb.h"
#include "pb/serverinfo_replay.pb.h"
#include "pb/serverinfo_user.pb.h"
#include "pb/serverinfo_deckstorage.pb.h"
@ -150,7 +151,9 @@ Response::ResponseCode AbstractServerSocketInterface::processExtendedSessionComm
case SessionCommand::REPLAY_DELETE_MATCH: return cmdReplayDeleteMatch(cmd.GetExtension(Command_ReplayDeleteMatch::ext), rc);
case SessionCommand::REGISTER: return cmdRegisterAccount(cmd.GetExtension(Command_Register::ext), rc); break;
case SessionCommand::ACTIVATE: return cmdActivateAccount(cmd.GetExtension(Command_Activate::ext), rc); break;
case SessionCommand::FORGOT_PASSWORD_REQUEST: return cmdForgotPasswordRequest(cmd.GetExtension(Command_ForgotPasswordRequest::ext), rc); break;
case SessionCommand::FORGOT_PASSWORD_RESET: return cmdForgotPasswordReset(cmd.GetExtension(Command_ForgotPasswordReset::ext), rc); break;
case SessionCommand::FORGOT_PASSWORD_CHALLENGE: return cmdForgotPasswordChallenge(cmd.GetExtension(Command_ForgotPasswordChallenge::ext), rc); break;
case SessionCommand::ACCOUNT_EDIT: return cmdAccountEdit(cmd.GetExtension(Command_AccountEdit::ext), rc);
case SessionCommand::ACCOUNT_IMAGE: return cmdAccountImage(cmd.GetExtension(Command_AccountImage::ext), rc);
case SessionCommand::ACCOUNT_PASSWORD: return cmdAccountPassword(cmd.GetExtension(Command_AccountPassword::ext), rc);
@ -1054,14 +1057,86 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountPassword(const C
QString userName = QString::fromStdString(userInfo->name());
bool changeFailed = databaseInterface->changeUserPassword(userName, oldPassword, newPassword);
if(changeFailed)
if(!databaseInterface->changeUserPassword(userName, oldPassword, newPassword, false))
return Response::RespWrongPassword;
return Response::RespOk;
}
Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordRequest(const Command_ForgotPasswordRequest &cmd, ResponseContainer &rc)
{
qDebug() << "Received forgot password request from user: " << QString::fromStdString(cmd.user_name());
if (!servatrice->getEnableForgotPassword())
return Response::RespFunctionNotAllowed;
if (!sqlInterface->userExists(QString::fromStdString(cmd.user_name())))
return Response::RespFunctionNotAllowed;
if (sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name()))) {
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
re->set_challenge_email(false);
rc.setResponseExtension(re);
return Response::RespOk;
}
QString banReason; int banTimeRemaining;
if (sqlInterface->checkUserIsBanned(this->getAddress(), QString::fromStdString(cmd.user_name()), QString::fromStdString(cmd.clientid()), banReason, banTimeRemaining))
return Response::RespFunctionNotAllowed;
if (servatrice->getEnableForgotPasswordChallenge()) {
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
re->set_challenge_email(true);
rc.setResponseExtension(re);
return Response::RespOk;
}
else {
if (sqlInterface->addForgotPassword(QString::fromStdString(cmd.user_name()))) {
Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest;
re->set_challenge_email(false);
rc.setResponseExtension(re);
return Response::RespOk;
}
}
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordReset(const Command_ForgotPasswordReset &cmd, ResponseContainer &rc)
{
Q_UNUSED(rc);
qDebug() << "Received forgot password reset from user: " << QString::fromStdString(cmd.user_name());
if (!sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name())))
return Response::RespFunctionNotAllowed;
if (!sqlInterface->validateTableColumnStringData("{prefix}_users","token", QString::fromStdString(cmd.user_name()),QString::fromStdString(cmd.token())))
return Response::RespFunctionNotAllowed;
if (sqlInterface->changeUserPassword(QString::fromStdString(cmd.user_name()), "", QString::fromStdString(cmd.new_password()), true)) {
sqlInterface->removeForgotPassword(QString::fromStdString(cmd.user_name()));
return Response::RespOk;
}
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordChallenge(const Command_ForgotPasswordChallenge &cmd, ResponseContainer &rc)
{
Q_UNUSED(rc);
qDebug() << "Received forgot password challenge from user: " << QString::fromStdString(cmd.user_name());
if (sqlInterface->doesForgotPasswordExist(QString::fromStdString(cmd.user_name())))
return Response::RespOk;
if (sqlInterface->validateTableColumnStringData("{prefix}_users","email", QString::fromStdString(cmd.user_name()), QString::fromStdString(cmd.email())))
if (sqlInterface->addForgotPassword(QString::fromStdString(cmd.user_name())))
return Response::RespOk;
return Response::RespFunctionNotAllowed;
}
// ADMIN FUNCTIONS.
// Permission is checked by the calling function.

View file

@ -57,124 +57,126 @@ class Command_AccountPassword;
class AbstractServerSocketInterface : public Server_ProtocolHandler
{
Q_OBJECT
Q_OBJECT
protected slots:
void catchSocketError(QAbstractSocket::SocketError socketError);
virtual void flushOutputQueue() = 0;
void catchSocketError(QAbstractSocket::SocketError socketError);
virtual void flushOutputQueue() = 0;
signals:
void outputQueueChanged();
void outputQueueChanged();
protected:
void logDebugMessage(const QString &message);
bool tooManyRegistrationAttempts(const QString &ipAddress);
void logDebugMessage(const QString &message);
bool tooManyRegistrationAttempts(const QString &ipAddress);
virtual void writeToSocket(QByteArray & data) = 0;
virtual void flushSocket() = 0;
virtual void writeToSocket(QByteArray & data) = 0;
virtual void flushSocket() = 0;
Servatrice *servatrice;
QList<ServerMessage> outputQueue;
QMutex outputQueueMutex;
Servatrice *servatrice;
QList<ServerMessage> outputQueue;
QMutex outputQueueMutex;
private:
Servatrice_DatabaseInterface *sqlInterface;
Response::ResponseCode cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc);
int getDeckPathId(int basePathId, QStringList path);
int getDeckPathId(const QString &path);
bool deckListHelper(int folderId, ServerInfo_DeckStorage_Folder *folder);
Response::ResponseCode cmdDeckList(const Command_DeckList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer &rc);
void deckDelDirHelper(int basePathId);
void sendServerMessage(const QString userName, const QString message);
Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer &rc);
Response::ResponseCode cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer &rc);
Response::ResponseCode cmdDeckUpload(const Command_DeckUpload &cmd, ResponseContainer &rc);
DeckList *getDeckFromDatabase(int deckId);
Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayList(const Command_ReplayList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayDeleteMatch(const Command_ReplayDeleteMatch &cmd, ResponseContainer &rc);
Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc);
Response::ResponseCode cmdWarnUser(const Command_WarnUser &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetLogHistory(const Command_ViewLogHistory &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetWarnList(const Command_GetWarnList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetWarnHistory(const Command_GetWarnHistory &cmd, ResponseContainer &rc);
Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc);
Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc);
Servatrice_DatabaseInterface *sqlInterface;
Response::ResponseCode cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc);
int getDeckPathId(int basePathId, QStringList path);
int getDeckPathId(const QString &path);
bool deckListHelper(int folderId, ServerInfo_DeckStorage_Folder *folder);
Response::ResponseCode cmdDeckList(const Command_DeckList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer &rc);
void deckDelDirHelper(int basePathId);
void sendServerMessage(const QString userName, const QString message);
Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer &rc);
Response::ResponseCode cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer &rc);
Response::ResponseCode cmdDeckUpload(const Command_DeckUpload &cmd, ResponseContainer &rc);
DeckList *getDeckFromDatabase(int deckId);
Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayList(const Command_ReplayList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer &rc);
Response::ResponseCode cmdReplayDeleteMatch(const Command_ReplayDeleteMatch &cmd, ResponseContainer &rc);
Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc);
Response::ResponseCode cmdWarnUser(const Command_WarnUser &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetLogHistory(const Command_ViewLogHistory &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetWarnList(const Command_GetWarnList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdGetWarnHistory(const Command_GetWarnHistory &cmd, ResponseContainer &rc);
Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc);
Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc);
Response::ResponseCode cmdRegisterAccount(const Command_Register &cmd, ResponseContainer &rc);
Response::ResponseCode cmdActivateAccount(const Command_Activate &cmd, ResponseContainer & /* rc */);
Response::ResponseCode cmdReloadConfig(const Command_ReloadConfig &/* cmd */, ResponseContainer & /*rc*/);
Response::ResponseCode cmdAdjustMod(const Command_AdjustMod &cmd, ResponseContainer & /*rc*/);
Response::ResponseCode processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc);
Response::ResponseCode processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc);
Response::ResponseCode processExtendedAdminCommand(int cmdType, const AdminCommand &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAdjustMod(const Command_AdjustMod &cmd, ResponseContainer & /*rc*/);
Response::ResponseCode cmdForgotPasswordRequest(const Command_ForgotPasswordRequest &cmd, ResponseContainer &rc);
Response::ResponseCode cmdForgotPasswordReset(const Command_ForgotPasswordReset &cmd, ResponseContainer &rc);
Response::ResponseCode cmdForgotPasswordChallenge(const Command_ForgotPasswordChallenge &cmd, ResponseContainer &rc);
Response::ResponseCode processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc);
Response::ResponseCode processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc);
Response::ResponseCode processExtendedAdminCommand(int cmdType, const AdminCommand &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountEdit(const Command_AccountEdit &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountImage(const Command_AccountImage &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountPassword(const Command_AccountPassword &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountEdit(const Command_AccountEdit &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountImage(const Command_AccountImage &cmd, ResponseContainer &rc);
Response::ResponseCode cmdAccountPassword(const Command_AccountPassword &cmd, ResponseContainer &rc);
public:
AbstractServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~AbstractServerSocketInterface() { };
bool initSession();
AbstractServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~AbstractServerSocketInterface() { };
bool initSession();
virtual QHostAddress getPeerAddress() const = 0;
virtual QString getAddress() const = 0;
virtual QHostAddress getPeerAddress() const = 0;
virtual QString getAddress() const = 0;
void transmitProtocolItem(const ServerMessage &item);
void transmitProtocolItem(const ServerMessage &item);
};
class TcpServerSocketInterface : public AbstractServerSocketInterface
{
Q_OBJECT
Q_OBJECT
public:
TcpServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~TcpServerSocketInterface();
TcpServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~TcpServerSocketInterface();
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
QString getAddress() const { return socket->peerAddress().toString(); }
QString getConnectionType() const { return "tcp"; };
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
QString getAddress() const { return socket->peerAddress().toString(); }
QString getConnectionType() const { return "tcp"; };
private:
QTcpSocket *socket;
QByteArray inputBuffer;
bool messageInProgress;
bool handshakeStarted;
int messageLength;
QTcpSocket *socket;
QByteArray inputBuffer;
bool messageInProgress;
bool handshakeStarted;
int messageLength;
protected:
void writeToSocket(QByteArray & data) { socket->write(data); };
void flushSocket() { socket->flush(); };
void initSessionDeprecated();
bool initTcpSession();
void writeToSocket(QByteArray & data) { socket->write(data); };
void flushSocket() { socket->flush(); };
void initSessionDeprecated();
bool initTcpSession();
protected slots:
void readClient();
void flushOutputQueue();
void readClient();
void flushOutputQueue();
public slots:
void initConnection(int socketDescriptor);
void initConnection(int socketDescriptor);
};
#if QT_VERSION > 0x050300
class WebsocketServerSocketInterface : public AbstractServerSocketInterface
{
Q_OBJECT
Q_OBJECT
public:
WebsocketServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~WebsocketServerSocketInterface();
WebsocketServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~WebsocketServerSocketInterface();
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
QString getAddress() const { return socket->peerAddress().toString(); }
QString getConnectionType() const { return "websocket"; };
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
QString getAddress() const { return socket->peerAddress().toString(); }
QString getConnectionType() const { return "websocket"; };
private:
QWebSocket *socket;
QWebSocket *socket;
protected:
void writeToSocket(QByteArray & data) { socket->sendBinaryMessage(data); };
void flushSocket() { socket->flush(); };
bool initWebsocketSession();
void writeToSocket(QByteArray & data) { socket->sendBinaryMessage(data); };
void flushSocket() { socket->flush(); };
bool initWebsocketSession();
protected slots:
void binaryMessageReceived(const QByteArray & message);
void flushOutputQueue();
void binaryMessageReceived(const QByteArray & message);
void flushOutputQueue();
public slots:
void initConnection(void * _socket);
void initConnection(void * _socket);
};
#endif

View file

@ -82,6 +82,54 @@ bool SmtpClient::enqueueActivationTokenMail(const QString &nickname, const QStri
return true;
}
bool SmtpClient::enqueueForgotPasswordTokenMail(const QString &nickname, const QString &recipient, const QString &token)
{
QString email = settingsCache->value("smtp/email", "").toString();
QString name = settingsCache->value("smtp/name", "").toString();
QString subject = settingsCache->value("forgotpassword/subject", "").toString();
QString body = settingsCache->value("forgotpassword/body", "").toString();
if (email.isEmpty())
{
qDebug() << "[MAIL] Missing sender email in configuration";
return false;
}
if (subject.isEmpty())
{
qDebug() << "[MAIL] Missing subject field in configuration";
return false;
}
if (body.isEmpty())
{
qDebug() << "[MAIL] Missing body field in configuration";
return false;
}
if (recipient.isEmpty())
{
qDebug() << "[MAIL] Missing recipient field for user " << nickname;
return false;
}
if (token.isEmpty())
{
qDebug() << "[MAIL] Missing token field for user " << nickname;
return false;
}
QxtMailMessage message;
message.setSender(name + " <" + email + ">");
message.addRecipient(recipient);
message.setSubject(subject);
message.setBody(body.replace("%username", nickname).replace("%token", token));
int id = smtp->send(message);
qDebug() << "[MAIL] Enqueued mail to" << recipient << "as" << id;
return true;
}
void SmtpClient::sendAllEmails()
{
// still connected from the previous round

View file

@ -7,28 +7,29 @@ class QxtSmtp;
class QxtMailMessage;
class SmtpClient : public QObject {
Q_OBJECT
Q_OBJECT
public:
SmtpClient(QObject *parent = 0);
~SmtpClient();
SmtpClient(QObject *parent = 0);
~SmtpClient();
protected:
QxtSmtp *smtp;
QxtSmtp *smtp;
public slots:
bool enqueueActivationTokenMail(const QString &nickname, const QString &recipient, const QString &token);
void sendAllEmails();
bool enqueueActivationTokenMail(const QString &nickname, const QString &recipient, const QString &token);
bool enqueueForgotPasswordTokenMail(const QString &nickname, const QString &recipient, const QString &token);
void sendAllEmails();
protected slots:
void authenticated();
void authenticationFailed(const QByteArray & msg);
void connected();
void connectionFailed(const QByteArray & msg);
void disconnected();
void encrypted();
void encryptionFailed(const QByteArray & msg);
void finished();
void mailFailed(int mailID, int errorCode, const QByteArray & msg);
void mailSent(int mailID);
void recipientRejected(int mailID, const QString & address, const QByteArray & msg);
void senderRejected(int mailID, const QString & address, const QByteArray & msg);
void authenticated();
void authenticationFailed(const QByteArray & msg);
void connected();
void connectionFailed(const QByteArray & msg);
void disconnected();
void encrypted();
void encryptionFailed(const QByteArray & msg);
void finished();
void mailFailed(int mailID, int errorCode, const QByteArray & msg);
void mailSent(int mailID);
void recipientRejected(int mailID, const QString & address, const QByteArray & msg);
void senderRejected(int mailID, const QString & address, const QByteArray & msg);
};
#endif