Add report media uploads

This commit is contained in:
gabdevele
2026-06-02 20:38:44 +02:00 Unverified
parent b59536757b
commit 1ef41bb2a3
12 changed files with 77 additions and 46 deletions
+32 -19
View File
@@ -63,25 +63,30 @@ void sendService(Json::Value body,
callback(visione::http::json(std::move(body), status));
}
bool isAllowedImage(const drogon::HttpFile &file)
struct MediaType
{
const auto type = file.getContentType();
return type == drogon::CT_IMAGE_JPG || type == drogon::CT_IMAGE_PNG ||
type == drogon::CT_IMAGE_WEBP;
}
std::string kind;
std::string contentType;
};
std::string imageContentType(const drogon::HttpFile &file)
std::optional<MediaType> allowedMediaType(const drogon::HttpFile &file)
{
switch (file.getContentType())
{
case drogon::CT_IMAGE_JPG:
return "image/jpeg";
return MediaType{"IMAGE", "image/jpeg"};
case drogon::CT_IMAGE_PNG:
return "image/png";
return MediaType{"IMAGE", "image/png"};
case drogon::CT_IMAGE_WEBP:
return "image/webp";
return MediaType{"IMAGE", "image/webp"};
case drogon::CT_VIDEO_MP4:
return MediaType{"VIDEO", "video/mp4"};
case drogon::CT_VIDEO_WEBM:
return MediaType{"VIDEO", "video/webm"};
case drogon::CT_VIDEO_QUICKTIME:
return MediaType{"VIDEO", "video/quicktime"};
default:
return "application/octet-stream";
return std::nullopt;
}
}
} // namespace
@@ -226,7 +231,7 @@ void ReportController::addFeedback(
sendService(service.addFeedback(*user, reportId, body), std::move(callback));
}
void ReportController::uploadPhotos(
void ReportController::uploadMedia(
const drogon::HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
long long reportId)
@@ -254,7 +259,7 @@ void ReportController::uploadPhotos(
std::filesystem::path(reportsPath) / std::to_string(reportId);
visione::services::ReportService service;
auto allowed = service.canAddPhoto(*user, reportId);
auto allowed = service.canAddMedia(*user, reportId);
if (!allowed.get("ok", false).asBool())
{
callback(visione::http::json(std::move(allowed), drogon::k403Forbidden));
@@ -262,16 +267,16 @@ void ReportController::uploadPhotos(
}
if (parser.getFiles().size() >
static_cast<size_t>(allowed.get("remaining_photo_slots", 0).asInt()))
static_cast<size_t>(allowed.get("remaining_media_slots", 0).asInt()))
{
callback(visione::http::error("too_many_photos", drogon::k400BadRequest));
callback(visione::http::error("too_many_media", drogon::k400BadRequest));
return;
}
for (const auto &file : parser.getFiles())
{
if (!isAllowedImage(file))
if (!allowedMediaType(file))
{
callback(visione::http::error("unsupported_photo_type",
callback(visione::http::error("unsupported_media_type",
drogon::k400BadRequest));
return;
}
@@ -281,10 +286,12 @@ void ReportController::uploadPhotos(
Json::Value response;
response["ok"] = true;
response["media"] = Json::arrayValue;
response["photos"] = Json::arrayValue;
for (const auto &file : parser.getFiles())
{
const auto mediaType = allowedMediaType(file).value();
auto extension = std::string(file.getFileExtension());
if (!extension.empty() && extension.front() != '.')
{
@@ -294,24 +301,30 @@ void ReportController::uploadPhotos(
const auto fullPath = reportDir / fileName;
if (file.saveAs(fullPath.string()) != 0)
{
callback(visione::http::error("photo_save_failed",
callback(visione::http::error("media_save_failed",
drogon::k500InternalServerError));
return;
}
const auto url = publicBasePath + "/reports/" + std::to_string(reportId) +
"/" + fileName;
auto saved = service.addPhoto(*user,
auto saved = service.addMedia(*user,
reportId,
url,
file.getFileName(),
imageContentType(file),
mediaType.contentType,
mediaType.kind,
file.fileLength());
if (!saved.get("ok", false).asBool())
{
callback(visione::http::json(std::move(saved), drogon::k403Forbidden));
return;
}
Json::Value item;
item["url"] = url;
item["kind"] = mediaType.kind;
item["content_type"] = mediaType.contentType;
response["media"].append(item);
response["photos"].append(url);
}
+5 -2
View File
@@ -27,7 +27,10 @@ class ReportController : public drogon::HttpController<ReportController>
ADD_METHOD_TO(ReportController::addFeedback,
"/api/v1/reports/{1}/feedback",
drogon::Post);
ADD_METHOD_TO(ReportController::uploadPhotos,
ADD_METHOD_TO(ReportController::uploadMedia,
"/api/v1/reports/{1}/media",
drogon::Post);
ADD_METHOD_TO(ReportController::uploadMedia,
"/api/v1/reports/{1}/photos",
drogon::Post);
METHOD_LIST_END
@@ -63,7 +66,7 @@ class ReportController : public drogon::HttpController<ReportController>
const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&callback,
long long reportId);
void uploadPhotos(
void uploadMedia(
const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&callback,
long long reportId);