Implement authorization service and refactor services to use it

- Added `AuthorizationService` and its implementation `AuthorizationServiceImpl` to handle permission checks across various services.
- Refactored `AlbumServiceImpl`, `MediaServiceImpl`, `PersonServiceImpl`, and `TagServiceImpl` to utilize the new authorization service for permission checks.
- Removed direct permission checks from services and replaced them with calls to the `AuthorizationService`.
- Updated repository interfaces to include new methods for checking media permissions in shared albums.
- Enhanced the `authz` module with new permission types for better granularity in access control.
- Adjusted the `AppState` struct to include the new `authorization_service`.
This commit is contained in:
2025-11-15 14:01:39 +01:00
parent ac8d16ba59
commit 8d05bdfd63
12 changed files with 547 additions and 292 deletions

View File

@@ -2,6 +2,34 @@ use uuid::Uuid;
use crate::models::{Album, AlbumPermission, Media, Person, PersonPermission, Role, User};
pub enum Permission {
// Media
ViewMedia(Uuid),
EditMedia(Uuid),
AddTags(Uuid),
RemoveTags(Uuid),
EditTags(Uuid),
DeleteMedia(Uuid),
// Albums
ViewAlbum(Uuid),
AddToAlbum(Uuid),
EditAlbum(Uuid),
ShareAlbum(Uuid),
DeleteAlbum(Uuid),
// People
ViewPerson(Uuid),
EditPerson(Uuid),
UsePerson(Uuid),
SharePerson(Uuid),
DeletePerson(Uuid),
// Faces
ViewFaces(Uuid),
AssignFace(Uuid),
}
pub trait Ownable {
fn owner_id(&self) -> Uuid;
}
@@ -48,10 +76,18 @@ pub fn can_contribute_to_album(
is_owner(user_id, album) || share_permission == Some(AlbumPermission::Contribute)
}
pub fn can_access_person(user_id: Uuid, person: &Person, share_permission: Option<PersonPermission>) -> bool {
pub fn can_access_person(
user_id: Uuid,
person: &Person,
share_permission: Option<PersonPermission>,
) -> bool {
is_owner(user_id, person) || share_permission.is_some()
}
pub fn can_edit_person(user_id: Uuid, person: &Person, share_permission: Option<PersonPermission>) -> bool {
pub fn can_use_person(
user_id: Uuid,
person: &Person,
share_permission: Option<PersonPermission>,
) -> bool {
is_owner(user_id, person) || share_permission == Some(PersonPermission::CanUse)
}
}

View File

@@ -3,7 +3,11 @@ use uuid::Uuid;
use crate::{
error::CoreResult,
models::{Album, AlbumPermission, FaceRegion, Media, MediaMetadata, Person, PersonPermission, Tag, User}, schema::ListMediaOptions,
models::{
Album, AlbumPermission, FaceRegion, Media, MediaMetadata, Person, PersonPermission, Tag,
User,
},
schema::ListMediaOptions,
};
#[async_trait]
@@ -11,7 +15,11 @@ pub trait MediaRepository: Send + Sync {
async fn find_by_hash(&self, hash: &str) -> CoreResult<Option<Media>>;
async fn create(&self, media: &Media) -> CoreResult<()>;
async fn find_by_id(&self, id: Uuid) -> CoreResult<Option<Media>>;
async fn list_by_user(&self, user_id: Uuid, options: &ListMediaOptions) -> CoreResult<Vec<Media>>;
async fn list_by_user(
&self,
user_id: Uuid,
options: &ListMediaOptions,
) -> CoreResult<Vec<Media>>;
async fn update_thumbnail_path(&self, id: Uuid, thumbnail_path: String) -> CoreResult<()>;
async fn delete(&self, id: Uuid) -> CoreResult<()>;
}
@@ -51,6 +59,11 @@ pub trait AlbumShareRepository: Send + Sync {
) -> CoreResult<Option<AlbumPermission>>;
async fn is_media_in_shared_album(&self, media_id: Uuid, user_id: Uuid) -> CoreResult<bool>;
async fn is_media_in_contributable_album(
&self,
media_id: Uuid,
user_id: Uuid,
) -> CoreResult<bool>;
}
#[async_trait]
@@ -65,7 +78,7 @@ pub trait TagRepository: Send + Sync {
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 fn find_tag_by_name(&self, name: &str) -> CoreResult<Option<Tag>>;
}
#[async_trait]
@@ -107,4 +120,4 @@ pub trait PersonShareRepository: Send + Sync {
&self,
user_id: Uuid,
) -> CoreResult<Vec<(Person, PersonPermission)>>;
}
}

View File

@@ -2,11 +2,9 @@ use async_trait::async_trait;
use uuid::Uuid;
use crate::{
error::CoreResult,
models::{Album, FaceRegion, Media, MediaBundle, Person, PersonPermission, Tag, User},
schema::{
authz::Permission, error::CoreResult, models::{Album, FaceRegion, Media, MediaBundle, Person, PersonPermission, Tag, User}, schema::{
AddMediaToAlbumData, CreateAlbumData, CreateUserData, ListMediaOptions, LoginUserData, ShareAlbumData, UpdateAlbumData, UploadMediaData
},
}
};
#[async_trait]
@@ -84,4 +82,9 @@ pub trait PersonService: Send + Sync {
target_user_id: Uuid,
owner_id: Uuid,
) -> CoreResult<()>;
}
#[async_trait]
pub trait AuthorizationService: Send + Sync {
async fn check_permission(&self, user_id: Uuid, permission: Permission) -> CoreResult<()>;
}