forked from torrust/torrust-index
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: [torrust#157] extract service: category
Decoupling services from actix-web framework.
- Loading branch information
1 parent
baa4c7e
commit d58f3cc
Showing
11 changed files
with
203 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#[allow(clippy::module_name_repetitions)] | ||
pub type CategoryId = i64; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod category; | ||
pub mod info_hash; | ||
pub mod response; | ||
pub mod torrent; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
//! Category service. | ||
use std::sync::Arc; | ||
|
||
use super::user::DbUserRepository; | ||
use crate::databases::database::{Category, Database, Error as DatabaseError}; | ||
use crate::errors::ServiceError; | ||
use crate::models::category::CategoryId; | ||
use crate::models::user::UserId; | ||
|
||
pub struct Service { | ||
category_repository: Arc<DbCategoryRepository>, | ||
user_repository: Arc<DbUserRepository>, | ||
} | ||
|
||
impl Service { | ||
#[must_use] | ||
pub fn new(category_repository: Arc<DbCategoryRepository>, user_repository: Arc<DbUserRepository>) -> Service { | ||
Service { | ||
category_repository, | ||
user_repository, | ||
} | ||
} | ||
|
||
/// Adds a new category. | ||
/// | ||
/// # Errors | ||
/// | ||
/// It returns an error if: | ||
/// | ||
/// * The user does not have the required permissions. | ||
/// * There is a database error. | ||
pub async fn add_category(&self, category_name: &str, user_id: &UserId) -> Result<i64, ServiceError> { | ||
let user = self.user_repository.get_compact_user(user_id).await?; | ||
|
||
// Check if user is administrator | ||
// todo: extract authorization service | ||
if !user.administrator { | ||
return Err(ServiceError::Unauthorized); | ||
} | ||
|
||
match self.category_repository.add_category(category_name).await { | ||
Ok(id) => Ok(id), | ||
Err(e) => match e { | ||
DatabaseError::CategoryAlreadyExists => Err(ServiceError::CategoryExists), | ||
_ => Err(ServiceError::DatabaseError), | ||
}, | ||
} | ||
} | ||
|
||
/// Deletes a new category. | ||
/// | ||
/// # Errors | ||
/// | ||
/// It returns an error if: | ||
/// | ||
/// * The user does not have the required permissions. | ||
/// * There is a database error. | ||
pub async fn delete_category(&self, category_name: &str, user_id: &UserId) -> Result<(), ServiceError> { | ||
let user = self.user_repository.get_compact_user(user_id).await?; | ||
|
||
// Check if user is administrator | ||
// todo: extract authorization service | ||
if !user.administrator { | ||
return Err(ServiceError::Unauthorized); | ||
} | ||
|
||
match self.category_repository.delete_category(category_name).await { | ||
Ok(_) => Ok(()), | ||
Err(e) => match e { | ||
DatabaseError::CategoryNotFound => Err(ServiceError::CategoryNotFound), | ||
_ => Err(ServiceError::DatabaseError), | ||
}, | ||
} | ||
} | ||
} | ||
|
||
pub struct DbCategoryRepository { | ||
database: Arc<Box<dyn Database>>, | ||
} | ||
|
||
impl DbCategoryRepository { | ||
#[must_use] | ||
pub fn new(database: Arc<Box<dyn Database>>) -> Self { | ||
Self { database } | ||
} | ||
|
||
/// It returns the categories. | ||
/// | ||
/// # Errors | ||
/// | ||
/// It returns an error if there is a database error. | ||
pub async fn get_categories(&self) -> Result<Vec<Category>, DatabaseError> { | ||
self.database.get_categories().await | ||
} | ||
|
||
/// Adds a new category. | ||
/// | ||
/// # Errors | ||
/// | ||
/// It returns an error if there is a database error. | ||
pub async fn add_category(&self, category_name: &str) -> Result<CategoryId, DatabaseError> { | ||
self.database.insert_category_and_get_id(category_name).await | ||
} | ||
|
||
/// Deletes a new category. | ||
/// | ||
/// # Errors | ||
/// | ||
/// It returns an error if there is a database error. | ||
pub async fn delete_category(&self, category_name: &str) -> Result<(), DatabaseError> { | ||
self.database.delete_category(category_name).await | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
pub mod about; | ||
pub mod category; | ||
pub mod user; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
//! User repository. | ||
use std::sync::Arc; | ||
|
||
use crate::databases::database::Database; | ||
use crate::errors::ServiceError; | ||
use crate::models::user::{UserCompact, UserId}; | ||
|
||
pub struct DbUserRepository { | ||
database: Arc<Box<dyn Database>>, | ||
} | ||
|
||
impl DbUserRepository { | ||
#[must_use] | ||
pub fn new(database: Arc<Box<dyn Database>>) -> Self { | ||
Self { database } | ||
} | ||
|
||
/// It returns the compact user. | ||
/// | ||
/// # Errors | ||
/// | ||
/// It returns an error if there is a database error. | ||
pub async fn get_compact_user(&self, user_id: &UserId) -> Result<UserCompact, ServiceError> { | ||
// todo: persistence layer should have its own errors instead of | ||
// returning a `ServiceError`. | ||
self.database | ||
.get_user_compact_from_id(*user_id) | ||
.await | ||
.map_err(|_| ServiceError::UserNotFound) | ||
} | ||
} |