feat: Implement merge person functionality with associated request and repository methods
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
use axum::{
|
||||
Json, Router,
|
||||
extract::{Path, State},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{get, post, put},
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use uuid::Uuid;
|
||||
@@ -12,8 +12,8 @@ use crate::{
|
||||
error::ApiError,
|
||||
middleware::auth::UserId,
|
||||
schema::{
|
||||
AssignFaceRequest, CreatePersonRequest, FaceRegionResponse, PersonResponse,
|
||||
SharePersonRequest, UpdatePersonRequest,
|
||||
AssignFaceRequest, CreatePersonRequest, FaceRegionResponse, MergePersonRequest,
|
||||
PersonResponse, SharePersonRequest, UpdatePersonRequest,
|
||||
},
|
||||
state::AppState,
|
||||
};
|
||||
@@ -23,11 +23,13 @@ pub fn people_routes() -> Router<AppState> {
|
||||
.route("/", get(list_people).post(create_person))
|
||||
.route(
|
||||
"/{person_id}",
|
||||
get(get_person)
|
||||
.put(update_person)
|
||||
.delete(delete_person),
|
||||
get(get_person).put(update_person).delete(delete_person),
|
||||
)
|
||||
.route("/{person_id}/share", post(share_person).delete(unshare_person))
|
||||
.route(
|
||||
"/{person_id}/share",
|
||||
post(share_person).delete(unshare_person),
|
||||
)
|
||||
.route("/{person_id}/merge", post(merge_person))
|
||||
}
|
||||
|
||||
pub fn face_routes() -> Router<AppState> {
|
||||
@@ -53,10 +55,7 @@ async fn get_person(
|
||||
UserId(user_id): UserId,
|
||||
Path(person_id): Path<Uuid>,
|
||||
) -> Result<Json<PersonResponse>, ApiError> {
|
||||
let person = state
|
||||
.person_service
|
||||
.get_person(person_id, user_id)
|
||||
.await?;
|
||||
let person = state.person_service.get_person(person_id, user_id).await?;
|
||||
Ok(Json(PersonResponse::from(person)))
|
||||
}
|
||||
|
||||
@@ -149,4 +148,17 @@ async fn assign_face_to_person(
|
||||
.assign_face_to_person(face_id, payload.person_id, user_id)
|
||||
.await?;
|
||||
Ok(Json(FaceRegionResponse::from(face)))
|
||||
}
|
||||
}
|
||||
|
||||
async fn merge_person(
|
||||
State(state): State<AppState>,
|
||||
UserId(user_id): UserId,
|
||||
Path(target_person_id): Path<Uuid>,
|
||||
Json(payload): Json<MergePersonRequest>,
|
||||
) -> Result<StatusCode, ApiError> {
|
||||
state
|
||||
.person_service
|
||||
.merge_people(target_person_id, payload.source_person_id, user_id)
|
||||
.await?;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
@@ -239,3 +239,8 @@ pub struct PublicAlbumBundleResponse {
|
||||
pub album: AlbumResponse,
|
||||
pub media: Vec<MediaResponse>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MergePersonRequest {
|
||||
pub source_person_id: Uuid,
|
||||
}
|
||||
|
||||
@@ -183,4 +183,36 @@ impl PersonService for PersonServiceImpl {
|
||||
.remove_share(person_id, target_user_id)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn merge_people(
|
||||
&self,
|
||||
target_person_id: Uuid,
|
||||
source_person_id: Uuid,
|
||||
user_id: Uuid,
|
||||
) -> CoreResult<()> {
|
||||
if target_person_id == source_person_id {
|
||||
return Err(CoreError::Validation(
|
||||
"Cannot merge the same person".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
self.auth_service
|
||||
.check_permission(
|
||||
Some(user_id),
|
||||
authz::Permission::EditPerson(target_person_id),
|
||||
)
|
||||
.await?;
|
||||
self.auth_service
|
||||
.check_permission(
|
||||
Some(user_id),
|
||||
authz::Permission::EditPerson(source_person_id),
|
||||
)
|
||||
.await?;
|
||||
|
||||
self.face_repo
|
||||
.reassign_person(source_person_id, target_person_id)
|
||||
.await?;
|
||||
|
||||
self.person_repo.delete(source_person_id).await
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user