feat: Implement person and tag management services

- Added `Person` and `Tag` models to the core library.
- Created `PersonService` and `TagService` traits with implementations for managing persons and tags.
- Introduced repositories for `Person`, `Tag`, `FaceRegion`, and `PersonShare` with PostgreSQL support.
- Updated authorization logic to include permissions for accessing and editing persons.
- Enhanced the schema to support new models and relationships.
- Implemented database migrations for new tables related to persons and tags.
- Added request and response structures for API interactions with persons and tags.
This commit is contained in:
2025-11-15 11:18:11 +01:00
parent 370d55f0b3
commit 4675285603
26 changed files with 1465 additions and 18 deletions

View File

@@ -3,7 +3,7 @@ use uuid::Uuid;
use crate::{
error::CoreResult,
models::{Album, AlbumPermission, Media, MediaMetadata, User}, schema::ListMediaOptions,
models::{Album, AlbumPermission, FaceRegion, Media, MediaMetadata, Person, PersonPermission, Tag, User}, schema::ListMediaOptions,
};
#[async_trait]
@@ -57,4 +57,54 @@ pub trait AlbumShareRepository: Send + Sync {
pub trait MediaMetadataRepository: Send + Sync {
async fn create_batch(&self, metadata: &[MediaMetadata]) -> CoreResult<()>;
async fn find_by_media_id(&self, media_id: Uuid) -> CoreResult<Vec<MediaMetadata>>;
}
#[async_trait]
pub trait TagRepository: Send + Sync {
async fn find_or_create_tags(&self, tag_names: &[String]) -> CoreResult<Vec<Tag>>;
async fn add_tags_to_media(&self, media_id: Uuid, tag_ids: &[Uuid]) -> CoreResult<()>;
async fn remove_tags_from_media(&self, media_id: Uuid, tag_ids: &[Uuid]) -> CoreResult<()>;
async fn list_tags_for_media(&self, media_id: Uuid) -> CoreResult<Vec<Tag>>;
async fn find_tag_by_name(&self, name: &str) -> CoreResult<Option<Tag>>;
}
#[async_trait]
pub trait PersonRepository: Send + Sync {
async fn create(&self, person: Person) -> CoreResult<()>;
async fn find_by_id(&self, id: Uuid) -> CoreResult<Option<Person>>;
async fn list_by_user(&self, user_id: Uuid) -> CoreResult<Vec<Person>>;
async fn update(&self, person: Person) -> CoreResult<()>;
async fn delete(&self, id: Uuid) -> CoreResult<()>;
}
#[async_trait]
pub trait FaceRegionRepository: Send + Sync {
async fn create_batch(&self, face_regions: &[FaceRegion]) -> CoreResult<()>;
async fn find_by_media_id(&self, media_id: Uuid) -> CoreResult<Vec<FaceRegion>>;
async fn find_by_id(&self, face_region_id: Uuid) -> CoreResult<Option<FaceRegion>>;
async fn update_person_id(&self, face_region_id: Uuid, person_id: Uuid) -> CoreResult<()>;
async fn delete(&self, face_region_id: Uuid) -> CoreResult<()>;
}
#[async_trait]
pub trait PersonShareRepository: Send + Sync {
async fn create_or_update_share(
&self,
person_id: Uuid,
user_id: Uuid,
permission: PersonPermission,
) -> CoreResult<()>;
async fn remove_share(&self, person_id: Uuid, user_id: Uuid) -> CoreResult<()>;
async fn get_user_permission(
&self,
person_id: Uuid,
user_id: Uuid,
) -> CoreResult<Option<PersonPermission>>;
async fn list_people_shared_with_user(
&self,
user_id: Uuid,
) -> CoreResult<Vec<(Person, PersonPermission)>>;
}