feat: enhance error handling and permissions in Admin and Report services

This commit is contained in:
gabdevele
2026-06-14 21:37:12 +02:00 Unverified
parent 002f89bd73
commit ca09e7b6c8
5 changed files with 93 additions and 14 deletions
+49 -5
View File
@@ -123,6 +123,11 @@ bool canInteractWithReport(const auth::UserContext &user, long long reportId)
return ownsReport(user, reportId) || canModifyReport(user, reportId);
}
bool canCreateCitizenReport(const auth::UserContext &user)
{
return !auth::canManageReports(user);
}
int boundedPage(const std::optional<std::string> &value)
{
if (!value)
@@ -257,6 +262,11 @@ void notifyReportOwner(long long reportId,
Json::Value ReportService::createReport(const auth::UserContext &user,
const Json::Value &body)
{
if (!canCreateCitizenReport(user))
{
return failure("forbidden");
}
const auto missing =
validation::missingStrings(body, {"address", "description"});
if (!missing.empty() || !validation::hasNumber(body, "category_id") ||
@@ -318,8 +328,13 @@ Json::Value ReportService::createReport(const auth::UserContext &user,
if (body["media"].isArray())
{
size_t mediaCount = 0;
for (const auto &item : body["media"])
{
if (mediaCount >= 5)
{
break;
}
if (item.isString() && !item.asString().empty())
{
db->execSqlSync(
@@ -327,6 +342,7 @@ Json::Value ReportService::createReport(const auth::UserContext &user,
"VALUES (?, ?, 'IMAGE')",
reportId,
item.asString());
++mediaCount;
}
}
}
@@ -713,6 +729,13 @@ Json::Value ReportService::assignTeam(const auth::UserContext &user,
{
return failure("invalid_status_transition");
}
const auto team = db->execSqlSync(
"SELECT id FROM teams WHERE id = ? AND active = TRUE",
body["team_id"].asInt64());
if (team.empty())
{
return failure("team_not_found");
}
db->execSqlSync(
"INSERT INTO assignments (report_id, team_id, assigned_by_user_id) "
@@ -786,11 +809,25 @@ Json::Value ReportService::flagReport(const auth::UserContext &user,
long long reportId,
const Json::Value &body)
{
if (!canAccessReport(user, reportId) ||
!validation::hasString(body, "reason"))
if (!validation::hasString(body, "reason"))
{
return failure("invalid_flag");
}
const auto owner = reportOwner(reportId);
if (!owner)
{
return failure("report_not_found");
}
if (*owner == user.id)
{
return failure("cannot_flag_own_report");
}
if (!canAccessReport(user, reportId))
{
return failure("forbidden");
}
auto db = drogon::app().getDbClient();
db->execSqlSync(
"INSERT INTO moderation_flags "
@@ -812,20 +849,27 @@ Json::Value ReportService::flagMessage(const auth::UserContext &user,
long long messageId,
const Json::Value &body)
{
if (!canInteractWithReport(user, reportId) ||
!validation::hasString(body, "reason"))
if (!validation::hasString(body, "reason"))
{
return failure("invalid_flag");
}
if (!canInteractWithReport(user, reportId))
{
return failure("forbidden");
}
auto db = drogon::app().getDbClient();
const auto message = db->execSqlSync(
"SELECT id FROM messages WHERE id = ? AND report_id = ?",
"SELECT id, user_id FROM messages WHERE id = ? AND report_id = ?",
messageId,
reportId);
if (message.empty())
{
return failure("message_not_found");
}
if (message[0]["user_id"].as<long long>() == user.id)
{
return failure("cannot_flag_own_message");
}
db->execSqlSync(
"INSERT INTO moderation_flags "
"(content_type, report_id, message_id, reason, details, created_by_user_id) "