Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release Version 3.0.0-beta #721

Merged
merged 13 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 157 additions & 118 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ license = "AGPL-3.0-only"
publish = true
repository = "https://github.com/torrust/torrust-tracker"
rust-version = "1.72"
version = "3.0.0-alpha.12"
version = "3.0.0-beta"

[profile.dev.package.sqlx-macros]
opt-level = 3
Expand Down Expand Up @@ -67,7 +67,7 @@ lettre = { version = "0", features = [
"tokio1-rustls-tls",
] }
log = "0"
mockall = "0.12.1"
mockall = "0.13.0"
pbkdf2 = { version = "0", features = ["simple"] }
pin-project-lite = "0.2"
rand = "0"
Expand All @@ -89,7 +89,7 @@ text-to-png = "0"
thiserror = "1"
tokio = { version = "1", features = ["fs", "io-util", "macros", "net", "rt-multi-thread", "signal", "sync", "time"] }
toml = "0"
torrust-index-located-error = { version = "3.0.0-alpha.12", path = "packages/located-error" }
torrust-index-located-error = { version = "3.0.0-beta", path = "packages/located-error" }
tower = { version = "0.4", features = ["timeout"] }
tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] }
trace = "0.1.7"
Expand Down
4 changes: 4 additions & 0 deletions src/services/authorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub enum ACTION {
GetSettings,
GetSettingsSecret,
GetPublicSettings,
GetSiteName,
AddTag,
DeleteTag,
GetTags,
Expand Down Expand Up @@ -236,6 +237,7 @@ impl Default for CasbinConfiguration {
admin, GetSettings
admin, GetSettingsSecret
admin, GetPublicSettings
admin, GetSiteName
admin, AddTag
admin, DeleteTag
admin, GetTags
Expand All @@ -252,6 +254,7 @@ impl Default for CasbinConfiguration {
registered, GetCategories
registered, GetImageByUrl
registered, GetPublicSettings
registered, GetSiteName
registered, GetTags
registered, AddTorrent
registered, GetTorrent
Expand All @@ -263,6 +266,7 @@ impl Default for CasbinConfiguration {
guest, GetLicensePage
guest, GetCategories
guest, GetPublicSettings
guest, GetSiteName
guest, GetTags
guest, GetTorrent
guest, GetTorrentInfo
Expand Down
8 changes: 5 additions & 3 deletions src/services/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ impl Service {
/// * The image URL is not an image.
/// * The image is too big.
/// * The user quota is met.
#[allow(clippy::missing_panics_doc)]
pub async fn get_image_by_url(&self, url: &str, maybe_user_id: Option<UserId>) -> Result<Bytes, Error> {
let Some(user_id) = maybe_user_id else {
return Err(Error::Unauthenticated);
};

self.authorization_service
.authorize(ACTION::GetImageByUrl, maybe_user_id)
.await
.map_err(|_| Error::Unauthenticated)?;

// The unwrap should never panic as if the maybe_user_id is none, an authorization error will be returned and handled at the method above
self.image_cache_service.get_image_by_url(url, maybe_user_id.unwrap()).await
self.image_cache_service.get_image_by_url(url, user_id).await
}
}
8 changes: 6 additions & 2 deletions src/services/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ impl Service {
/// # Errors
///
/// It returns an error if the user does not have the required permissions.
pub async fn get_site_name(&self) -> String {
self.configuration.get_site_name().await
pub async fn get_site_name(&self, maybe_user_id: Option<UserId>) -> Result<String, ServiceError> {
self.authorization_service
.authorize(ACTION::GetSiteName, maybe_user_id)
.await?;

Ok(self.configuration.get_site_name().await)
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/services/torrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ impl Index {
add_torrent_req: AddTorrentRequest,
maybe_user_id: Option<UserId>,
) -> Result<AddTorrentResponse, ServiceError> {
let Some(user_id) = maybe_user_id else {
return Err(ServiceError::UnauthorizedActionForGuests);
};

self.authorization_service
.authorize(ACTION::AddTorrent, maybe_user_id)
.await?;
Expand All @@ -149,7 +153,7 @@ impl Index {

let torrent_id = self
.torrent_repository
.add(&original_info_hash, &torrent, &metadata, maybe_user_id.unwrap())
.add(&original_info_hash, &torrent, &metadata, user_id)
.await?;

// Synchronous secondary tasks
Expand Down
21 changes: 12 additions & 9 deletions src/services/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,23 +227,26 @@ impl ProfileService {
/// * An error if unable to successfully hash the password.
/// * An error if unable to change the password in the database.
/// * An error if it is not possible to authorize the action
#[allow(clippy::missing_panics_doc)]
pub async fn change_password(
&self,
maybe_user_id: Option<UserId>,
change_password_form: &ChangePasswordForm,
) -> Result<(), ServiceError> {
let Some(user_id) = maybe_user_id else {
return Err(ServiceError::UnauthorizedActionForGuests);
};

self.authorization_service
.authorize(ACTION::ChangePassword, maybe_user_id)
.await?;

info!("changing user password for user ID: {}", maybe_user_id.unwrap());
info!("changing user password for user ID: {}", user_id);

let settings = self.configuration.settings.read().await;

let user_authentication = self
.user_authentication_repository
.get_user_authentication_from_id(&maybe_user_id.unwrap())
.get_user_authentication_from_id(&user_id)
.await?;

verify_password(change_password_form.current_password.as_bytes(), &user_authentication)?;
Expand All @@ -262,7 +265,7 @@ impl ProfileService {
let password_hash = hash_password(&change_password_form.password)?;

self.user_authentication_repository
.change_password(maybe_user_id.unwrap(), &password_hash)
.change_password(user_id, &password_hash)
.await?;

Ok(())
Expand Down Expand Up @@ -298,15 +301,15 @@ impl BanService {
/// * `ServiceError::InternalServerError` if unable get user from the request.
/// * An error if unable to get user profile from supplied username.
/// * An error if unable to set the ban of the user in the database.
#[allow(clippy::missing_panics_doc)]
pub async fn ban_user(&self, username_to_be_banned: &str, maybe_user_id: Option<UserId>) -> Result<(), ServiceError> {
debug!(
"user with ID {} banning username: {username_to_be_banned}",
maybe_user_id.unwrap()
);
let Some(user_id) = maybe_user_id else {
return Err(ServiceError::UnauthorizedActionForGuests);
};

self.authorization_service.authorize(ACTION::BanUser, maybe_user_id).await?;

debug!("user with ID {} banning username: {username_to_be_banned}", user_id);

let user_profile = self
.user_profile_repository
.get_user_profile_from_username(username_to_be_banned)
Expand Down
12 changes: 8 additions & 4 deletions src/web/api/server/v1/contexts/settings/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ pub async fn get_public_handler(

/// Get website name.
#[allow(clippy::unused_async)]
pub async fn get_site_name_handler(State(app_data): State<Arc<AppData>>) -> Response {
let site_name = app_data.settings_service.get_site_name().await;

Json(responses::OkResponseData { data: site_name }).into_response()
pub async fn get_site_name_handler(
State(app_data): State<Arc<AppData>>,
ExtractOptionalLoggedInUser(maybe_user_id): ExtractOptionalLoggedInUser,
) -> Response {
match app_data.settings_service.get_site_name(maybe_user_id).await {
Ok(site_name) => Json(responses::OkResponseData { data: site_name }).into_response(),
Err(error) => error.into_response(),
}
}
Loading