From b86d5b7fdb9b9fb07ae99ba3790366e3270bafbc Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Wed, 13 Nov 2024 12:52:00 +0100 Subject: [PATCH 01/12] Updated changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f27c81f0..e4ea443b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [648](https://github.com/thoth-pub/thoth/issues/648) - Added new `LocationPlatform`, `THOTH`, for Locations where file is hosted directly by Thoth on S3. +### Changed +- [648](https://github.com/thoth-pub/thoth/issues/650) - Allow only superusers to create/update/delete a `Location` when the `LocationPlatform` is `THOTH`. + ## [[0.12.14]](https://github.com/thoth-pub/thoth/releases/tag/v0.12.14) - 2024-11-04 ### Changed - [642](https://github.com/thoth-pub/thoth/issues/642) - Output `ProductAvailability` based on work status in Thoth ONIX 3.0 From 3b57ec72157f00b64c6300d01d9b98395503de84 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Wed, 13 Nov 2024 13:53:05 +0100 Subject: [PATCH 02/12] Created new Thoth Error, ThothLocationError, and added error message to create_location, update_location, delete_location in model.rs --- thoth-api/src/graphql/model.rs | 12 ++++++++++++ thoth-errors/src/lib.rs | 2 ++ 2 files changed, 14 insertions(+) diff --git a/thoth-api/src/graphql/model.rs b/thoth-api/src/graphql/model.rs index 830cb905..253b7f1f 100644 --- a/thoth-api/src/graphql/model.rs +++ b/thoth-api/src/graphql/model.rs @@ -1615,6 +1615,10 @@ impl MutationRoot { #[graphql(description = "Values for location to be created")] data: NewLocation, ) -> FieldResult { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; + // Only superusers can create new locations where Location Platform is Thoth + if !context.account_access.is_superuser && data.location_platform == LocationPlatform::Thoth { + return Err(ThothError::ThothLocationError.into()); + } context .account_access .can_edit(publisher_id_from_publication_id( @@ -1971,6 +1975,10 @@ impl MutationRoot { ) -> FieldResult { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; let location = Location::from_id(&context.db, &data.location_id).unwrap(); + // Only superusers can edit locations where Location Platform is Thoth + if !context.account_access.is_superuser && location.location_platform == LocationPlatform::Thoth { + return Err(ThothError::ThothLocationError.into()); + } context .account_access .can_edit(location.publisher_id(&context.db)?)?; @@ -2294,6 +2302,10 @@ impl MutationRoot { ) -> FieldResult { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; let location = Location::from_id(&context.db, &location_id).unwrap(); + // Only superusers can delete locations where Location Platform is Thoth + if !context.account_access.is_superuser && location.location_platform == LocationPlatform::Thoth { + return Err(ThothError::ThothLocationError.into()); + } context .account_access .can_edit(location.publisher_id(&context.db)?)?; diff --git a/thoth-errors/src/lib.rs b/thoth-errors/src/lib.rs index c5e25123..9244de18 100644 --- a/thoth-errors/src/lib.rs +++ b/thoth-errors/src/lib.rs @@ -97,6 +97,8 @@ pub enum ThothError { WithdrawnDateError, #[error("A Superseded or Withdrawn Work must have a Withdrawn Date.")] NoWithdrawnDateError, + #[error("Only superusers can create, edit, or delete Locations where the Location Platform is Thoth.")] + ThothLocationError, } #[cfg(not(target_arch = "wasm32"))] From 720d9159c8302c97e4ee1349394284573108a23e Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Wed, 13 Nov 2024 17:00:22 +0100 Subject: [PATCH 03/12] Disable delete and edit buttons in view for Thoth location for non-superuser --- thoth-app/src/component/locations_form.rs | 16 +++++++++++++++- thoth-app/src/component/publication.rs | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/thoth-app/src/component/locations_form.rs b/thoth-app/src/component/locations_form.rs index 671fcaed..f3c22cfd 100644 --- a/thoth-app/src/component/locations_form.rs +++ b/thoth-app/src/component/locations_form.rs @@ -1,4 +1,5 @@ use std::str::FromStr; +use thoth_api::account::model::AccountDetails; use thoth_api::model::location::Location; use thoth_api::model::location::LocationPlatform; use thoth_errors::ThothError; @@ -84,6 +85,7 @@ pub struct Props { pub locations: Option>, pub publication_id: Uuid, pub update_locations: Callback<()>, + pub current_user: AccountDetails, } impl Component for LocationsFormComponent { @@ -462,12 +464,23 @@ impl LocationsFormComponent { ctx.link() .callback(move |_| Msg::DeleteLocation(location_id)), ); + let mut edit_callback = Some( + ctx.link() + .callback(move |_| Msg::ToggleModalFormDisplay(true, Some(location.clone()))) + ); let mut delete_deactivated = false; + let mut edit_deactivated = false; // If the location is canonical and other (non-canonical) locations exist, prevent it from // being deleted by deactivating the delete button and unsetting its callback attribute if l.canonical && ctx.props().locations.as_ref().unwrap_or(&vec![]).len() > 1 { delete_callback = None; delete_deactivated = true; + // Restrict deleting locations with Thoth as location platform to superusers + } else if ctx.props().current_user.resource_access.restricted_to().is_some() && l.location_platform == LocationPlatform::Thoth { + delete_callback = None; + delete_deactivated = true; + edit_callback = None; + edit_deactivated = true; } html! { @@ -510,7 +523,8 @@ impl LocationsFormComponent {
{ EDIT_BUTTON } diff --git a/thoth-app/src/component/publication.rs b/thoth-app/src/component/publication.rs index 5cbe20de..29fe26b0 100644 --- a/thoth-app/src/component/publication.rs +++ b/thoth-app/src/component/publication.rs @@ -416,6 +416,7 @@ impl Component for PublicationComponent { Date: Fri, 15 Nov 2024 10:37:57 +0100 Subject: [PATCH 04/12] remove Thoth from LocationPlatform enum for non-superusers --- thoth-app/src/component/locations_form.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/thoth-app/src/component/locations_form.rs b/thoth-app/src/component/locations_form.rs index f3c22cfd..0e18c619 100644 --- a/thoth-app/src/component/locations_form.rs +++ b/thoth-app/src/component/locations_form.rs @@ -147,8 +147,20 @@ impl Component for LocationsFormComponent { { FetchState::NotFetching(_) => vec![], FetchState::Fetching(_) => vec![], - FetchState::Fetched(body) => body.data.location_platforms.enum_values.clone(), + FetchState::Fetched(body) => { + // remove Thoth from LocationPlatform enum for non-superusers + if ctx.props().current_user.resource_access.restricted_to().is_some() { + body.data.location_platforms.enum_values + .clone() + .into_iter() + .filter(|platform| *platform != LocationPlatformValues { name: LocationPlatform::Thoth }) + .collect() + } else { + body.data.location_platforms.enum_values.clone() + } + } FetchState::Failed(_, _err) => vec![], + }; true } From 6b3ade7bcc3d366a0119788d3e0bdb21b8c7fac9 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Fri, 15 Nov 2024 10:59:37 +0100 Subject: [PATCH 05/12] Run cargo fmt --all to fix formatting errors --- thoth-api/src/graphql/model.rs | 11 +++++--- thoth-app/src/component/locations_form.rs | 31 ++++++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/thoth-api/src/graphql/model.rs b/thoth-api/src/graphql/model.rs index 253b7f1f..194da909 100644 --- a/thoth-api/src/graphql/model.rs +++ b/thoth-api/src/graphql/model.rs @@ -1616,7 +1616,8 @@ impl MutationRoot { ) -> FieldResult { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; // Only superusers can create new locations where Location Platform is Thoth - if !context.account_access.is_superuser && data.location_platform == LocationPlatform::Thoth { + if !context.account_access.is_superuser && data.location_platform == LocationPlatform::Thoth + { return Err(ThothError::ThothLocationError.into()); } context @@ -1976,7 +1977,9 @@ impl MutationRoot { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; let location = Location::from_id(&context.db, &data.location_id).unwrap(); // Only superusers can edit locations where Location Platform is Thoth - if !context.account_access.is_superuser && location.location_platform == LocationPlatform::Thoth { + if !context.account_access.is_superuser + && location.location_platform == LocationPlatform::Thoth + { return Err(ThothError::ThothLocationError.into()); } context @@ -2303,7 +2306,9 @@ impl MutationRoot { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; let location = Location::from_id(&context.db, &location_id).unwrap(); // Only superusers can delete locations where Location Platform is Thoth - if !context.account_access.is_superuser && location.location_platform == LocationPlatform::Thoth { + if !context.account_access.is_superuser + && location.location_platform == LocationPlatform::Thoth + { return Err(ThothError::ThothLocationError.into()); } context diff --git a/thoth-app/src/component/locations_form.rs b/thoth-app/src/component/locations_form.rs index 0e18c619..a231861e 100644 --- a/thoth-app/src/component/locations_form.rs +++ b/thoth-app/src/component/locations_form.rs @@ -149,18 +149,30 @@ impl Component for LocationsFormComponent { FetchState::Fetching(_) => vec![], FetchState::Fetched(body) => { // remove Thoth from LocationPlatform enum for non-superusers - if ctx.props().current_user.resource_access.restricted_to().is_some() { - body.data.location_platforms.enum_values + if ctx + .props() + .current_user + .resource_access + .restricted_to() + .is_some() + { + body.data + .location_platforms + .enum_values .clone() .into_iter() - .filter(|platform| *platform != LocationPlatformValues { name: LocationPlatform::Thoth }) + .filter(|platform| { + *platform + != LocationPlatformValues { + name: LocationPlatform::Thoth, + } + }) .collect() } else { body.data.location_platforms.enum_values.clone() } } FetchState::Failed(_, _err) => vec![], - }; true } @@ -478,7 +490,7 @@ impl LocationsFormComponent { ); let mut edit_callback = Some( ctx.link() - .callback(move |_| Msg::ToggleModalFormDisplay(true, Some(location.clone()))) + .callback(move |_| Msg::ToggleModalFormDisplay(true, Some(location.clone()))), ); let mut delete_deactivated = false; let mut edit_deactivated = false; @@ -488,7 +500,14 @@ impl LocationsFormComponent { delete_callback = None; delete_deactivated = true; // Restrict deleting locations with Thoth as location platform to superusers - } else if ctx.props().current_user.resource_access.restricted_to().is_some() && l.location_platform == LocationPlatform::Thoth { + } else if ctx + .props() + .current_user + .resource_access + .restricted_to() + .is_some() + && l.location_platform == LocationPlatform::Thoth + { delete_callback = None; delete_deactivated = true; edit_callback = None; From bdc4b52f3a54834e5583a8ace48e1fe7b1bfeb93 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Fri, 15 Nov 2024 11:04:13 +0100 Subject: [PATCH 06/12] Fix issue number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4ea443b..01357bff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- [648](https://github.com/thoth-pub/thoth/issues/648) - Added new `LocationPlatform`, `THOTH`, for Locations where file is hosted directly by Thoth on S3. +- [650](https://github.com/thoth-pub/thoth/issues/648) - Added new `LocationPlatform`, `THOTH`, for Locations where file is hosted directly by Thoth on S3. ### Changed - [648](https://github.com/thoth-pub/thoth/issues/650) - Allow only superusers to create/update/delete a `Location` when the `LocationPlatform` is `THOTH`. From 11caea356678447f15ce36b062bbdf17de12dd35 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Fri, 15 Nov 2024 11:05:36 +0100 Subject: [PATCH 07/12] Fix changelog issue numbers --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01357bff..9bc89c90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- [650](https://github.com/thoth-pub/thoth/issues/648) - Added new `LocationPlatform`, `THOTH`, for Locations where file is hosted directly by Thoth on S3. +- [648](https://github.com/thoth-pub/thoth/issues/648) - Added new `LocationPlatform`, `THOTH`, for Locations where file is hosted directly by Thoth on S3. ### Changed -- [648](https://github.com/thoth-pub/thoth/issues/650) - Allow only superusers to create/update/delete a `Location` when the `LocationPlatform` is `THOTH`. +- [650](https://github.com/thoth-pub/thoth/issues/650) - Allow only superusers to create/update/delete a `Location` when the `LocationPlatform` is `THOTH`. ## [[0.12.14]](https://github.com/thoth-pub/thoth/releases/tag/v0.12.14) - 2024-11-04 ### Changed From d878637b3c888678ad83d510c117dd2854b18ab8 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Tue, 19 Nov 2024 12:53:18 +0100 Subject: [PATCH 08/12] Fixed logic for disabling edit button on canonical locations, used is_superuser --- thoth-app/src/component/locations_form.rs | 41 ++++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/thoth-app/src/component/locations_form.rs b/thoth-app/src/component/locations_form.rs index a231861e..b0751f64 100644 --- a/thoth-app/src/component/locations_form.rs +++ b/thoth-app/src/component/locations_form.rs @@ -148,28 +148,27 @@ impl Component for LocationsFormComponent { FetchState::NotFetching(_) => vec![], FetchState::Fetching(_) => vec![], FetchState::Fetched(body) => { - // remove Thoth from LocationPlatform enum for non-superusers if ctx .props() .current_user .resource_access - .restricted_to() - .is_some() + .is_superuser { - body.data - .location_platforms - .enum_values - .clone() - .into_iter() - .filter(|platform| { - *platform - != LocationPlatformValues { - name: LocationPlatform::Thoth, - } - }) - .collect() - } else { body.data.location_platforms.enum_values.clone() + // remove Thoth from LocationPlatform enum for non-superusers + } else { + body.data + .location_platforms + .enum_values + .clone() + .into_iter() + .filter(|platform| { + *platform + != LocationPlatformValues { + name: LocationPlatform::Thoth, + } + }) + .collect() } } FetchState::Failed(_, _err) => vec![], @@ -494,18 +493,20 @@ impl LocationsFormComponent { ); let mut delete_deactivated = false; let mut edit_deactivated = false; + // If the location is canonical and other (non-canonical) locations exist, prevent it from // being deleted by deactivating the delete button and unsetting its callback attribute if l.canonical && ctx.props().locations.as_ref().unwrap_or(&vec![]).len() > 1 { delete_callback = None; delete_deactivated = true; - // Restrict deleting locations with Thoth as location platform to superusers - } else if ctx + + } + // If not superuser, restrict deleting and editing locations with Thoth location platform + if !ctx .props() .current_user .resource_access - .restricted_to() - .is_some() + .is_superuser && l.location_platform == LocationPlatform::Thoth { delete_callback = None; From 39a19a078cccf75012345b1cc76fbbf46fda52b0 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Tue, 19 Nov 2024 12:55:48 +0100 Subject: [PATCH 09/12] Fix formatter errors --- thoth-app/src/component/locations_form.rs | 38 +++++++++-------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/thoth-app/src/component/locations_form.rs b/thoth-app/src/component/locations_form.rs index b0751f64..e9cf4315 100644 --- a/thoth-app/src/component/locations_form.rs +++ b/thoth-app/src/component/locations_form.rs @@ -148,27 +148,22 @@ impl Component for LocationsFormComponent { FetchState::NotFetching(_) => vec![], FetchState::Fetching(_) => vec![], FetchState::Fetched(body) => { - if ctx - .props() - .current_user - .resource_access - .is_superuser - { + if ctx.props().current_user.resource_access.is_superuser { body.data.location_platforms.enum_values.clone() // remove Thoth from LocationPlatform enum for non-superusers } else { body.data - .location_platforms - .enum_values - .clone() - .into_iter() - .filter(|platform| { - *platform - != LocationPlatformValues { - name: LocationPlatform::Thoth, - } - }) - .collect() + .location_platforms + .enum_values + .clone() + .into_iter() + .filter(|platform| { + *platform + != LocationPlatformValues { + name: LocationPlatform::Thoth, + } + }) + .collect() } } FetchState::Failed(_, _err) => vec![], @@ -499,14 +494,9 @@ impl LocationsFormComponent { if l.canonical && ctx.props().locations.as_ref().unwrap_or(&vec![]).len() > 1 { delete_callback = None; delete_deactivated = true; - } - // If not superuser, restrict deleting and editing locations with Thoth location platform - if !ctx - .props() - .current_user - .resource_access - .is_superuser + // If not superuser, restrict deleting and editing locations with Thoth location platform + if !ctx.props().current_user.resource_access.is_superuser && l.location_platform == LocationPlatform::Thoth { delete_callback = None; From da7537d3195b47c34e2f5ca0bd04fc3bf816b55e Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Tue, 19 Nov 2024 14:17:34 +0100 Subject: [PATCH 10/12] Prevent non-superusers from editing canonical location when Thoth canonical location exists --- thoth-api/src/graphql/model.rs | 29 +++++++++++++++++++---- thoth-app/src/component/locations_form.rs | 7 +----- thoth-errors/src/lib.rs | 2 ++ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/thoth-api/src/graphql/model.rs b/thoth-api/src/graphql/model.rs index 194da909..25360680 100644 --- a/thoth-api/src/graphql/model.rs +++ b/thoth-api/src/graphql/model.rs @@ -1975,18 +1975,37 @@ impl MutationRoot { #[graphql(description = "Values to apply to existing location")] data: PatchLocation, ) -> FieldResult { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; - let location = Location::from_id(&context.db, &data.location_id).unwrap(); + let current_location = Location::from_id(&context.db, &data.location_id).unwrap(); + let publication = Publication::from_id(&context.db, &data.publication_id).unwrap(); + let thoth_location = publication.locations( + context, + Some(100), + Some(0), + Some(LocationOrderBy::default()), + Some(vec![LocationPlatform::Thoth]), + ); + + let locations = thoth_location?; + + let has_canonical_thoth_location = locations.iter().any(|location| { + location.location_platform == LocationPlatform::Thoth && location.canonical + }); + // Only superusers can update the canonical location when a Thoth Location Platform canonical location already exists + if has_canonical_thoth_location && data.canonical && !context.account_access.is_superuser { + return Err(ThothError::ThothUpdateCanonicalError.into()); + } + // Only superusers can edit locations where Location Platform is Thoth if !context.account_access.is_superuser - && location.location_platform == LocationPlatform::Thoth + && current_location.location_platform == LocationPlatform::Thoth { return Err(ThothError::ThothLocationError.into()); } context .account_access - .can_edit(location.publisher_id(&context.db)?)?; + .can_edit(current_location.publisher_id(&context.db)?)?; - if data.publication_id != location.publication_id { + if data.publication_id != current_location.publication_id { context .account_access .can_edit(publisher_id_from_publication_id( @@ -2000,7 +2019,7 @@ impl MutationRoot { } let account_id = context.token.jwt.as_ref().unwrap().account_id(&context.db); - location + current_location .update(&context.db, &data, &account_id) .map_err(|e| e.into()) } diff --git a/thoth-app/src/component/locations_form.rs b/thoth-app/src/component/locations_form.rs index e9cf4315..028ff02f 100644 --- a/thoth-app/src/component/locations_form.rs +++ b/thoth-app/src/component/locations_form.rs @@ -157,12 +157,7 @@ impl Component for LocationsFormComponent { .enum_values .clone() .into_iter() - .filter(|platform| { - *platform - != LocationPlatformValues { - name: LocationPlatform::Thoth, - } - }) + .filter(|platform| platform.name != LocationPlatform::Thoth) .collect() } } diff --git a/thoth-errors/src/lib.rs b/thoth-errors/src/lib.rs index 9244de18..26445d53 100644 --- a/thoth-errors/src/lib.rs +++ b/thoth-errors/src/lib.rs @@ -99,6 +99,8 @@ pub enum ThothError { NoWithdrawnDateError, #[error("Only superusers can create, edit, or delete Locations where the Location Platform is Thoth.")] ThothLocationError, + #[error("Only superusers can update the canonical location when Thoth Location Platform is already set as canonical.")] + ThothUpdateCanonicalError, } #[cfg(not(target_arch = "wasm32"))] From aa83d2a4fad832d0285838d7f0b5afe14e4b7ee4 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Tue, 19 Nov 2024 14:31:31 +0100 Subject: [PATCH 11/12] Remove extraneous check on LocationPlatform::Thoth --- thoth-api/src/graphql/model.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/thoth-api/src/graphql/model.rs b/thoth-api/src/graphql/model.rs index 25360680..d1d5e888 100644 --- a/thoth-api/src/graphql/model.rs +++ b/thoth-api/src/graphql/model.rs @@ -1987,9 +1987,7 @@ impl MutationRoot { let locations = thoth_location?; - let has_canonical_thoth_location = locations.iter().any(|location| { - location.location_platform == LocationPlatform::Thoth && location.canonical - }); + let has_canonical_thoth_location = locations.iter().any(|location| location.canonical); // Only superusers can update the canonical location when a Thoth Location Platform canonical location already exists if has_canonical_thoth_location && data.canonical && !context.account_access.is_superuser { return Err(ThothError::ThothUpdateCanonicalError.into()); From 0e7523d4b065d68c421ca9fa0a3e0424c9907cc6 Mon Sep 17 00:00:00 2001 From: Brendan O'Connell Date: Tue, 19 Nov 2024 15:32:19 +0100 Subject: [PATCH 12/12] Refactor has_canonical_thoth_location --- thoth-api/src/graphql/model.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/thoth-api/src/graphql/model.rs b/thoth-api/src/graphql/model.rs index 6ecd82e2..339ff4e1 100644 --- a/thoth-api/src/graphql/model.rs +++ b/thoth-api/src/graphql/model.rs @@ -1976,18 +1976,16 @@ impl MutationRoot { ) -> FieldResult { context.token.jwt.as_ref().ok_or(ThothError::Unauthorised)?; let current_location = Location::from_id(&context.db, &data.location_id).unwrap(); - let publication = Publication::from_id(&context.db, &data.publication_id).unwrap(); - let thoth_location = publication.locations( - context, - Some(100), - Some(0), - Some(LocationOrderBy::default()), - Some(vec![LocationPlatform::Thoth]), - ); - - let locations = thoth_location?; - - let has_canonical_thoth_location = locations.iter().any(|location| location.canonical); + let has_canonical_thoth_location = Publication::from_id(&context.db, &data.publication_id)? + .locations( + context, + Some(1), + None, + None, + Some(vec![LocationPlatform::Thoth]), + )? + .first() + .map_or(false, |location| location.canonical); // Only superusers can update the canonical location when a Thoth Location Platform canonical location already exists if has_canonical_thoth_location && data.canonical && !context.account_access.is_superuser { return Err(ThothError::ThothUpdateCanonicalError.into());