use std::sync::Arc;
use super::authorization::{self, ACTION};
use crate::databases::database::{Database, Error as DatabaseError, Error};
use crate::errors::ServiceError;
use crate::models::torrent_tag::{TagId, TorrentTag};
use crate::models::user::UserId;
pub struct Service {
tag_repository: Arc<DbTagRepository>,
authorization_service: Arc<authorization::Service>,
}
impl Service {
#[must_use]
pub fn new(tag_repository: Arc<DbTagRepository>, authorization_service: Arc<authorization::Service>) -> Service {
Service {
tag_repository,
authorization_service,
}
}
pub async fn add_tag(&self, tag_name: &str, maybe_user_id: Option<UserId>) -> Result<TagId, ServiceError> {
self.authorization_service.authorize(ACTION::AddTag, maybe_user_id).await?;
let trimmed_name = tag_name.trim();
if trimmed_name.is_empty() {
return Err(ServiceError::TagNameEmpty);
}
match self.tag_repository.add(trimmed_name).await {
Ok(id) => Ok(id),
Err(e) => match e {
DatabaseError::TagAlreadyExists => Err(ServiceError::TagAlreadyExists),
_ => Err(ServiceError::DatabaseError),
},
}
}
pub async fn delete_tag(&self, tag_id: &TagId, maybe_user_id: Option<UserId>) -> Result<(), ServiceError> {
self.authorization_service.authorize(ACTION::DeleteTag, maybe_user_id).await?;
match self.tag_repository.delete(tag_id).await {
Ok(()) => Ok(()),
Err(e) => match e {
DatabaseError::TagNotFound => Err(ServiceError::TagNotFound),
_ => Err(ServiceError::DatabaseError),
},
}
}
pub async fn get_tags(&self, maybe_user_id: Option<UserId>) -> Result<Vec<TorrentTag>, ServiceError> {
self.authorization_service.authorize(ACTION::GetTags, maybe_user_id).await?;
self.tag_repository.get_all().await.map_err(|_| ServiceError::DatabaseError)
}
}
pub struct DbTagRepository {
database: Arc<Box<dyn Database>>,
}
impl DbTagRepository {
#[must_use]
pub fn new(database: Arc<Box<dyn Database>>) -> Self {
Self { database }
}
pub async fn add(&self, tag_name: &str) -> Result<TagId, Error> {
self.database.insert_tag_and_get_id(tag_name).await
}
pub async fn get_all(&self) -> Result<Vec<TorrentTag>, Error> {
self.database.get_tags().await
}
pub async fn delete(&self, tag_id: &TagId) -> Result<(), Error> {
self.database.delete_tag(*tag_id).await
}
}