mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
Add first draft of protocol extension for registration
Stub for registration command handling in server First draft of handling registration requests WIP (will be rebased) clean up bad imports (rebase this later) Finish checkUserIsBanned method Add username validity check Check servatrice registration settings WIP Finish(?) server side of registration Needs testing Fix switch case compile failure I have no idea why I have to do this WIP for registration testing python script Stub register script initial attempt Rearrange register script First try at sending reg register.py sends commands correctly now Add more debug to register.py Pack bytes the right way - servatrice can parse py script sends now register.py should be working now Parse xml hack correctly Log registration enabled settings on server start Insert gender correctly on register Show tcpserver error message on failed gameserver listen Fail startup if db configured and can't be opened. TIL qt5 comes without mysql by default in homebrew...
This commit is contained in:
parent
d1b243481b
commit
735fcbf311
16 changed files with 394 additions and 48 deletions
|
|
@ -9,6 +9,7 @@
|
|||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QDateTime>
|
||||
#include <QChar>
|
||||
|
||||
Servatrice_DatabaseInterface::Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server)
|
||||
: instanceId(_instanceId),
|
||||
|
|
@ -34,7 +35,9 @@ void Servatrice_DatabaseInterface::initDatabase(const QSqlDatabase &_sqlDatabase
|
|||
}
|
||||
}
|
||||
|
||||
void Servatrice_DatabaseInterface::initDatabase(const QString &type, const QString &hostName, const QString &databaseName, const QString &userName, const QString &password)
|
||||
bool Servatrice_DatabaseInterface::initDatabase(const QString &type, const QString &hostName,
|
||||
const QString &databaseName, const QString &userName,
|
||||
const QString &password)
|
||||
{
|
||||
sqlDatabase = QSqlDatabase::addDatabase(type, "main");
|
||||
sqlDatabase.setHostName(hostName);
|
||||
|
|
@ -42,7 +45,7 @@ void Servatrice_DatabaseInterface::initDatabase(const QString &type, const QStri
|
|||
sqlDatabase.setUserName(userName);
|
||||
sqlDatabase.setPassword(password);
|
||||
|
||||
openDatabase();
|
||||
return openDatabase();
|
||||
}
|
||||
|
||||
bool Servatrice_DatabaseInterface::openDatabase()
|
||||
|
|
@ -102,11 +105,52 @@ bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user)
|
|||
return re.exactMatch(user);
|
||||
}
|
||||
|
||||
// TODO move this to Server
|
||||
bool Servatrice_DatabaseInterface::getRequireRegistration()
|
||||
{
|
||||
return settingsCache->value("authentication/regonly", 0).toBool();
|
||||
}
|
||||
|
||||
bool Servatrice_DatabaseInterface::registerUser(const QString &userName, const QString &realName, ServerInfo_User_Gender const &gender, const QString &passwordSha512, const QString &emailAddress, const QString &country, bool active)
|
||||
{
|
||||
if (!checkSql())
|
||||
return false;
|
||||
|
||||
QSqlQuery *query = prepareQuery("insert into {prefix}_users "
|
||||
"(name, realname, gender, password_sha512, email, country, registrationDate, active) "
|
||||
"values "
|
||||
"(:userName, :realName, :gender, :password_sha512, :email, :country, UTC_TIMESTAMP(), :active)");
|
||||
query->bindValue(":userName", userName);
|
||||
query->bindValue(":realName", realName);
|
||||
query->bindValue(":gender", getGenderChar(gender));
|
||||
query->bindValue(":password_sha512", passwordSha512);
|
||||
query->bindValue(":email", emailAddress);
|
||||
query->bindValue(":country", country);
|
||||
query->bindValue(":active", active ? 1 : 0);
|
||||
|
||||
if (!execSqlQuery(query)) {
|
||||
qDebug() << "Failed to insert user: " << query->lastError() << " sql: " << query->lastQuery();
|
||||
// TODO handle duplicate insert error
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QChar Servatrice_DatabaseInterface::getGenderChar(ServerInfo_User_Gender const &gender)
|
||||
{
|
||||
switch (gender) {
|
||||
case ServerInfo_User_Gender_GenderUnknown:
|
||||
return QChar('u');
|
||||
case ServerInfo_User_Gender_Male:
|
||||
return QChar('m');
|
||||
case ServerInfo_User_Gender_Female:
|
||||
return QChar('f');
|
||||
default:
|
||||
return QChar('u');
|
||||
}
|
||||
}
|
||||
|
||||
AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &banSecondsLeft)
|
||||
{
|
||||
switch (server->getAuthenticationMethod()) {
|
||||
|
|
@ -125,43 +169,8 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
|
|||
if (!usernameIsValid(user))
|
||||
return UsernameInvalid;
|
||||
|
||||
QSqlQuery *ipBanQuery = prepareQuery("select time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))), b.minutes <=> 0, b.visible_reason from {prefix}_bans b where b.time_from = (select max(c.time_from) from {prefix}_bans c where c.ip_address = :address) and b.ip_address = :address2");
|
||||
ipBanQuery->bindValue(":address", static_cast<ServerSocketInterface *>(handler)->getPeerAddress().toString());
|
||||
ipBanQuery->bindValue(":address2", static_cast<ServerSocketInterface *>(handler)->getPeerAddress().toString());
|
||||
if (!execSqlQuery(ipBanQuery)) {
|
||||
qDebug("Login denied: SQL error");
|
||||
return NotLoggedIn;
|
||||
}
|
||||
|
||||
if (ipBanQuery->next()) {
|
||||
const int secondsLeft = -ipBanQuery->value(0).toInt();
|
||||
const bool permanentBan = ipBanQuery->value(1).toInt();
|
||||
if ((secondsLeft > 0) || permanentBan) {
|
||||
reasonStr = ipBanQuery->value(2).toString();
|
||||
banSecondsLeft = permanentBan ? 0 : secondsLeft;
|
||||
qDebug("Login denied: banned by address");
|
||||
return UserIsBanned;
|
||||
}
|
||||
}
|
||||
|
||||
QSqlQuery *nameBanQuery = prepareQuery("select time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))), b.minutes <=> 0, b.visible_reason from {prefix}_bans b where b.time_from = (select max(c.time_from) from {prefix}_bans c where c.user_name = :name2) and b.user_name = :name1");
|
||||
nameBanQuery->bindValue(":name1", user);
|
||||
nameBanQuery->bindValue(":name2", user);
|
||||
if (!execSqlQuery(nameBanQuery)) {
|
||||
qDebug("Login denied: SQL error");
|
||||
return NotLoggedIn;
|
||||
}
|
||||
|
||||
if (nameBanQuery->next()) {
|
||||
const int secondsLeft = -nameBanQuery->value(0).toInt();
|
||||
const bool permanentBan = nameBanQuery->value(1).toInt();
|
||||
if ((secondsLeft > 0) || permanentBan) {
|
||||
reasonStr = nameBanQuery->value(2).toString();
|
||||
banSecondsLeft = permanentBan ? 0 : secondsLeft;
|
||||
qDebug("Login denied: banned by name");
|
||||
return UserIsBanned;
|
||||
}
|
||||
}
|
||||
if (checkUserIsBanned(handler->getAddress(), user, reasonStr, banSecondsLeft))
|
||||
return UserIsBanned;
|
||||
|
||||
QSqlQuery *passwordQuery = prepareQuery("select password_sha512 from {prefix}_users where name = :name and active = 1");
|
||||
passwordQuery->bindValue(":name", user);
|
||||
|
|
@ -188,6 +197,79 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
|
|||
return UnknownUser;
|
||||
}
|
||||
|
||||
bool Servatrice_DatabaseInterface::checkUserIsBanned(const QString &ipAddress, const QString &userName, QString &banReason, int &banSecondsRemaining)
|
||||
{
|
||||
if (server->getAuthenticationMethod() != Servatrice::AuthenticationSql)
|
||||
return false;
|
||||
|
||||
if (!checkSql()) {
|
||||
qDebug("Failed to check if user is banned. Database invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return
|
||||
checkUserIsIpBanned(ipAddress, banReason, banSecondsRemaining)
|
||||
|| checkUserIsNameBanned(userName, banReason, banSecondsRemaining);
|
||||
|
||||
}
|
||||
|
||||
bool Servatrice_DatabaseInterface::checkUserIsNameBanned(const QString &userName, QString &banReason, int &banSecondsRemaining)
|
||||
{
|
||||
QSqlQuery *nameBanQuery = prepareQuery("select time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))), b.minutes <=> 0, b.visible_reason from {prefix}_bans b where b.time_from = (select max(c.time_from) from {prefix}_bans c where c.user_name = :name2) and b.user_name = :name1");
|
||||
nameBanQuery->bindValue(":name1", userName);
|
||||
nameBanQuery->bindValue(":name2", userName);
|
||||
if (!execSqlQuery(nameBanQuery)) {
|
||||
qDebug() << "Name ban check failed: SQL error" << nameBanQuery->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nameBanQuery->next()) {
|
||||
const int secondsLeft = -nameBanQuery->value(0).toInt();
|
||||
const bool permanentBan = nameBanQuery->value(1).toInt();
|
||||
if ((secondsLeft > 0) || permanentBan) {
|
||||
banReason = nameBanQuery->value(2).toString();
|
||||
banSecondsRemaining = permanentBan ? 0 : secondsLeft;
|
||||
qDebug() << "Username" << userName << "is banned by name";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Servatrice_DatabaseInterface::checkUserIsIpBanned(const QString &ipAddress, QString &banReason, int &banSecondsRemaining)
|
||||
{
|
||||
QSqlQuery *ipBanQuery = prepareQuery(
|
||||
"select"
|
||||
" time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))),"
|
||||
" b.minutes <=> 0,"
|
||||
" b.visible_reason"
|
||||
" from {prefix}_bans b"
|
||||
" where"
|
||||
" b.time_from = (select max(c.time_from)"
|
||||
" from {prefix}_bans c"
|
||||
" where c.ip_address = :address)"
|
||||
" and b.ip_address = :address2");
|
||||
|
||||
ipBanQuery->bindValue(":address", ipAddress);
|
||||
ipBanQuery->bindValue(":address2", ipAddress);
|
||||
if (!execSqlQuery(ipBanQuery)) {
|
||||
qDebug() << "IP ban check failed: SQL error." << ipBanQuery->lastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ipBanQuery->next()) {
|
||||
const int secondsLeft = -ipBanQuery->value(0).toInt();
|
||||
const bool permanentBan = ipBanQuery->value(1).toInt();
|
||||
if ((secondsLeft > 0) || permanentBan) {
|
||||
banReason = ipBanQuery->value(2).toString();
|
||||
banSecondsRemaining = permanentBan ? 0 : secondsLeft;
|
||||
qDebug() << "User is banned by address" << ipAddress;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Servatrice_DatabaseInterface::userExists(const QString &user)
|
||||
{
|
||||
if (server->getAuthenticationMethod() == Servatrice::AuthenticationSql) {
|
||||
|
|
@ -579,4 +661,4 @@ void Servatrice_DatabaseInterface::logMessage(const int senderId, const QString
|
|||
query->bindValue(":target_id", (targetType == MessageTargetChat && targetId < 1) ? QVariant() : targetId);
|
||||
query->bindValue(":target_name", targetName);
|
||||
execSqlQuery(query);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue