Remove photo alias
This commit is contained in:
@@ -26,7 +26,7 @@
|
|||||||
- OpenAPI: `cmake --build build --target openapi`
|
- OpenAPI: `cmake --build build --target openapi`
|
||||||
- Lab frontend: `streamlit run tools/visione-lab/app.py`
|
- Lab frontend: `streamlit run tools/visione-lab/app.py`
|
||||||
- Local services: `docker compose up -d`
|
- Local services: `docker compose up -d`
|
||||||
- App: `./build/visione-backend config.json`
|
- App: `./build/visione-backend`
|
||||||
|
|
||||||
## Development Workflow
|
## Development Workflow
|
||||||
- Update docs when behavior, schema, setup or API contracts change.
|
- Update docs when behavior, schema, setup or API contracts change.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ docker compose up -d
|
|||||||
|
|
||||||
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
|
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
|
||||||
cmake --build build
|
cmake --build build
|
||||||
./build/visione-backend config.json
|
./build/visione-backend
|
||||||
```
|
```
|
||||||
|
|
||||||
The API listens on `http://localhost:5555`.
|
The API listens on `http://localhost:5555`.
|
||||||
|
|||||||
@@ -287,7 +287,6 @@ void ReportController::uploadMedia(
|
|||||||
Json::Value response;
|
Json::Value response;
|
||||||
response["ok"] = true;
|
response["ok"] = true;
|
||||||
response["media"] = Json::arrayValue;
|
response["media"] = Json::arrayValue;
|
||||||
response["photos"] = Json::arrayValue;
|
|
||||||
|
|
||||||
for (const auto &file : parser.getFiles())
|
for (const auto &file : parser.getFiles())
|
||||||
{
|
{
|
||||||
@@ -325,7 +324,6 @@ void ReportController::uploadMedia(
|
|||||||
item["kind"] = mediaType.kind;
|
item["kind"] = mediaType.kind;
|
||||||
item["content_type"] = mediaType.contentType;
|
item["content_type"] = mediaType.contentType;
|
||||||
response["media"].append(item);
|
response["media"].append(item);
|
||||||
response["photos"].append(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(visione::http::json(std::move(response), drogon::k201Created));
|
callback(visione::http::json(std::move(response), drogon::k201Created));
|
||||||
|
|||||||
@@ -30,9 +30,6 @@ class ReportController : public drogon::HttpController<ReportController>
|
|||||||
ADD_METHOD_TO(ReportController::uploadMedia,
|
ADD_METHOD_TO(ReportController::uploadMedia,
|
||||||
"/api/v1/reports/{1}/media",
|
"/api/v1/reports/{1}/media",
|
||||||
drogon::Post);
|
drogon::Post);
|
||||||
ADD_METHOD_TO(ReportController::uploadMedia,
|
|
||||||
"/api/v1/reports/{1}/photos",
|
|
||||||
drogon::Post);
|
|
||||||
METHOD_LIST_END
|
METHOD_LIST_END
|
||||||
|
|
||||||
void create(const drogon::HttpRequestPtr &req,
|
void create(const drogon::HttpRequestPtr &req,
|
||||||
|
|||||||
+1
-2
@@ -33,8 +33,7 @@ Authorization: Bearer <token>
|
|||||||
- `POST /reports/{id}/assignments`: assign a team.
|
- `POST /reports/{id}/assignments`: assign a team.
|
||||||
- `POST /reports/{id}/feedback`: add citizen feedback.
|
- `POST /reports/{id}/feedback`: add citizen feedback.
|
||||||
- `POST /reports/{id}/media`: upload up to five multipart media files. Supported
|
- `POST /reports/{id}/media`: upload up to five multipart media files. Supported
|
||||||
types are JPEG, PNG, WebP, MP4, WebM and QuickTime. The legacy
|
types are JPEG, PNG, WebP, MP4, WebM and QuickTime.
|
||||||
`/reports/{id}/photos` path is kept as a compatibility alias.
|
|
||||||
|
|
||||||
## Admin Reference Data
|
## Admin Reference Data
|
||||||
- `GET|POST /admin/categories`
|
- `GET|POST /admin/categories`
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
than plain SHA-256 and available through the existing OpenSSL dependency.
|
than plain SHA-256 and available through the existing OpenSSL dependency.
|
||||||
- Added report media uploads at `POST /api/v1/reports/{id}/media`.
|
- Added report media uploads at `POST /api/v1/reports/{id}/media`.
|
||||||
- Supported JPEG, PNG, WebP, MP4, WebM and QuickTime uploads.
|
- Supported JPEG, PNG, WebP, MP4, WebM and QuickTime uploads.
|
||||||
- Kept `POST /api/v1/reports/{id}/photos` as a temporary compatibility alias.
|
- Removed the old `/photos` upload path; report attachments now use `/media`.
|
||||||
- Added generated OpenAPI JSON from Drogon controller route macros.
|
- Added generated OpenAPI JSON from Drogon controller route macros.
|
||||||
- Exposed `/api/v1/openapi.json` and `/api/v1/docs`.
|
- Exposed `/api/v1/openapi.json` and `/api/v1/docs`.
|
||||||
- Added a small Streamlit API lab for visual endpoint testing.
|
- Added a small Streamlit API lab for visual endpoint testing.
|
||||||
@@ -17,5 +17,5 @@
|
|||||||
- Consider extracting `tools/drogon-openapi-gen` into an open-source standalone
|
- Consider extracting `tools/drogon-openapi-gen` into an open-source standalone
|
||||||
project once the conventions stabilize.
|
project once the conventions stabilize.
|
||||||
- Add minimal media upload integration tests after endpoint contracts settle.
|
- Add minimal media upload integration tests after endpoint contracts settle.
|
||||||
- Replace the compatibility `/photos` alias once external scripts use `/media`.
|
- Keep API and docs on `media` terminology only.
|
||||||
- Keep the Streamlit lab small and replace it with the real frontend later.
|
- Keep the Streamlit lab small and replace it with the real frontend later.
|
||||||
|
|||||||
@@ -6,16 +6,15 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main()
|
||||||
{
|
{
|
||||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||||
(void)RequestLogger::classTypeName();
|
(void)RequestLogger::classTypeName();
|
||||||
|
|
||||||
const auto configPath = argc > 1 ? argv[1] : "config.json";
|
|
||||||
Json::Value requestLoggerConfig;
|
Json::Value requestLoggerConfig;
|
||||||
requestLoggerConfig["include_query"] = true;
|
requestLoggerConfig["include_query"] = true;
|
||||||
|
|
||||||
drogon::app().loadConfigFile(configPath);
|
drogon::app().loadConfigFile("config.json");
|
||||||
drogon::app().addPlugin("RequestLogger", {}, requestLoggerConfig);
|
drogon::app().addPlugin("RequestLogger", {}, requestLoggerConfig);
|
||||||
visione::cors::configure();
|
visione::cors::configure();
|
||||||
|
|
||||||
|
|||||||
@@ -181,11 +181,9 @@ Json::Value ReportService::createReport(const auth::UserContext &user,
|
|||||||
reportId,
|
reportId,
|
||||||
user.id);
|
user.id);
|
||||||
|
|
||||||
const auto &mediaItems =
|
if (body["media"].isArray())
|
||||||
body["media"].isArray() ? body["media"] : body["photos"];
|
|
||||||
if (mediaItems.isArray())
|
|
||||||
{
|
{
|
||||||
for (const auto &item : mediaItems)
|
for (const auto &item : body["media"])
|
||||||
{
|
{
|
||||||
if (item.isString() && !item.asString().empty())
|
if (item.isString() && !item.asString().empty())
|
||||||
{
|
{
|
||||||
@@ -287,7 +285,6 @@ Json::Value ReportService::reportDetail(const auth::UserContext &user,
|
|||||||
response["media"] = repositories::resultToJson(db->execSqlSync(
|
response["media"] = repositories::resultToJson(db->execSqlSync(
|
||||||
"SELECT * FROM report_photos WHERE report_id = ? ORDER BY id",
|
"SELECT * FROM report_photos WHERE report_id = ? ORDER BY id",
|
||||||
reportId));
|
reportId));
|
||||||
response["photos"] = response["media"];
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ def openapi_path(path: str) -> tuple[str, list[dict]]:
|
|||||||
def request_body(path: str, method: str) -> dict | None:
|
def request_body(path: str, method: str) -> dict | None:
|
||||||
if method != "post" and method != "patch":
|
if method != "post" and method != "patch":
|
||||||
return None
|
return None
|
||||||
if path.endswith("/media") or path.endswith("/photos"):
|
if path.endswith("/media"):
|
||||||
return {
|
return {
|
||||||
"required": True,
|
"required": True,
|
||||||
"content": {
|
"content": {
|
||||||
|
|||||||
Reference in New Issue
Block a user