feat: Add public album routes and enhance authorization checks for media and albums
This commit is contained in:
@@ -15,7 +15,6 @@ pub struct DatabaseConfig {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ThumbnailFormat {
|
||||
@@ -53,8 +52,12 @@ pub struct Config {
|
||||
pub thumbnail_config: Option<ThumbnailConfig>,
|
||||
}
|
||||
|
||||
fn default_max_upload_size() -> u32 { 100 }
|
||||
fn default_storage_quota() -> u64 { 10 }
|
||||
fn default_max_upload_size() -> u32 {
|
||||
100
|
||||
}
|
||||
fn default_storage_quota() -> u64 {
|
||||
10
|
||||
}
|
||||
fn default_allowed_sort_columns() -> Vec<String> {
|
||||
vec!["created_at".to_string(), "original_filename".to_string()]
|
||||
}
|
||||
@@ -78,20 +81,19 @@ pub fn load_config() -> CoreResult<AppConfig> {
|
||||
println!("Loaded config from {}", env_path.display());
|
||||
|
||||
let config = config::Config::builder()
|
||||
.add_source(config::Environment::default()
|
||||
.with_list_parse_key("allowed_sort_columns")
|
||||
.list_separator(",")
|
||||
.try_parsing(true)
|
||||
.separator("__")
|
||||
)
|
||||
.add_source(
|
||||
config::Environment::default()
|
||||
.with_list_parse_key("allowed_sort_columns")
|
||||
.list_separator(",")
|
||||
.try_parsing(true)
|
||||
.separator("__"),
|
||||
)
|
||||
.build()
|
||||
.map_err(|e| CoreError::Config(format!("Failed to build config: {}", e)))?;
|
||||
|
||||
|
||||
let config: Config = config
|
||||
.try_deserialize()
|
||||
.map_err(|e| CoreError::Config(format!("Failed to deserialize config: {}", e)))?;
|
||||
println!("Built config from environment variables. Contents: {:?}", config);
|
||||
|
||||
|
||||
Ok(AppConfig {
|
||||
database: DatabaseConfig {
|
||||
@@ -107,4 +109,4 @@ pub fn load_config() -> CoreResult<AppConfig> {
|
||||
allowed_sort_columns: Some(config.allowed_sort_columns),
|
||||
thumbnail_config: config.thumbnail_config,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +149,11 @@ pub struct AlbumShare {
|
||||
pub permission: AlbumPermission,
|
||||
}
|
||||
|
||||
pub struct PublicAlbumBundle {
|
||||
pub album: Album,
|
||||
pub media: Vec<Media>,
|
||||
}
|
||||
|
||||
pub struct MediaBundle {
|
||||
pub media: Media,
|
||||
pub metadata: Vec<MediaMetadata>,
|
||||
|
||||
@@ -41,6 +41,8 @@ pub trait AlbumRepository: Send + Sync {
|
||||
async fn add_media_to_album(&self, album_id: Uuid, media_ids: &[Uuid]) -> CoreResult<()>;
|
||||
async fn update(&self, album: Album) -> CoreResult<()>;
|
||||
async fn delete(&self, id: Uuid) -> CoreResult<()>;
|
||||
async fn list_media_by_album_id(&self, album_id: Uuid) -> CoreResult<Vec<Media>>;
|
||||
async fn is_media_in_public_album(&self, media_id: Uuid) -> CoreResult<bool>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -2,17 +2,28 @@ use async_trait::async_trait;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
authz::Permission, error::CoreResult, models::{Album, FaceRegion, Media, MediaBundle, Person, PersonPermission, Tag, User}, schema::{
|
||||
AddMediaToAlbumData, CreateAlbumData, CreateUserData, ListMediaOptions, LoginUserData, ShareAlbumData, UpdateAlbumData, UploadMediaData
|
||||
}
|
||||
authz::Permission,
|
||||
error::CoreResult,
|
||||
models::{
|
||||
Album, FaceRegion, Media, MediaBundle, Person, PersonPermission, PublicAlbumBundle, Tag,
|
||||
User,
|
||||
},
|
||||
schema::{
|
||||
AddMediaToAlbumData, CreateAlbumData, CreateUserData, ListMediaOptions, LoginUserData,
|
||||
ShareAlbumData, UpdateAlbumData, UploadMediaData,
|
||||
},
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
pub trait MediaService: Send + Sync {
|
||||
async fn upload_media(&self, data: UploadMediaData<'_>) -> CoreResult<Media>;
|
||||
async fn get_media_details(&self, id: Uuid, user_id: Uuid) -> CoreResult<MediaBundle>;
|
||||
async fn list_user_media(&self, user_id: Uuid, options: ListMediaOptions) -> CoreResult<Vec<Media>>;
|
||||
async fn get_media_filepath(&self, id: Uuid, user_id: Uuid) -> CoreResult<String>;
|
||||
async fn get_media_details(&self, id: Uuid, user_id: Option<Uuid>) -> CoreResult<MediaBundle>;
|
||||
async fn list_user_media(
|
||||
&self,
|
||||
user_id: Uuid,
|
||||
options: ListMediaOptions,
|
||||
) -> CoreResult<Vec<Media>>;
|
||||
async fn get_media_filepath(&self, id: Uuid, user_id: Option<Uuid>) -> CoreResult<String>;
|
||||
async fn delete_media(&self, id: Uuid, user_id: Uuid) -> CoreResult<()>;
|
||||
}
|
||||
|
||||
@@ -37,12 +48,23 @@ pub trait AlbumService: Send + Sync {
|
||||
data: UpdateAlbumData<'_>,
|
||||
) -> CoreResult<Album>;
|
||||
async fn delete_album(&self, album_id: Uuid, user_id: Uuid) -> CoreResult<()>;
|
||||
async fn get_public_album_bundle(&self, album_id: Uuid) -> CoreResult<PublicAlbumBundle>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait TagService: Send + Sync {
|
||||
async fn add_tags_to_media(&self, media_id: Uuid, tag_names: &[String], user_id: Uuid) -> CoreResult<Vec<Tag>>;
|
||||
async fn remove_tags_from_media(&self, media_id: Uuid, tag_names: &[String], user_id: Uuid) -> CoreResult<()>;
|
||||
async fn add_tags_to_media(
|
||||
&self,
|
||||
media_id: Uuid,
|
||||
tag_names: &[String],
|
||||
user_id: Uuid,
|
||||
) -> CoreResult<Vec<Tag>>;
|
||||
async fn remove_tags_from_media(
|
||||
&self,
|
||||
media_id: Uuid,
|
||||
tag_names: &[String],
|
||||
user_id: Uuid,
|
||||
) -> CoreResult<()>;
|
||||
async fn list_tags_for_media(&self, media_id: Uuid, user_id: Uuid) -> CoreResult<Vec<Tag>>;
|
||||
}
|
||||
|
||||
@@ -51,22 +73,22 @@ pub trait PersonService: Send + Sync {
|
||||
async fn create_person(&self, name: &str, owner_id: Uuid) -> CoreResult<Person>;
|
||||
async fn get_person(&self, person_id: Uuid, user_id: Uuid) -> CoreResult<Person>;
|
||||
async fn list_people(&self, user_id: Uuid) -> CoreResult<Vec<Person>>;
|
||||
async fn update_person(
|
||||
&self,
|
||||
person_id: Uuid,
|
||||
name: &str,
|
||||
user_id: Uuid,
|
||||
) -> CoreResult<Person>;
|
||||
async fn update_person(&self, person_id: Uuid, name: &str, user_id: Uuid)
|
||||
-> CoreResult<Person>;
|
||||
async fn delete_person(&self, person_id: Uuid, user_id: Uuid) -> CoreResult<()>;
|
||||
|
||||
|
||||
async fn assign_face_to_person(
|
||||
&self,
|
||||
face_region_id: Uuid,
|
||||
person_id: Uuid,
|
||||
user_id: Uuid,
|
||||
) -> CoreResult<FaceRegion>;
|
||||
|
||||
async fn list_faces_for_media(&self, media_id: Uuid, user_id: Uuid) -> CoreResult<Vec<FaceRegion>>;
|
||||
|
||||
async fn list_faces_for_media(
|
||||
&self,
|
||||
media_id: Uuid,
|
||||
user_id: Uuid,
|
||||
) -> CoreResult<Vec<FaceRegion>>;
|
||||
|
||||
async fn share_person(
|
||||
&self,
|
||||
@@ -86,5 +108,9 @@ pub trait PersonService: Send + Sync {
|
||||
|
||||
#[async_trait]
|
||||
pub trait AuthorizationService: Send + Sync {
|
||||
async fn check_permission(&self, user_id: Uuid, permission: Permission) -> CoreResult<()>;
|
||||
}
|
||||
async fn check_permission(
|
||||
&self,
|
||||
user_id: Option<Uuid>,
|
||||
permission: Permission,
|
||||
) -> CoreResult<()>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user