From 336908a498e707582b03c5835025a010280e79d2 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 18 Mar 2024 23:09:44 +0100 Subject: [PATCH] feat: [#448] authorization logic now done by the authorization service --- src/app.rs | 14 +++++++++++--- src/common.rs | 7 +++++++ src/services/category.rs | 24 ++++++------------------ src/services/settings.rs | 24 ++++++------------------ src/services/tag.rs | 24 ++++++------------------ 5 files changed, 36 insertions(+), 57 deletions(-) diff --git a/src/app.rs b/src/app.rs index 9cdd0523..d7ad62da 100644 --- a/src/app.rs +++ b/src/app.rs @@ -9,6 +9,7 @@ use crate::common::AppData; use crate::config::Configuration; use crate::databases::database; use crate::services::authentication::{DbUserAuthenticationRepository, JsonWebToken, Service}; +use crate::services::authorization::{AuthorizationService, DbUserAuthorizationRepository}; use crate::services::category::{self, DbCategoryRepository}; use crate::services::tag::{self, DbTagRepository}; use crate::services::torrent::{ @@ -72,6 +73,7 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running let tag_repository = Arc::new(DbTagRepository::new(database.clone())); let user_repository = Arc::new(DbUserRepository::new(database.clone())); let user_authentication_repository = Arc::new(DbUserAuthenticationRepository::new(database.clone())); + let user_authorization_repository = Arc::new(DbUserAuthorizationRepository::new(database.clone())); let user_profile_repository = Arc::new(DbUserProfileRepository::new(database.clone())); let torrent_repository = Arc::new(DbTorrentRepository::new(database.clone())); let canonical_info_hash_group_repository = Arc::new(DbCanonicalInfoHashGroupRepository::new(database.clone())); @@ -83,15 +85,19 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running let banned_user_list = Arc::new(DbBannedUserList::new(database.clone())); // Services + let authorization_service = Arc::new(AuthorizationService::new(user_authorization_repository.clone())); let tracker_service = Arc::new(tracker::service::Service::new(configuration.clone(), database.clone()).await); let tracker_statistics_importer = Arc::new(StatisticsImporter::new(configuration.clone(), tracker_service.clone(), database.clone()).await); let mailer_service = Arc::new(mailer::Service::new(configuration.clone()).await); let image_cache_service: Arc = Arc::new(ImageCacheService::new(configuration.clone()).await); - let category_service = Arc::new(category::Service::new(category_repository.clone(), user_repository.clone())); - let tag_service = Arc::new(tag::Service::new(tag_repository.clone(), user_repository.clone())); + let category_service = Arc::new(category::Service::new( + category_repository.clone(), + authorization_service.clone(), + )); + let tag_service = Arc::new(tag::Service::new(tag_repository.clone(), authorization_service.clone())); let proxy_service = Arc::new(proxy::Service::new(image_cache_service.clone(), user_repository.clone())); - let settings_service = Arc::new(settings::Service::new(configuration.clone(), user_repository.clone())); + let settings_service = Arc::new(settings::Service::new(configuration.clone(), authorization_service.clone())); let torrent_index = Arc::new(torrent::Index::new( configuration.clone(), tracker_statistics_importer.clone(), @@ -133,6 +139,7 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running json_web_token.clone(), auth.clone(), authentication_service, + authorization_service, tracker_service.clone(), tracker_statistics_importer.clone(), mailer_service, @@ -141,6 +148,7 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running tag_repository, user_repository, user_authentication_repository, + user_authorization_repository, user_profile_repository, torrent_repository, canonical_info_hash_group_repository, diff --git a/src/common.rs b/src/common.rs index 755a775b..fa0763fa 100644 --- a/src/common.rs +++ b/src/common.rs @@ -4,6 +4,7 @@ use crate::cache::image::manager::ImageCacheService; use crate::config::Configuration; use crate::databases::database::Database; use crate::services::authentication::{DbUserAuthenticationRepository, JsonWebToken, Service}; +use crate::services::authorization::{AuthorizationService, DbUserAuthorizationRepository}; use crate::services::category::{self, DbCategoryRepository}; use crate::services::tag::{self, DbTagRepository}; use crate::services::torrent::{ @@ -23,6 +24,7 @@ pub struct AppData { pub json_web_token: Arc, pub auth: Arc, pub authentication_service: Arc, + pub authorization_service: Arc, pub tracker_service: Arc, pub tracker_statistics_importer: Arc, pub mailer: Arc, @@ -32,6 +34,7 @@ pub struct AppData { pub tag_repository: Arc, pub user_repository: Arc, pub user_authentication_repository: Arc, + pub user_authorization_repository: Arc, pub user_profile_repository: Arc, pub torrent_repository: Arc, pub torrent_info_hash_repository: Arc, @@ -59,6 +62,7 @@ impl AppData { json_web_token: Arc, auth: Arc, authentication_service: Arc, + authorization_service: Arc, tracker_service: Arc, tracker_statistics_importer: Arc, mailer: Arc, @@ -68,6 +72,7 @@ impl AppData { tag_repository: Arc, user_repository: Arc, user_authentication_repository: Arc, + user_authorization_repository: Arc, user_profile_repository: Arc, torrent_repository: Arc, torrent_info_hash_repository: Arc, @@ -92,6 +97,7 @@ impl AppData { json_web_token, auth, authentication_service, + authorization_service, tracker_service, tracker_statistics_importer, mailer, @@ -101,6 +107,7 @@ impl AppData { tag_repository, user_repository, user_authentication_repository, + user_authorization_repository, user_profile_repository, torrent_repository, torrent_info_hash_repository, diff --git a/src/services/category.rs b/src/services/category.rs index ec3e5ca2..db1ac4e8 100644 --- a/src/services/category.rs +++ b/src/services/category.rs @@ -1,7 +1,7 @@ //! Category service. use std::sync::Arc; -use super::user::DbUserRepository; +use super::authorization::AuthorizationService; use crate::databases::database::{Category, Database, Error as DatabaseError}; use crate::errors::ServiceError; use crate::models::category::CategoryId; @@ -9,15 +9,15 @@ use crate::models::user::UserId; pub struct Service { category_repository: Arc, - user_repository: Arc, + authorization_service: Arc, } impl Service { #[must_use] - pub fn new(category_repository: Arc, user_repository: Arc) -> Service { + pub fn new(category_repository: Arc, authorization_service: Arc) -> Service { Service { category_repository, - user_repository, + authorization_service, } } @@ -32,13 +32,7 @@ impl Service { /// * The category already exists. /// * There is a database error. pub async fn add_category(&self, category_name: &str, user_id: &UserId) -> Result { - let user = self.user_repository.get_compact(user_id).await?; - - // Check if user is administrator - // todo: extract authorization service - if !user.administrator { - return Err(ServiceError::Unauthorized); - } + self.authorization_service.authorize_user(*user_id, true).await?; let trimmed_name = category_name.trim(); @@ -70,13 +64,7 @@ impl Service { /// * 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_id).await?; - - // Check if user is administrator - // todo: extract authorization service - if !user.administrator { - return Err(ServiceError::Unauthorized); - } + self.authorization_service.authorize_user(*user_id, true).await?; match self.category_repository.delete(category_name).await { Ok(()) => Ok(()), diff --git a/src/services/settings.rs b/src/services/settings.rs index 1693df73..61b07443 100644 --- a/src/services/settings.rs +++ b/src/services/settings.rs @@ -1,22 +1,22 @@ //! Settings service. use std::sync::Arc; -use super::user::DbUserRepository; +use super::authorization::AuthorizationService; use crate::config::{Configuration, ConfigurationPublic, TorrustIndex}; use crate::errors::ServiceError; use crate::models::user::UserId; pub struct Service { configuration: Arc, - user_repository: Arc, + authorization_service: Arc, } impl Service { #[must_use] - pub fn new(configuration: Arc, user_repository: Arc) -> Service { + pub fn new(configuration: Arc, authorization_service: Arc) -> Service { Service { configuration, - user_repository, + authorization_service, } } @@ -26,13 +26,7 @@ impl Service { /// /// It returns an error if the user does not have the required permissions. pub async fn get_all(&self, user_id: &UserId) -> Result { - let user = self.user_repository.get_compact(user_id).await?; - - // Check if user is administrator - // todo: extract authorization service - if !user.administrator { - return Err(ServiceError::Unauthorized); - } + self.authorization_service.authorize_user(*user_id, true).await?; let torrust_index_configuration = self.configuration.get_all().await; @@ -45,13 +39,7 @@ impl Service { /// /// It returns an error if the user does not have the required permissions. pub async fn get_all_masking_secrets(&self, user_id: &UserId) -> Result { - let user = self.user_repository.get_compact(user_id).await?; - - // Check if user is administrator - // todo: extract authorization service - if !user.administrator { - return Err(ServiceError::Unauthorized); - } + self.authorization_service.authorize_user(*user_id, true).await?; let mut torrust_index_configuration = self.configuration.get_all().await; diff --git a/src/services/tag.rs b/src/services/tag.rs index fcbf56c3..08916dd5 100644 --- a/src/services/tag.rs +++ b/src/services/tag.rs @@ -1,7 +1,7 @@ //! Tag service. use std::sync::Arc; -use super::user::DbUserRepository; +use super::authorization::AuthorizationService; use crate::databases::database::{Database, Error as DatabaseError, Error}; use crate::errors::ServiceError; use crate::models::torrent_tag::{TagId, TorrentTag}; @@ -9,15 +9,15 @@ use crate::models::user::UserId; pub struct Service { tag_repository: Arc, - user_repository: Arc, + authorization_service: Arc, } impl Service { #[must_use] - pub fn new(tag_repository: Arc, user_repository: Arc) -> Service { + pub fn new(tag_repository: Arc, authorization_service: Arc) -> Service { Service { tag_repository, - user_repository, + authorization_service, } } @@ -30,13 +30,7 @@ impl Service { /// * The user does not have the required permissions. /// * There is a database error. pub async fn add_tag(&self, tag_name: &str, user_id: &UserId) -> Result { - let user = self.user_repository.get_compact(user_id).await?; - - // Check if user is administrator - // todo: extract authorization service - if !user.administrator { - return Err(ServiceError::Unauthorized); - } + self.authorization_service.authorize_user(*user_id, true).await?; let trimmed_name = tag_name.trim(); @@ -62,13 +56,7 @@ impl Service { /// * The user does not have the required permissions. /// * There is a database error. pub async fn delete_tag(&self, tag_id: &TagId, user_id: &UserId) -> Result<(), ServiceError> { - let user = self.user_repository.get_compact(user_id).await?; - - // Check if user is administrator - // todo: extract authorization service - if !user.administrator { - return Err(ServiceError::Unauthorized); - } + self.authorization_service.authorize_user(*user_id, true).await?; match self.tag_repository.delete(tag_id).await { Ok(()) => Ok(()),