3491 lines
83 KiB
YAML
3491 lines
83 KiB
YAML
{
|
|
"components": {
|
|
"responses": {
|
|
"BadRequest": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Invalid request or business validation failure."
|
|
},
|
|
"Forbidden": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Authenticated user cannot perform this action."
|
|
},
|
|
"NotFound": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Requested resource was not found."
|
|
},
|
|
"Unauthorized": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Missing or invalid bearer token."
|
|
}
|
|
},
|
|
"schemas": {
|
|
"AdminUser": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"banned": {
|
|
"type": "boolean"
|
|
},
|
|
"email": {
|
|
"format": "email",
|
|
"type": "string"
|
|
},
|
|
"first_name": {
|
|
"type": "string"
|
|
},
|
|
"fiscal_code": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"last_name": {
|
|
"type": "string"
|
|
},
|
|
"must_change_password": {
|
|
"type": "boolean"
|
|
},
|
|
"phone": {
|
|
"type": "string"
|
|
},
|
|
"points": {
|
|
"type": "integer"
|
|
},
|
|
"roles": {
|
|
"description": "Comma-separated role names from SQL GROUP_CONCAT.",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"Area": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"active": {
|
|
"type": "boolean"
|
|
},
|
|
"boundary_geojson": {
|
|
"$ref": "#/components/schemas/GeoJsonObject"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"AreaListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"areas": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Area"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"areas"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"AssignTeamRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"team_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"team_id"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Category": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"active": {
|
|
"type": "boolean"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"CategoryListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"categories": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Category"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"categories"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ChangePasswordRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"current_password": {
|
|
"format": "password",
|
|
"type": "string"
|
|
},
|
|
"new_password": {
|
|
"format": "password",
|
|
"minLength": 10,
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"current_password",
|
|
"new_password"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"CreateAreaRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"boundary_geojson": {
|
|
"$ref": "#/components/schemas/GeoJsonObject"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"name",
|
|
"boundary_geojson"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"CreateCategoryRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"name"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"CreateReportRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"address": {
|
|
"type": "string"
|
|
},
|
|
"category_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"latitude": {
|
|
"format": "double",
|
|
"type": "number"
|
|
},
|
|
"longitude": {
|
|
"format": "double",
|
|
"type": "number"
|
|
},
|
|
"media": {
|
|
"items": {
|
|
"format": "uri-reference",
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"category_id",
|
|
"latitude",
|
|
"longitude",
|
|
"address",
|
|
"description"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"CreateReportResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"area_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"report_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"report_id"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"CreateTeamRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"area_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"team_category_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"team_category_id",
|
|
"name"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"CurrentUser": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"email": {
|
|
"format": "email",
|
|
"type": "string"
|
|
},
|
|
"first_name": {
|
|
"type": "string"
|
|
},
|
|
"fiscal_code": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"last_name": {
|
|
"type": "string"
|
|
},
|
|
"must_change_password": {
|
|
"type": "boolean"
|
|
},
|
|
"permissions": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"phone": {
|
|
"type": "string"
|
|
},
|
|
"points": {
|
|
"type": "integer"
|
|
},
|
|
"role": {
|
|
"type": "string"
|
|
},
|
|
"roles": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"first_name",
|
|
"last_name",
|
|
"email",
|
|
"fiscal_code",
|
|
"points",
|
|
"must_change_password",
|
|
"role",
|
|
"roles",
|
|
"permissions"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"CurrentUserResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"user": {
|
|
"$ref": "#/components/schemas/CurrentUser"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"user"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"EmailRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"email": {
|
|
"format": "email",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"email"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ErrorResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"error": {
|
|
"type": "string"
|
|
},
|
|
"fields": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"message": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"error"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"FeedbackRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"comment": {
|
|
"type": "string"
|
|
},
|
|
"rating": {
|
|
"maximum": 5,
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"rating"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"FlagRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"details": {
|
|
"type": "string"
|
|
},
|
|
"reason": {
|
|
"maxLength": 120,
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"reason"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"FlagResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"flag_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"flag_id"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"GeoJsonObject": {
|
|
"additionalProperties": true,
|
|
"description": "GeoJSON polygon or multipolygon boundary.",
|
|
"type": "object"
|
|
},
|
|
"HealthResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"service": {
|
|
"example": "visione-backend",
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"example": "ok",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"status",
|
|
"service"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"InterventionSummaryResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"latest_messages": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Message"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"media": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Media"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"summary": {
|
|
"$ref": "#/components/schemas/Report"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"summary",
|
|
"media",
|
|
"latest_messages"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Media": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"content_type": {
|
|
"type": "string"
|
|
},
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"media_kind": {
|
|
"enum": [
|
|
"IMAGE",
|
|
"VIDEO"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"original_filename": {
|
|
"type": "string"
|
|
},
|
|
"report_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"size_bytes": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"url": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"MediaUploadRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"files": {
|
|
"items": {
|
|
"format": "binary",
|
|
"type": "string"
|
|
},
|
|
"maxItems": 5,
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"files"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"MediaUploadResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"media": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Media"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"media"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Message": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"body": {
|
|
"type": "string"
|
|
},
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"first_name": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"last_name": {
|
|
"type": "string"
|
|
},
|
|
"report_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"user_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"MessageListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"messages": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Message"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"messages"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"MessageRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"body": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"body"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ModerationFlag": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"content_type": {
|
|
"enum": [
|
|
"REPORT",
|
|
"MESSAGE"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"created_by_email": {
|
|
"type": "string"
|
|
},
|
|
"created_by_user_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"details": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"message_id": {
|
|
"format": "int64",
|
|
"nullable": true,
|
|
"type": "integer"
|
|
},
|
|
"reason": {
|
|
"type": "string"
|
|
},
|
|
"report_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"resolution_note": {
|
|
"nullable": true,
|
|
"type": "string"
|
|
},
|
|
"resolved_at": {
|
|
"nullable": true,
|
|
"type": "string"
|
|
},
|
|
"resolved_by_email": {
|
|
"nullable": true,
|
|
"type": "string"
|
|
},
|
|
"resolved_by_user_id": {
|
|
"format": "int64",
|
|
"nullable": true,
|
|
"type": "integer"
|
|
},
|
|
"status": {
|
|
"enum": [
|
|
"OPEN",
|
|
"RESOLVED",
|
|
"DISMISSED"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"ModerationListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"flags": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/ModerationFlag"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"page": {
|
|
"type": "integer"
|
|
},
|
|
"per_page": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"page",
|
|
"per_page",
|
|
"flags"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Notification": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"body": {
|
|
"type": "string"
|
|
},
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"read_at": {
|
|
"nullable": true,
|
|
"type": "string"
|
|
},
|
|
"report_id": {
|
|
"format": "int64",
|
|
"nullable": true,
|
|
"type": "integer"
|
|
},
|
|
"title": {
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"NotificationListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"notifications": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Notification"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"page": {
|
|
"type": "integer"
|
|
},
|
|
"per_page": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"page",
|
|
"per_page",
|
|
"notifications"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"OkResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"OpenApiDocument": {
|
|
"additionalProperties": true,
|
|
"description": "Generated OpenAPI 3 document.",
|
|
"type": "object"
|
|
},
|
|
"OpenDataReport": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"area_id": {
|
|
"format": "int64",
|
|
"nullable": true,
|
|
"type": "integer"
|
|
},
|
|
"area_name": {
|
|
"nullable": true,
|
|
"type": "string"
|
|
},
|
|
"category_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"category_name": {
|
|
"type": "string"
|
|
},
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"latitude": {
|
|
"type": "number"
|
|
},
|
|
"longitude": {
|
|
"type": "number"
|
|
},
|
|
"status": {
|
|
"$ref": "#/components/schemas/ReportStatus"
|
|
},
|
|
"updated_at": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"OpenDataReportListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"page": {
|
|
"type": "integer"
|
|
},
|
|
"per_page": {
|
|
"type": "integer"
|
|
},
|
|
"reports": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/OpenDataReport"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"page",
|
|
"per_page",
|
|
"reports"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"OtpRequestResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"delivery": {
|
|
"example": "mailhog",
|
|
"type": "string"
|
|
},
|
|
"expires_in_minutes": {
|
|
"type": "integer"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"delivery",
|
|
"expires_in_minutes"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"OverviewStatsResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"avg_resolution_hours": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"value": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"avg_resolution_hours_by_area": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"area": {
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"avg_resolution_hours_by_category": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"category": {
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"monthly_reports": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"month": {
|
|
"type": "string"
|
|
},
|
|
"total": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"reports_by_area": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"area": {
|
|
"type": "string"
|
|
},
|
|
"total": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"reports_by_category": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"category": {
|
|
"type": "string"
|
|
},
|
|
"total": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"reports_by_status": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"status": {
|
|
"$ref": "#/components/schemas/ReportStatus"
|
|
},
|
|
"total": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"reports_by_team": {
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"team": {
|
|
"type": "string"
|
|
},
|
|
"total": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"reports_by_status",
|
|
"reports_by_area",
|
|
"avg_resolution_hours",
|
|
"reports_by_category",
|
|
"reports_by_team",
|
|
"monthly_reports",
|
|
"avg_resolution_hours_by_category",
|
|
"avg_resolution_hours_by_area"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"PagedReportListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"page": {
|
|
"type": "integer"
|
|
},
|
|
"per_page": {
|
|
"type": "integer"
|
|
},
|
|
"reports": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Report"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"page",
|
|
"per_page",
|
|
"reports"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"PasswordLoginRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"email": {
|
|
"format": "email",
|
|
"type": "string"
|
|
},
|
|
"password": {
|
|
"format": "password",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"email",
|
|
"password"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ReadyResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"dependencies": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"mysql": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"mysql"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"errors": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"mysql": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"status": {
|
|
"enum": [
|
|
"ready",
|
|
"not_ready"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"status",
|
|
"dependencies"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"RegisterCitizenRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"birth_date": {
|
|
"format": "date",
|
|
"type": "string"
|
|
},
|
|
"birth_place": {
|
|
"type": "string"
|
|
},
|
|
"email": {
|
|
"format": "email",
|
|
"type": "string"
|
|
},
|
|
"first_name": {
|
|
"type": "string"
|
|
},
|
|
"fiscal_code": {
|
|
"maxLength": 16,
|
|
"minLength": 16,
|
|
"type": "string"
|
|
},
|
|
"last_name": {
|
|
"type": "string"
|
|
},
|
|
"password": {
|
|
"format": "password",
|
|
"minLength": 10,
|
|
"type": "string"
|
|
},
|
|
"phone": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"first_name",
|
|
"last_name",
|
|
"email",
|
|
"password",
|
|
"fiscal_code"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"RegisterCitizenResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"user_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"user_id"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Report": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"address": {
|
|
"type": "string"
|
|
},
|
|
"area_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"area_name": {
|
|
"type": "string"
|
|
},
|
|
"assigned_operator_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"category_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"category_name": {
|
|
"type": "string"
|
|
},
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"latitude": {
|
|
"type": "number"
|
|
},
|
|
"longitude": {
|
|
"type": "number"
|
|
},
|
|
"status": {
|
|
"$ref": "#/components/schemas/ReportStatus"
|
|
},
|
|
"updated_at": {
|
|
"type": "string"
|
|
},
|
|
"user_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"category_id",
|
|
"latitude",
|
|
"longitude",
|
|
"address",
|
|
"description",
|
|
"status"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ReportDetailResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"history": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/StatusHistoryItem"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"media": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Media"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"report": {
|
|
"$ref": "#/components/schemas/Report"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"report",
|
|
"history",
|
|
"media"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ReportListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"reports": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Report"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"reports"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ReportStatus": {
|
|
"enum": [
|
|
"OPEN",
|
|
"UNDER_REVIEW",
|
|
"ASSIGNED",
|
|
"IN_PROGRESS",
|
|
"RESOLVED",
|
|
"REJECTED",
|
|
"CLOSED"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"RewardEvent": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"points": {
|
|
"type": "integer"
|
|
},
|
|
"reason": {
|
|
"type": "string"
|
|
},
|
|
"report_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"RewardsResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"page": {
|
|
"type": "integer"
|
|
},
|
|
"per_page": {
|
|
"type": "integer"
|
|
},
|
|
"points": {
|
|
"type": "integer"
|
|
},
|
|
"reward_events": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/RewardEvent"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"points",
|
|
"page",
|
|
"per_page",
|
|
"reward_events"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"StatusHistoryItem": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"changed_by_user_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"created_at": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"new_status": {
|
|
"$ref": "#/components/schemas/ReportStatus"
|
|
},
|
|
"note": {
|
|
"type": "string"
|
|
},
|
|
"old_status": {
|
|
"$ref": "#/components/schemas/ReportStatus"
|
|
},
|
|
"report_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"Team": {
|
|
"additionalProperties": true,
|
|
"properties": {
|
|
"active": {
|
|
"type": "boolean"
|
|
},
|
|
"area_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"area_name": {
|
|
"type": "string"
|
|
},
|
|
"category_name": {
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"team_category_id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"TeamListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"teams": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Team"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"teams"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"TokenResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"expires_in_hours": {
|
|
"type": "integer"
|
|
},
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"token": {
|
|
"type": "string"
|
|
},
|
|
"token_type": {
|
|
"example": "Bearer",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"token",
|
|
"token_type",
|
|
"expires_in_hours"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"UpdateModerationRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"reject_report": {
|
|
"type": "boolean"
|
|
},
|
|
"resolution_note": {
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"enum": [
|
|
"RESOLVED",
|
|
"DISMISSED"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"status"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"UpdateStatusRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"note": {
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"$ref": "#/components/schemas/ReportStatus"
|
|
}
|
|
},
|
|
"required": [
|
|
"status"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"UpdateUserBanRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"banned": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"banned"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"UpdateUserRolesRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"roles": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"roles"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"UserListResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ok": {
|
|
"type": "boolean"
|
|
},
|
|
"users": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/AdminUser"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ok",
|
|
"users"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"VerifyOtpRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"code": {
|
|
"type": "string"
|
|
},
|
|
"email": {
|
|
"format": "email",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"email",
|
|
"code"
|
|
],
|
|
"type": "object"
|
|
}
|
|
},
|
|
"securitySchemes": {
|
|
"bearerAuth": {
|
|
"scheme": "bearer",
|
|
"type": "http"
|
|
}
|
|
}
|
|
},
|
|
"info": {
|
|
"description": "Visione OpenAPI contract maintained manually and merged with Drogon route extraction.",
|
|
"title": "Visione API",
|
|
"version": "0.1.0"
|
|
},
|
|
"openapi": "3.0.3",
|
|
"paths": {
|
|
"/api/v1/admin/areas": {
|
|
"get": {
|
|
"description": "Lists configured municipal areas.",
|
|
"operationId": "AdminController.listAreas",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AreaListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Area list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List areas",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
},
|
|
"post": {
|
|
"description": "Creates a municipal area with GeoJSON boundary.",
|
|
"operationId": "AdminController.createArea",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CreateAreaRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Created area result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Create area",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/categories": {
|
|
"get": {
|
|
"description": "Lists active report categories.",
|
|
"operationId": "AdminController.listCategories",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CategoryListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Report category list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List categories",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
},
|
|
"post": {
|
|
"description": "Creates a report category.",
|
|
"operationId": "AdminController.createCategory",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CreateCategoryRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Created category result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Create category",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation": {
|
|
"get": {
|
|
"description": "Lists moderation flags for admin/operator review.",
|
|
"operationId": "AdminController.listModeration",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "status",
|
|
"required": false,
|
|
"schema": {
|
|
"enum": [
|
|
"OPEN",
|
|
"RESOLVED",
|
|
"DISMISSED"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "per_page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ModerationListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Paged moderation flags."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List moderation flags",
|
|
"tags": [
|
|
"Moderation"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation/{id}": {
|
|
"patch": {
|
|
"description": "Resolves or dismisses a moderation flag. Optionally rejects the related report.",
|
|
"operationId": "AdminController.updateModeration",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UpdateModerationRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Moderation update result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Update moderation flag",
|
|
"tags": [
|
|
"Moderation"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/stats/overview": {
|
|
"get": {
|
|
"description": "Returns report statistics for administration dashboards.",
|
|
"operationId": "AdminController.overviewStats",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OverviewStatsResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Aggregated report statistics."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Overview stats",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/teams": {
|
|
"get": {
|
|
"description": "Lists intervention teams.",
|
|
"operationId": "AdminController.listTeams",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TeamListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Team list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List teams",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
},
|
|
"post": {
|
|
"description": "Creates an intervention team.",
|
|
"operationId": "AdminController.createTeam",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CreateTeamRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Created team result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Create team",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/users": {
|
|
"get": {
|
|
"description": "Lists platform users with role information.",
|
|
"operationId": "AdminController.listUsers",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "User list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List users",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/users/{id}/ban": {
|
|
"patch": {
|
|
"description": "Updates a user's banned flag.",
|
|
"operationId": "AdminController.updateUserBan",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UpdateUserBanRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Ban update result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Ban or unban user",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/users/{id}/roles": {
|
|
"patch": {
|
|
"description": "Replaces the roles assigned to a user.",
|
|
"operationId": "AdminController.updateUserRoles",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UpdateUserRolesRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Role update result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Update user roles",
|
|
"tags": [
|
|
"Admin"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/change-password": {
|
|
"post": {
|
|
"description": "Changes the authenticated user's password.",
|
|
"operationId": "AuthController.changePassword",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ChangePasswordRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Password change result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Change password",
|
|
"tags": [
|
|
"Auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/login/password": {
|
|
"post": {
|
|
"description": "Password-based login fallback for local development.",
|
|
"operationId": "AuthController.loginWithPassword",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PasswordLoginRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TokenResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Bearer token when credentials are valid."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
}
|
|
},
|
|
"summary": "Password login",
|
|
"tags": [
|
|
"Auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/otp/request": {
|
|
"post": {
|
|
"description": "Sends a one-time code by email through MailHog locally.",
|
|
"operationId": "AuthController.requestOtp",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/EmailRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OtpRequestResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "OTP challenge result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
}
|
|
},
|
|
"summary": "Request OTP",
|
|
"tags": [
|
|
"Auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/otp/verify": {
|
|
"post": {
|
|
"description": "Verifies an email OTP and creates an API token.",
|
|
"operationId": "AuthController.verifyOtp",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/VerifyOtpRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TokenResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Bearer token when verification succeeds."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
}
|
|
},
|
|
"summary": "Verify OTP",
|
|
"tags": [
|
|
"Auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/register": {
|
|
"post": {
|
|
"description": "Creates a citizen account with personal data and password.",
|
|
"operationId": "AuthController.registerCitizen",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RegisterCitizenRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RegisterCitizenResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Registration result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
}
|
|
},
|
|
"summary": "Register citizen",
|
|
"tags": [
|
|
"Auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/docs": {
|
|
"get": {
|
|
"description": "Serves a local Swagger UI page backed by openapi.json.",
|
|
"operationId": "ApiController.docs",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"text/html": {
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "HTML documentation page."
|
|
}
|
|
},
|
|
"summary": "Swagger UI",
|
|
"tags": [
|
|
"Technical"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/health": {
|
|
"get": {
|
|
"description": "Returns process health without checking dependencies.",
|
|
"operationId": "ApiController.health",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/HealthResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Service health status."
|
|
}
|
|
},
|
|
"summary": "Health check",
|
|
"tags": [
|
|
"Technical"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/me": {
|
|
"get": {
|
|
"description": "Returns the authenticated user's profile and permissions.",
|
|
"operationId": "AuthController.me",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CurrentUserResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Authenticated user context."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Current user",
|
|
"tags": [
|
|
"Auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/me/rewards": {
|
|
"get": {
|
|
"description": "Returns current points and reward events for the authenticated user.",
|
|
"operationId": "UserController.rewards",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "per_page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RewardsResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Reward ledger."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Reward ledger",
|
|
"tags": [
|
|
"User"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/notifications": {
|
|
"get": {
|
|
"description": "Lists notifications for the authenticated user.",
|
|
"operationId": "UserController.listNotifications",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "per_page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotificationListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Paged notification list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List notifications",
|
|
"tags": [
|
|
"User"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/notifications/{id}/read": {
|
|
"patch": {
|
|
"description": "Marks a notification as read for the authenticated user.",
|
|
"operationId": "UserController.markNotificationRead",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Notification update result."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
},
|
|
"404": {
|
|
"$ref": "#/components/responses/NotFound"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Mark notification read",
|
|
"tags": [
|
|
"User"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/open-data/reports": {
|
|
"get": {
|
|
"description": "Returns anonymized resolved/closed report data for public reuse.",
|
|
"operationId": "PublicController.openDataReports",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "per_page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OpenDataReportListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Paged open-data report list."
|
|
}
|
|
},
|
|
"summary": "Open data reports",
|
|
"tags": [
|
|
"Public"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/openapi.json": {
|
|
"get": {
|
|
"description": "Returns the generated OpenAPI JSON document.",
|
|
"operationId": "ApiController.openApi",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OpenApiDocument"
|
|
}
|
|
}
|
|
},
|
|
"description": "OpenAPI 3 JSON document."
|
|
},
|
|
"404": {
|
|
"$ref": "#/components/responses/NotFound"
|
|
}
|
|
},
|
|
"summary": "OpenAPI document",
|
|
"tags": [
|
|
"Technical"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/operator/reports/assigned": {
|
|
"get": {
|
|
"description": "Lists reports assigned to the authenticated operator.",
|
|
"operationId": "ReportController.assignedReports",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "per_page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PagedReportListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Paged assigned report list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Assigned reports",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/operator/reports/open": {
|
|
"get": {
|
|
"description": "Lists open reports not yet taken by an operator.",
|
|
"operationId": "ReportController.openReports",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "per_page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PagedReportListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Paged open report list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Open unassigned reports",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/operator/reports/others": {
|
|
"get": {
|
|
"description": "Lists reports assigned to another operator.",
|
|
"operationId": "ReportController.otherOperatorReports",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "per_page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PagedReportListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Paged report list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Other operator reports",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/ready": {
|
|
"get": {
|
|
"description": "Checks whether MySQL is reachable.",
|
|
"operationId": "ApiController.ready",
|
|
"parameters": [],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ReadyResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Dependency readiness status."
|
|
},
|
|
"503": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ReadyResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Dependency readiness failure."
|
|
}
|
|
},
|
|
"summary": "Readiness check",
|
|
"tags": [
|
|
"Technical"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports": {
|
|
"get": {
|
|
"description": "Lists reports visible to the authenticated user.",
|
|
"operationId": "ReportController.list",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "area_id",
|
|
"required": false,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "category_id",
|
|
"required": false,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "status",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ReportListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Report list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List reports",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
},
|
|
"post": {
|
|
"description": "Creates a citizen urban issue report.",
|
|
"operationId": "ReportController.create",
|
|
"parameters": [],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CreateReportRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CreateReportResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Created report id and inferred area."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Create report",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}": {
|
|
"get": {
|
|
"description": "Returns report detail, status history and media.",
|
|
"operationId": "ReportController.detail",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ReportDetailResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Report detail."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Report detail",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/assignments": {
|
|
"post": {
|
|
"description": "Assigns an intervention team to a report.",
|
|
"operationId": "ReportController.assignTeam",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AssignTeamRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Assignment result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Assign team",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/feedback": {
|
|
"post": {
|
|
"description": "Adds citizen feedback after report resolution.",
|
|
"operationId": "ReportController.addFeedback",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/FeedbackRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Feedback result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Add feedback",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/flags": {
|
|
"post": {
|
|
"description": "Creates a moderation flag for a report.",
|
|
"operationId": "ReportController.flagReport",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/FlagRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/FlagResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Created moderation flag."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Flag report",
|
|
"tags": [
|
|
"Moderation"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/intervention-summary": {
|
|
"get": {
|
|
"description": "Returns operator-facing report data, media and the latest messages for intervention planning.",
|
|
"operationId": "ReportController.interventionSummary",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/InterventionSummaryResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Intervention summary."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Intervention summary",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/media": {
|
|
"post": {
|
|
"description": "Uploads report images or videos as multipart files.",
|
|
"operationId": "ReportController.uploadMedia",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"multipart/form-data": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MediaUploadRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MediaUploadResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Uploaded media list."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Upload media",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/messages": {
|
|
"get": {
|
|
"description": "Lists messages for a report conversation.",
|
|
"operationId": "ReportController.listMessages",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MessageListResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Message list."
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "List messages",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
},
|
|
"post": {
|
|
"description": "Adds a citizen/operator message to a report.",
|
|
"operationId": "ReportController.addMessage",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MessageRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Message creation result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Add message",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/messages/{message_id}/flags": {
|
|
"post": {
|
|
"description": "Creates a moderation flag for a report message.",
|
|
"operationId": "ReportController.flagMessage",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "path",
|
|
"name": "message_id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/FlagRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/FlagResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Created moderation flag."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Flag message",
|
|
"tags": [
|
|
"Moderation"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/status": {
|
|
"patch": {
|
|
"description": "Updates a report status following allowed transitions.",
|
|
"operationId": "ReportController.updateStatus",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UpdateStatusRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Status update result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Update report status",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/reports/{id}/take": {
|
|
"post": {
|
|
"description": "Assigns an open report to the current operator.",
|
|
"operationId": "ReportController.takeReport",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "id",
|
|
"required": true,
|
|
"schema": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/OkResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "Take report result."
|
|
},
|
|
"400": {
|
|
"$ref": "#/components/responses/BadRequest"
|
|
},
|
|
"401": {
|
|
"$ref": "#/components/responses/Unauthorized"
|
|
},
|
|
"403": {
|
|
"$ref": "#/components/responses/Forbidden"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"summary": "Take report",
|
|
"tags": [
|
|
"Reports"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"servers": [
|
|
{
|
|
"url": "http://localhost:5555"
|
|
}
|
|
]
|
|
}
|