feat: POST /identity/:uuid/bind/trace endpoint
This commit is contained in:
@@ -9,7 +9,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::core::db::{Database, PostgresDb};
|
use crate::core::db::{Database, PostgresDb};
|
||||||
use crate::core::person_identity::{
|
use crate::core::person_identity::{
|
||||||
BindIdentityRequest, Identity, MergeIdentitiesRequest, UnbindIdentityRequest,
|
BindIdentityRequest, BindIdentityTraceRequest, Identity, MergeIdentitiesRequest,
|
||||||
|
UnbindIdentityRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
@@ -388,6 +389,80 @@ pub struct TracesQuery {
|
|||||||
pub page_size: Option<usize>,
|
pub page_size: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn bind_identity_trace(
|
||||||
|
Path(identity_uuid): Path<String>,
|
||||||
|
Json(req): Json<BindIdentityTraceRequest>,
|
||||||
|
) -> Result<Json<ApiResponse<serde_json::Value>>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
let fd_table = crate::core::db::schema::table_name("face_detections");
|
||||||
|
let id_table = crate::core::db::schema::table_name("identities");
|
||||||
|
|
||||||
|
let db = sqlx::PgPool::connect(&crate::core::config::DATABASE_URL)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(serde_json::json!({"error": e.to_string()})),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let identity_row: Option<(i64, String)> = sqlx::query_as(&format!(
|
||||||
|
"SELECT id::bigint, name FROM {} WHERE uuid = $1::uuid",
|
||||||
|
id_table
|
||||||
|
))
|
||||||
|
.bind(&identity_uuid)
|
||||||
|
.fetch_optional(&db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(serde_json::json!({"error": format!("DB error: {}", e)})),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let (identity_id, name) = identity_row.ok_or_else(|| {
|
||||||
|
(
|
||||||
|
StatusCode::NOT_FOUND,
|
||||||
|
Json(serde_json::json!({"error": format!("Identity not found: {}", identity_uuid)})),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let result = sqlx::query(&format!(
|
||||||
|
"UPDATE {} SET identity_id = $1 WHERE file_uuid = $2 AND trace_id = $3",
|
||||||
|
fd_table
|
||||||
|
))
|
||||||
|
.bind(identity_id)
|
||||||
|
.bind(&req.file_uuid)
|
||||||
|
.bind(req.trace_id)
|
||||||
|
.execute(&db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(serde_json::json!({"error": format!("Update failed: {}", e)})),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let uuid_clean = identity_uuid.replace('-', "");
|
||||||
|
if let Err(e) =
|
||||||
|
crate::core::identity::storage::save_identity_file_by_pool(&db, &uuid_clean).await
|
||||||
|
{
|
||||||
|
tracing::warn!(
|
||||||
|
"[bind/trace] Failed to sync identity file for {}: {}",
|
||||||
|
uuid_clean,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Json(ApiResponse {
|
||||||
|
success: true,
|
||||||
|
message: format!(
|
||||||
|
"Bound trace {} of {} to {}",
|
||||||
|
req.trace_id, req.file_uuid, name
|
||||||
|
),
|
||||||
|
data: Some(serde_json::json!({"rows_affected": result.rows_affected()})),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_identity_traces(
|
pub async fn get_identity_traces(
|
||||||
State(state): State<crate::api::types::AppState>,
|
State(state): State<crate::api::types::AppState>,
|
||||||
Path(identity_uuid): Path<String>,
|
Path(identity_uuid): Path<String>,
|
||||||
@@ -488,6 +563,10 @@ pub async fn get_identity_traces(
|
|||||||
pub fn identity_binding_routes() -> Router<crate::api::types::AppState> {
|
pub fn identity_binding_routes() -> Router<crate::api::types::AppState> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/api/v1/identity/:identity_uuid/bind", post(bind_identity))
|
.route("/api/v1/identity/:identity_uuid/bind", post(bind_identity))
|
||||||
|
.route(
|
||||||
|
"/api/v1/identity/:identity_uuid/bind/trace",
|
||||||
|
post(bind_identity_trace),
|
||||||
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/v1/identity/:identity_uuid/unbind",
|
"/api/v1/identity/:identity_uuid/unbind",
|
||||||
post(unbind_identity),
|
post(unbind_identity),
|
||||||
|
|||||||
@@ -72,6 +72,12 @@ pub struct BindIdentityRequest {
|
|||||||
pub face_id: String,
|
pub face_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
pub struct BindIdentityTraceRequest {
|
||||||
|
pub file_uuid: String,
|
||||||
|
pub trace_id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub struct UnbindIdentityRequest {
|
pub struct UnbindIdentityRequest {
|
||||||
pub file_uuid: String,
|
pub file_uuid: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user