mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 09:05:10 -07:00
* [Server/Client/Protocol] Add developer staff role Introduce a Developer staff level (proto flag 32, DB admin bit 8) that sits between admin and moderator: no kick/ban/warn/report/admin powers, but gets server log access via a new developer command container family (GET_SERVER_STATS, VIEWLOG_HISTORY) and an idle-timeout exemption. - Protocol: IsDeveloper flag, developer_commands.proto envelope, Command_GetServerStats/Command_GetLogHistory, Response_GetServerStats, Command_AdjustMod.should_be_developer - Servatrice: fail-closed developer dispatcher, uptime snapshot handler, shared log history handler reuse, bit-8 DB mapping - Client: burgundy pawn/badge/labels/sort order, prepareDeveloperCommand, minimal Developer stats tab, log tab access, promote/demote actions Took 24 minutes Took 18 seconds * [Server/Client/Protocol] Address developer role review feedback Address ZeizaZach's review of the developer staff role: - Nudge the developer log query to exclude private chat and sender IPs (the ModeratorCommand path still sees everything). - Deduplicate Command_GetLogHistory into Command_ViewLogHistory, which now extends both ModeratorCommand (ext) and DeveloperCommand (dev_ext); the client picks the DeveloperCommand-scoped extension by extendee, and the server reads it via the extension number. - Pull the uptime snapshot SQL into Servatrice_DatabaseInterface as getLatestUptimeSnapshot() and widen the reported counters to 64-bit. - Document the admin bitfield (1 admin, 2 moderator, 4 judge, 8 developer) and add a server-side test for the developer command path. * Add missing trailing newline to user_context_menu.cpp * Remove stale includes of deleted command_get_log_history proto The Command_GetLogHistory message was folded into Command_ViewLogHistory, which deleted command_get_log_history.proto, but serversocketinterface still #included its generated header. Fresh CI builds fail on the missing file; local builds masked it by reusing a previously generated header. * [Server] Exclude chat rows when private-chat filter is bypassable A developer who omits log_location entirely — or sends only "chat" — leaves chatType, gameType, roomType all false, so getMessageLogHistory skips the target_type clause and returns every row, private messages included. When !allowPrivateChat the server now forces game+room when no surviving location was requested, guaranteeing the query always carries a target_type restriction. [Client] Demote mod+dev to moderator path in log-tab dispatch The developer command family is strictly weaker than the moderator one (no private chat, no sender_ip, ip filter ignored), so granting the developer bit to an existing moderator must not silently strip their capabilities. useDeveloperCommands is now true only when the user holds the developer bit and not the moderator bit. [Client] Hide the IP-address filter for developer log tab users The developer path ignores the ip_address query field server-side. Showing the field lets a developer type an IP and get results that are silently unfiltered by it rather than an empty result set — reads as a broken filter. Hide labelFindIPAddress/findIPAddress alongside the privateChat checkbox. * Developer pawn is silver. * [Client] Fix indentation of merged Card Art Rules / Developer tabs --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
175 lines
8.4 KiB
C++
175 lines
8.4 KiB
C++
#ifndef SERVATRICE_DATABASE_INTERFACE_H
|
|
#define SERVATRICE_DATABASE_INTERFACE_H
|
|
|
|
#include <QChar>
|
|
#include <QHash>
|
|
#include <QObject>
|
|
#include <QSqlDatabase>
|
|
#include <libcockatrice/protocol/pb/serverinfo_chat_message.pb.h>
|
|
#include <libcockatrice/protocol/pb/serverinfo_moderator_login.pb.h>
|
|
#include <libcockatrice/protocol/pb/serverinfo_user_alt.pb.h>
|
|
#include <libcockatrice/protocol/pb/serverinfo_user_session.pb.h>
|
|
#include <libcockatrice/protocol/pb/serverinfo_warning.pb.h>
|
|
#include <server.h>
|
|
#include <server_database_interface.h>
|
|
|
|
#define DATABASE_SCHEMA_VERSION 36
|
|
|
|
class Servatrice;
|
|
|
|
class Servatrice_DatabaseInterface : public Server_DatabaseInterface
|
|
{
|
|
Q_OBJECT
|
|
private:
|
|
int instanceId;
|
|
QSqlDatabase sqlDatabase;
|
|
QHash<QString, QSqlQuery *> preparedStatements;
|
|
Servatrice *server;
|
|
ServerInfo_User evalUserQueryResult(const QSqlQuery *query, bool complete, bool withId = false);
|
|
/** Must be called after checkSql and server is known to be in auth mode. */
|
|
bool checkUserIsIdBanned(const QString &clientId, QString &banReason, int &banSecondsRemaining);
|
|
/** Must be called after checkSql and server is known to be in auth mode. */
|
|
bool checkUserIsIpBanned(const QString &ipAddress, QString &banReason, int &banSecondsRemaining);
|
|
/** Must be called after checkSql and server is known to be in auth mode. */
|
|
bool checkUserIsNameBanned(QString const &userName, QString &banReason, int &banSecondsRemaining);
|
|
|
|
protected:
|
|
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler,
|
|
const QString &user,
|
|
const QString &password,
|
|
const QString &clientId,
|
|
QString &reasonStr,
|
|
int &banSecondsLeft,
|
|
bool passwordNeedsHash) override;
|
|
|
|
public slots:
|
|
void initDatabase(const QSqlDatabase &_sqlDatabase);
|
|
|
|
public:
|
|
explicit Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server);
|
|
~Servatrice_DatabaseInterface() override;
|
|
bool initDatabase(const QString &type,
|
|
const QString &hostName,
|
|
const QString &databaseName,
|
|
const QString &userName,
|
|
const QString &password);
|
|
bool openDatabase();
|
|
bool checkSql();
|
|
QSqlQuery *prepareQuery(const QString &queryText);
|
|
bool execSqlQuery(QSqlQuery *query);
|
|
const QSqlDatabase &getDatabase()
|
|
{
|
|
return sqlDatabase;
|
|
}
|
|
|
|
bool activeUserExists(const QString &user) override;
|
|
bool userExists(const QString &user) override;
|
|
QString getUserSalt(const QString &user) override;
|
|
int getUserIdInDB(const QString &name);
|
|
QMap<QString, ServerInfo_User> getBuddyList(const QString &name) override;
|
|
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) override;
|
|
bool isInBuddyList(const QString &whoseList, const QString &who) override;
|
|
bool isInIgnoreList(const QString &whoseList, const QString &who) override;
|
|
ServerInfo_User getUserData(const QString &name, bool withId = false) override;
|
|
void storeGameInformation(const QString &roomName,
|
|
const QStringList &roomGameTypes,
|
|
const ServerInfo_Game &gameInfo,
|
|
const QSet<QString> &allPlayersEver,
|
|
const QSet<QString> &allSpectatorsEver,
|
|
const QList<GameReplay *> &replayList) override;
|
|
DeckList *getDeckFromDatabase(int deckId, int userId) override;
|
|
|
|
int getNextGameId() override;
|
|
int getNextReplayId() override;
|
|
int getActiveUserCount(QString connectionType = QString()) override;
|
|
|
|
qint64 startSession(const QString &userName,
|
|
const QString &address,
|
|
const QString &clientId,
|
|
const QString &connectionType) override;
|
|
void endSession(qint64 sessionId) override;
|
|
void clearSessionTables() override;
|
|
void lockSessionTables() override;
|
|
void unlockSessionTables() override;
|
|
bool userSessionExists(const QString &userName) override;
|
|
bool usernameIsValid(const QString &user, QString &error) override;
|
|
bool checkUserIsBanned(const QString &ipAddress,
|
|
const QString &userName,
|
|
const QString &clientId,
|
|
QString &banReason,
|
|
int &banSecondsRemaining) override;
|
|
int checkNumberOfUserAccounts(const QString &email) override;
|
|
bool registerUser(const QString &userName,
|
|
const QString &realName,
|
|
const QString &password,
|
|
bool passwordNeedsHash,
|
|
const QString &emailAddress,
|
|
const QString &country,
|
|
bool active = false) override;
|
|
bool activateUser(const QString &userName, const QString &token) override;
|
|
void updateUsersClientID(const QString &userName, const QString &userClientID) override;
|
|
void updateUsersLastLoginData(const QString &userName, const QString &clientVersion) override;
|
|
void logMessage(const int senderId,
|
|
const QString &senderName,
|
|
const QString &senderIp,
|
|
const QString &logMessage,
|
|
LogMessage_TargetType targetType,
|
|
const int targetId,
|
|
const QString &targetName) override;
|
|
bool changeUserPassword(const QString &user, const QString &password, bool passwordNeedsHash) override;
|
|
bool changeUserPassword(const QString &user,
|
|
const QString &oldPassword,
|
|
bool oldPasswordNeedsHash,
|
|
const QString &newPassword,
|
|
bool newPasswordNeedsHash) override;
|
|
void setForcePasswordChange(const QString &user, bool force) override;
|
|
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);
|
|
QList<ServerInfo_UserSession> getUserSessions(const QString &userName, int limit);
|
|
QList<ServerInfo_UserAlt> getUserAlts(const QString &userName);
|
|
QList<ServerInfo_ModeratorLogin> getModeratorLastLogins();
|
|
|
|
// Uptime snapshot as recorded by Servatrice::statusUpdate() into the
|
|
// {prefix}_uptime table. valid is false when no snapshot exists yet.
|
|
struct UptimeSnapshot
|
|
{
|
|
bool valid = false;
|
|
quint64 usersCount = 0;
|
|
quint64 modsCount = 0;
|
|
quint64 gamesCount = 0;
|
|
quint64 txBytes = 0;
|
|
quint64 rxBytes = 0;
|
|
quint64 uptimeSecs = 0;
|
|
quint64 timest = 0;
|
|
};
|
|
UptimeSnapshot getLatestUptimeSnapshot(int serverId);
|
|
bool removeUserAvatar(const QString &userName);
|
|
bool addForgotPassword(const QString &user);
|
|
bool removeForgotPassword(const QString &user) override;
|
|
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);
|
|
void addAuditRecord(const QString &user,
|
|
const QString &ipaddress,
|
|
const QString &clientid,
|
|
const QString &action,
|
|
const QString &details,
|
|
const bool &results);
|
|
};
|
|
|
|
#endif
|