Skip to content

Commit

Permalink
refactor: [torrust#448]: extract authorization service
Browse files Browse the repository at this point in the history
  • Loading branch information
josecelano committed Mar 21, 2024
1 parent 9c78895 commit d7ea59e
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 35 deletions.
13 changes: 9 additions & 4 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use crate::services::torrent::{
DbCanonicalInfoHashGroupRepository, DbTorrentAnnounceUrlRepository, DbTorrentFileRepository, DbTorrentInfoRepository,
DbTorrentListingGenerator, DbTorrentRepository, DbTorrentTagRepository,
};
use crate::services::user::{self, DbBannedUserList, DbUserProfileRepository, DbUserRepository};
use crate::services::{proxy, settings, torrent};
use crate::services::user::{self, DbBannedUserList, DbUserProfileRepository, DbUserRepository, Repository};
use crate::services::{authorization, proxy, settings, torrent};
use crate::tracker::statistics_importer::StatisticsImporter;
use crate::web::api::server::v1::auth::Authentication;
use crate::web::api::Version;
Expand Down Expand Up @@ -70,7 +70,7 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running
// Repositories
let category_repository = Arc::new(DbCategoryRepository::new(database.clone()));
let tag_repository = Arc::new(DbTagRepository::new(database.clone()));
let user_repository = Arc::new(DbUserRepository::new(database.clone()));
let user_repository: Arc<Box<dyn Repository>> = Arc::new(Box::new(DbUserRepository::new(database.clone())));
let user_authentication_repository = Arc::new(DbUserAuthenticationRepository::new(database.clone()));
let user_profile_repository = Arc::new(DbUserProfileRepository::new(database.clone()));
let torrent_repository = Arc::new(DbTorrentRepository::new(database.clone()));
Expand All @@ -83,12 +83,17 @@ 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(authorization::Service::new(user_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<ImageCacheService> = Arc::new(ImageCacheService::new(configuration.clone()).await);
let category_service = Arc::new(category::Service::new(category_repository.clone(), user_repository.clone()));
let category_service = Arc::new(category::Service::new(
category_repository.clone(),
user_repository.clone(),
authorization_service.clone(),
));
let tag_service = Arc::new(tag::Service::new(tag_repository.clone(), user_repository.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()));
Expand Down
7 changes: 4 additions & 3 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ use crate::services::torrent::{
DbCanonicalInfoHashGroupRepository, DbTorrentAnnounceUrlRepository, DbTorrentFileRepository, DbTorrentInfoRepository,
DbTorrentListingGenerator, DbTorrentRepository, DbTorrentTagRepository,
};
use crate::services::user::{self, DbBannedUserList, DbUserProfileRepository, DbUserRepository};
use crate::services::user::{self, DbBannedUserList, DbUserProfileRepository, Repository};
use crate::services::{proxy, settings, torrent};
use crate::tracker::statistics_importer::StatisticsImporter;
use crate::web::api::server::v1::auth::Authentication;
use crate::{mailer, tracker};

pub type Username = String;

pub struct AppData {
Expand All @@ -30,7 +31,7 @@ pub struct AppData {
// Repositories
pub category_repository: Arc<DbCategoryRepository>,
pub tag_repository: Arc<DbTagRepository>,
pub user_repository: Arc<DbUserRepository>,
pub user_repository: Arc<Box<dyn Repository>>,
pub user_authentication_repository: Arc<DbUserAuthenticationRepository>,
pub user_profile_repository: Arc<DbUserProfileRepository>,
pub torrent_repository: Arc<DbTorrentRepository>,
Expand Down Expand Up @@ -66,7 +67,7 @@ impl AppData {
// Repositories
category_repository: Arc<DbCategoryRepository>,
tag_repository: Arc<DbTagRepository>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
user_authentication_repository: Arc<DbUserAuthenticationRepository>,
user_profile_repository: Arc<DbUserProfileRepository>,
torrent_repository: Arc<DbTorrentRepository>,
Expand Down
7 changes: 4 additions & 3 deletions src/services/authentication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ use argon2::{Argon2, PasswordHash, PasswordVerifier};
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
use pbkdf2::Pbkdf2;

use super::user::{DbUserProfileRepository, DbUserRepository};
use super::user::DbUserProfileRepository;
use crate::config::Configuration;
use crate::databases::database::{Database, Error};
use crate::errors::ServiceError;
use crate::models::user::{UserAuthentication, UserClaims, UserCompact, UserId};
use crate::services::user::Repository;
use crate::utils::clock;

pub struct Service {
configuration: Arc<Configuration>,
json_web_token: Arc<JsonWebToken>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
user_profile_repository: Arc<DbUserProfileRepository>,
user_authentication_repository: Arc<DbUserAuthenticationRepository>,
}
Expand All @@ -24,7 +25,7 @@ impl Service {
pub fn new(
configuration: Arc<Configuration>,
json_web_token: Arc<JsonWebToken>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
user_profile_repository: Arc<DbUserProfileRepository>,
user_authentication_repository: Arc<DbUserAuthenticationRepository>,
) -> Self {
Expand Down
52 changes: 52 additions & 0 deletions src/services/authorization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! Authorization service.
use std::sync::Arc;

use super::user::Repository;
use crate::errors::ServiceError;
use crate::models::user::{UserCompact, UserId};

pub enum ACTION {
AddCategory,
DeleteCategory,
}

pub struct Service {
user_repository: Arc<Box<dyn Repository>>,
}

impl Service {
#[must_use]
pub fn new(user_repository: Arc<Box<dyn Repository>>) -> Self {
Self { user_repository }
}

/// # Errors
///
/// Will return an error if:
///
/// - There is not any user with the provided `UserId` (when the user id is some).
/// - The user is not authorized to perform the action.
pub async fn authorize(&self, action: ACTION, maybe_user_id: Option<UserId>) -> Result<(), ServiceError> {
match action {
ACTION::AddCategory | ACTION::DeleteCategory => match maybe_user_id {
Some(user_id) => {
let user = self.get_user(user_id).await?;

if !user.administrator {
return Err(ServiceError::Unauthorized);
}

Ok(())
}
None => Err(ServiceError::Unauthorized),
},
}
}

async fn get_user(&self, user_id: UserId) -> Result<UserCompact, ServiceError> {
self.user_repository.get_compact(&user_id).await
}
}

#[cfg(test)]
mod tests {}
21 changes: 16 additions & 5 deletions src/services/category.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
//! Category service.
use std::sync::Arc;

use super::user::DbUserRepository;
use super::authorization::{self, ACTION};
use crate::databases::database::{Category, Database, Error as DatabaseError};
use crate::errors::ServiceError;
use crate::models::category::CategoryId;
use crate::models::user::UserId;
use crate::services::user::Repository;

pub struct Service {
category_repository: Arc<DbCategoryRepository>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
authorization_service: Arc<authorization::Service>,
}

impl Service {
#[must_use]
pub fn new(category_repository: Arc<DbCategoryRepository>, user_repository: Arc<DbUserRepository>) -> Service {
pub fn new(
category_repository: Arc<DbCategoryRepository>,
user_repository: Arc<Box<dyn Repository>>,
authorization_service: Arc<authorization::Service>,
) -> Service {
Service {
category_repository,
user_repository,
authorization_service,
}
}

Expand All @@ -32,13 +39,17 @@ impl Service {
/// * The category already exists.
/// * 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_id).await?;
/*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(ACTION::AddCategory, Some(*user_id))
.await?;

let trimmed_name = category_name.trim();

Expand Down
1 change: 1 addition & 0 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! App services.
pub mod about;
pub mod authentication;
pub mod authorization;
pub mod category;
pub mod hasher;
pub mod proxy;
Expand Down
6 changes: 3 additions & 3 deletions src/services/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ use std::sync::Arc;

use bytes::Bytes;

use super::user::DbUserRepository;
use crate::cache::image::manager::{Error, ImageCacheService};
use crate::models::user::UserId;
use crate::services::user::Repository;

pub struct Service {
image_cache_service: Arc<ImageCacheService>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
}

impl Service {
#[must_use]
pub fn new(image_cache_service: Arc<ImageCacheService>, user_repository: Arc<DbUserRepository>) -> Self {
pub fn new(image_cache_service: Arc<ImageCacheService>, user_repository: Arc<Box<dyn Repository>>) -> Self {
Self {
image_cache_service,
user_repository,
Expand Down
6 changes: 3 additions & 3 deletions src/services/settings.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
//! Settings service.
use std::sync::Arc;

use super::user::DbUserRepository;
use crate::config::{Configuration, ConfigurationPublic, TorrustIndex};
use crate::errors::ServiceError;
use crate::models::user::UserId;
use crate::services::user::Repository;

pub struct Service {
configuration: Arc<Configuration>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
}

impl Service {
#[must_use]
pub fn new(configuration: Arc<Configuration>, user_repository: Arc<DbUserRepository>) -> Service {
pub fn new(configuration: Arc<Configuration>, user_repository: Arc<Box<dyn Repository>>) -> Service {
Service {
configuration,
user_repository,
Expand Down
6 changes: 3 additions & 3 deletions src/services/tag.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
//! Tag service.
use std::sync::Arc;

use super::user::DbUserRepository;
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;
use crate::services::user::Repository;

pub struct Service {
tag_repository: Arc<DbTagRepository>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
}

impl Service {
#[must_use]
pub fn new(tag_repository: Arc<DbTagRepository>, user_repository: Arc<DbUserRepository>) -> Service {
pub fn new(tag_repository: Arc<DbTagRepository>, user_repository: Arc<Box<dyn Repository>>) -> Service {
Service {
tag_repository,
user_repository,
Expand Down
6 changes: 3 additions & 3 deletions src/services/torrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use log::debug;
use serde_derive::{Deserialize, Serialize};

use super::category::DbCategoryRepository;
use super::user::DbUserRepository;
use crate::config::{Configuration, TrackerMode};
use crate::databases::database::{Database, Error, Sorting};
use crate::errors::ServiceError;
Expand All @@ -16,6 +15,7 @@ use crate::models::torrent::{Metadata, TorrentId, TorrentListing};
use crate::models::torrent_file::{DbTorrent, Torrent, TorrentFile};
use crate::models::torrent_tag::{TagId, TorrentTag};
use crate::models::user::UserId;
use crate::services::user::Repository;
use crate::tracker::statistics_importer::StatisticsImporter;
use crate::utils::parse_torrent::decode_and_validate_torrent_file;
use crate::{tracker, AsCSV};
Expand All @@ -24,7 +24,7 @@ pub struct Index {
configuration: Arc<Configuration>,
tracker_statistics_importer: Arc<StatisticsImporter>,
tracker_service: Arc<tracker::service::Service>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
category_repository: Arc<DbCategoryRepository>,
torrent_repository: Arc<DbTorrentRepository>,
torrent_info_hash_repository: Arc<DbCanonicalInfoHashGroupRepository>,
Expand Down Expand Up @@ -80,7 +80,7 @@ impl Index {
configuration: Arc<Configuration>,
tracker_statistics_importer: Arc<StatisticsImporter>,
tracker_service: Arc<tracker::service::Service>,
user_repository: Arc<DbUserRepository>,
user_repository: Arc<Box<dyn Repository>>,
category_repository: Arc<DbCategoryRepository>,
torrent_repository: Arc<DbTorrentRepository>,
torrent_info_hash_repository: Arc<DbCanonicalInfoHashGroupRepository>,
Expand Down
Loading

0 comments on commit d7ea59e

Please sign in to comment.