[Server] Serve report mutations through the database interface (#7846)

cmdReportAssign, cmdReportResolve, cmdReportReopen and cmdReportAddComment still
ran their lookups and updates inline through Servatrice_DatabaseInterface. Add
assignReport, resolveReport, reopenReport, getUserNameById,
getReportNotificationTarget, countReportCommentsInLastHour,
getReportCommentTarget and addReportComment to Server_DatabaseInterface with
fail-closed defaults, and model the outcomes as ReportAssignResult and
ReportUpdateResult so "no such report", "wrong state" and "query failed" stay
distinguishable. Authorization checks, audit records, notification recipients
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 a54e13756c
commit 948035af06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 339 additions and 148 deletions

View file

@ -484,6 +484,72 @@ public:
{
return false;
}
/** @brief Outcome of a report state change. */
enum class ReportUpdateResult
{
Ok,
InvalidState,
Failed
};
/** @brief Outcome of claiming an open report for a moderator. */
enum class ReportAssignResult
{
Ok,
NotFound,
NotOpen,
Failed
};
virtual ReportAssignResult assignReport(int /* reportId */, int /* moderatorId */)
{
return ReportAssignResult::Failed;
}
virtual ReportUpdateResult
resolveReport(int /* reportId */, const QString & /* status */, const QString & /* note */, int /* moderatorId */)
{
return ReportUpdateResult::Failed;
}
virtual ReportUpdateResult reopenReport(int /* reportId */)
{
return ReportUpdateResult::Failed;
}
/** @brief The user name behind a database user id; false when the lookup fails or finds no row. */
virtual bool getUserNameById(int /* userId */, QString & /* userName */)
{
return false;
}
/** @brief The reporter and reported user of a report, for the resolve notification. */
virtual bool
getReportNotificationTarget(int /* reportId */, int & /* reporterId */, QString & /* reportedUserName */)
{
return false;
}
/** @brief Comments the author wrote in the last hour, for the hourly cap. */
virtual int countReportCommentsInLastHour(int /* authorId */)
{
return 0;
}
/** @brief One report's reporter, assignee and status, for the comment checks. */
struct ReportCommentTargetRecord
{
bool found = false;
int reporterId = 0;
QString reporterName;
int assignedToId = 0;
QString status;
};
virtual bool getReportCommentTarget(int /* reportId */, ReportCommentTargetRecord & /* target */)
{
return false;
}
virtual bool addReportComment(int /* reportId */,
const QString & /* authorName */,
int /* authorId */,
const QString & /* commentText */,
bool /* isModerator */,
qlonglong & /* commentId */)
{
return false;
}
/** @brief One resolved or dismissed report whose reporter has not been told yet. */
struct PendingReportNotification
{