[Server] Serve report aggregates through the database interface (#7845)

cmdReportStats and cmdReportUserInfo still ran their queries inline through
Servatrice_DatabaseInterface and built the response in the socket handler. Add
ReportStatsRecord, ReportUserInfoRecord and their count records to
Server_DatabaseInterface with fail-closed defaults, implement getReportStats and
getReportUserInfo with the previous statements and query order, and keep
presence flags for the fields the old code set only on a successful query so
the proto2 wire output is unchanged. The stats cache decision and every response
code stay in the handler.
This commit is contained in:
BruebachL 2026-11-10 12:16:28 +01:00 • committed by GitHub
parent 2ba80cb61d
commit a54e13756c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 309 additions and 144 deletions

View file

@ -424,6 +424,66 @@ public:
{
return false;
}
/** @brief One report category and how many reports it covers. */
struct ReportCategoryCountRecord
{
QString category;
int count = 0;
};
/** @brief One reported or reporting user and how many reports involve them. */
struct ReportTopUserRecord
{
QString userName;
int count = 0;
};
/** @brief Aggregated report queue statistics for the moderator overview. */
struct ReportStatsRecord
{
int totalReports = 0;
int totalPending = 0;
int totalAssigned = 0;
int totalResolved = 0;
int reportsLast24h = 0;
int reportsLast7d = 0;
int reportsLast30d = 0;
int reportsThisWeek = 0;
bool hasReportsLastWeek = false;
int reportsLastWeek = 0;
bool hasAvgResolutionHours = false;
double avgResolutionHours = 0.0;
QList<ReportCategoryCountRecord> categoryCounts;
QList<ReportTopUserRecord> topReportedUsers;
QList<ReportTopUserRecord> topReporters;
/// False when a non-overview query failed, which keeps the result out of the cache.
bool allQueriesOk = true;
};
virtual bool getReportStats(ReportStatsRecord & /* stats */)
{
return false;
}
/** @brief Report history and moderation counts for one user, for the moderator overview. */
struct ReportUserInfoRecord
{
bool found = false;
bool isAdmin = false;
bool isActive = false;
qint64 registrationTime = 0;
bool hasAdminNotes = false;
QString adminNotes;
bool hasTotalReports = false;
int totalReports = 0;
bool hasTotalBans = false;
int totalBans = 0;
bool hasTotalWarns = false;
int totalWarns = 0;
bool hasLastLogin = false;
qint64 lastLogin = 0;
QList<ServerInfo_Report> recentReports;
};
virtual bool getReportUserInfo(const QString & /* userName */, ReportUserInfoRecord & /* info */)
{
return false;
}
/** @brief One resolved or dismissed report whose reporter has not been told yet. */
struct PendingReportNotification
{