torrust_index/services/
category.rs1use std::sync::Arc;
3
4use super::authorization::{self, ACTION};
5use crate::databases::database::{Category, Database, Error as DatabaseError};
6use crate::errors::ServiceError;
7use crate::models::category::CategoryId;
8use crate::models::user::UserId;
9
10pub struct Service {
11 category_repository: Arc<DbCategoryRepository>,
12 authorization_service: Arc<authorization::Service>,
13}
14
15impl Service {
16 #[must_use]
17 pub fn new(category_repository: Arc<DbCategoryRepository>, authorization_service: Arc<authorization::Service>) -> Service {
18 Service {
19 category_repository,
20 authorization_service,
21 }
22 }
23
24 pub async fn add_category(&self, category_name: &str, maybe_user_id: Option<UserId>) -> Result<i64, ServiceError> {
35 self.authorization_service
36 .authorize(ACTION::AddCategory, maybe_user_id)
37 .await?;
38
39 let trimmed_name = category_name.trim();
40
41 if trimmed_name.is_empty() {
42 return Err(ServiceError::CategoryNameEmpty);
43 }
44
45 match self.category_repository.get_by_name(trimmed_name).await {
47 Ok(_) => Err(ServiceError::CategoryAlreadyExists),
49 Err(e) => match e {
50 DatabaseError::CategoryNotFound => match self.category_repository.add(trimmed_name).await {
52 Ok(id) => Ok(id),
53 Err(_) => Err(ServiceError::DatabaseError),
54 },
55 _ => Err(ServiceError::DatabaseError),
56 },
57 }
58 }
59
60 pub async fn delete_category(&self, category_name: &str, maybe_user_id: Option<UserId>) -> Result<(), ServiceError> {
69 self.authorization_service
70 .authorize(ACTION::DeleteCategory, maybe_user_id)
71 .await?;
72
73 match self.category_repository.delete(category_name).await {
74 Ok(()) => Ok(()),
75 Err(e) => match e {
76 DatabaseError::CategoryNotFound => Err(ServiceError::CategoryNotFound),
77 _ => Err(ServiceError::DatabaseError),
78 },
79 }
80 }
81
82 pub async fn get_categories(&self, maybe_user_id: Option<UserId>) -> Result<Vec<Category>, ServiceError> {
91 self.authorization_service
92 .authorize(ACTION::GetCategories, maybe_user_id)
93 .await?;
94
95 self.category_repository
96 .get_all()
97 .await
98 .map_err(|_| ServiceError::DatabaseError)
99 }
100}
101
102pub struct DbCategoryRepository {
103 database: Arc<Box<dyn Database>>,
104}
105
106impl DbCategoryRepository {
107 #[must_use]
108 pub fn new(database: Arc<Box<dyn Database>>) -> Self {
109 Self { database }
110 }
111
112 pub async fn get_all(&self) -> Result<Vec<Category>, DatabaseError> {
118 self.database.get_categories().await
119 }
120
121 pub async fn add(&self, category_name: &str) -> Result<CategoryId, DatabaseError> {
127 self.database.insert_category_and_get_id(category_name).await
128 }
129
130 pub async fn delete(&self, category_name: &str) -> Result<(), DatabaseError> {
136 self.database.delete_category(category_name).await
137 }
138
139 pub async fn get_by_name(&self, category_name: &str) -> Result<Category, DatabaseError> {
145 self.database.get_category_from_name(category_name).await
146 }
147
148 pub async fn get_by_id(&self, category_id: &CategoryId) -> Result<Category, DatabaseError> {
154 self.database.get_category_from_id(*category_id).await
155 }
156}