diff --git a/crates/api-common/bindings/AllServiceHostSettings.ts b/crates/api-common/bindings/AllServiceHostSettings.ts new file mode 100644 index 0000000..22956a7 --- /dev/null +++ b/crates/api-common/bindings/AllServiceHostSettings.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ServiceHostId } from "./ServiceHostId"; +import type { ServiceHostSettings } from "./ServiceHostSettings"; + +export interface AllServiceHostSettings { user: Record, member?: Record, } \ No newline at end of file diff --git a/crates/api-common/src/lib.rs b/crates/api-common/src/lib.rs index 6390154..c7ce625 100644 --- a/crates/api-common/src/lib.rs +++ b/crates/api-common/src/lib.rs @@ -923,6 +923,7 @@ impl ServiceHostSettings { /// Service settings for a given user categorized by origin #[derive(Deserialize, Serialize, Debug, Clone, TS)] +#[ts(export)] pub struct AllServiceSettings { /// A hosts service settings owned by the user #[ts(optional)] @@ -932,6 +933,17 @@ pub struct AllServiceSettings { pub member: Option, } +/// Service settings for a given user categorized by origin +#[derive(Deserialize, Serialize, Debug, Clone, TS)] +#[ts(export)] +pub struct AllServiceHostSettings { + /// All service-host settings owned by the user + pub user: HashMap, + /// All service-host settings owned by a group in which the user is a member + #[ts(optional)] + pub member: Option>, +} + /// Send message request (for authorized services) #[derive(Deserialize, Serialize, Debug, Clone, TS)] #[serde(rename_all = "camelCase")] diff --git a/crates/cloud/src/services/settings/actions.rs b/crates/cloud/src/services/settings/actions.rs index 8ce33ad..9ff311b 100644 --- a/crates/cloud/src/services/settings/actions.rs +++ b/crates/cloud/src/services/settings/actions.rs @@ -17,20 +17,20 @@ impl<'a> SettingsActions<'a> { Self { users, groups } } - pub(crate) async fn get_all_settings( + pub(crate) async fn get_all_user_settings( &self, vs: &auth::ViewSettings, host: &api::ServiceHostId, ) -> Result { let query = doc! {"username": &vs.username}; - let user = self + let mut user = self .users .find_one(query, None) .await .map_err(InternalError::DatabaseConnectionError)? .ok_or(UserError::UserNotFoundError)?; - let mut user_settings = user.service_settings.get(host).cloned(); + let mut user_settings = user.service_settings.remove(host); let mut member_settings = if let Some(group_id) = user.group_id { let query = doc! {"id": group_id}; @@ -41,8 +41,7 @@ impl<'a> SettingsActions<'a> { .map_err(InternalError::DatabaseConnectionError)? .ok_or(UserError::UserNotFoundError)? .service_settings - .get(host) - .cloned(); + .remove(host); settings } else { None @@ -68,6 +67,56 @@ impl<'a> SettingsActions<'a> { Ok(all_settings) } + pub(crate) async fn get_all_settings( + &self, + vs: &auth::ViewSettings, + ) -> Result { + let query = doc! {"username": &vs.username}; + let user = self + .users + .find_one(query, None) + .await + .map_err(InternalError::DatabaseConnectionError)? + .ok_or(UserError::UserNotFoundError)?; + + let mut all_user_settings = user.service_settings; + + let mut all_member_settings = if let Some(group_id) = user.group_id { + let query = doc! {"id": group_id}; + let settings = self + .groups + .find_one(query, None) + .await + .map_err(InternalError::DatabaseConnectionError)? + .ok_or(UserError::UserNotFoundError)? + .service_settings; + Some(settings) + } else { + None + }; + + for (host, host_settings) in all_user_settings.iter_mut() { + if Some(host) != vs.requesting_host.as_ref() { + utils::redact_setting_secrets(host_settings); + } + } + + if let Some(all_member_settings_ref) = all_member_settings.as_mut() { + for (host, host_settings) in all_member_settings_ref.iter_mut() { + if Some(host) != vs.requesting_host.as_ref() { + utils::redact_setting_secrets(host_settings); + } + } + } + + let all_settings = api::AllServiceHostSettings{ + user: all_user_settings, + member: all_member_settings, + }; + + Ok(all_settings) + } + pub(crate) async fn update_user_settings( &self, us: &auth::UpdateSettings, diff --git a/crates/cloud/src/services/settings/routes.rs b/crates/cloud/src/services/settings/routes.rs index d7162a4..ce7a13d 100644 --- a/crates/cloud/src/services/settings/routes.rs +++ b/crates/cloud/src/services/settings/routes.rs @@ -5,25 +5,6 @@ use crate::auth; use crate::common::api; use crate::{app_data::AppData, errors::UserError}; -#[patch("/user/{username}/host/{host}")] -async fn update_user_settings( - app: web::Data, - path: web::Path<(String, api::ServiceHostId)>, - body: web::Json, - req: HttpRequest, -) -> Result { - let (username, host) = path.into_inner(); - let settings = body.into_inner(); - - let auth_us = auth::try_update_user_settings(&app, &req, username, host, settings).await?; - - app.as_settings_actions() - .update_user_settings(&auth_us) - .await?; - - Ok(HttpResponse::Ok().finish()) -} - #[get("/user/{username}")] async fn list_user_hosts_with_settings( app: web::Data, @@ -43,8 +24,21 @@ async fn list_user_hosts_with_settings( Ok(HttpResponse::Ok().json(hosts)) } -#[get("/user/{username}/host/{host}")] +#[get("/user/{username}/all")] async fn get_user_settings( + req: HttpRequest, + app: web::Data, + path: web::Path, +) -> Result { + let username = path.into_inner(); + + let auth_vs = auth::try_view_user_settings(&app, &req, username).await?; + let all_settings = app.as_settings_actions().get_all_settings(&auth_vs).await?; + Ok(HttpResponse::Ok().json(all_settings)) +} + +#[get("/user/{username}/host/{host}")] +async fn get_user_settings_for_host( app: web::Data, path: web::Path<(String, api::ServiceHostId)>, req: HttpRequest, @@ -61,7 +55,7 @@ async fn get_user_settings( } #[get("/user/{username}/host/{host}/all")] -async fn get_all_settings( +async fn get_all_user_settings_for_host( req: HttpRequest, app: web::Data, path: web::Path<(String, api::ServiceHostId)>, @@ -71,13 +65,32 @@ async fn get_all_settings( let auth_vs = auth::try_view_user_settings(&app, &req, username).await?; let all_settings = app .as_settings_actions() - .get_all_settings(&auth_vs, &host) + .get_all_user_settings(&auth_vs, &host) .await?; Ok(HttpResponse::Ok().json(all_settings)) } +#[patch("/user/{username}/host/{host}")] +async fn update_user_host_settings( + app: web::Data, + path: web::Path<(String, api::ServiceHostId)>, + body: web::Json, + req: HttpRequest, +) -> Result { + let (username, host) = path.into_inner(); + let settings = body.into_inner(); + + let auth_us = auth::try_update_user_settings(&app, &req, username, host, settings).await?; + + app.as_settings_actions() + .update_user_settings(&auth_us) + .await?; + + Ok(HttpResponse::Ok().finish()) +} + #[delete("/user/{username}/host/{host}")] -async fn delete_user_settings( +async fn delete_user_settings_for_host( app: web::Data, path: web::Path<(String, api::ServiceHostId)>, req: HttpRequest, @@ -93,7 +106,7 @@ async fn delete_user_settings( } #[delete("/user/{username}/host/{host}/service/{service}")] -async fn delete_all_user_service_settings( +async fn delete_user_settings_for_host_service( app: web::Data, path: web::Path<(String, api::ServiceHostId, api::ServiceName)>, req: HttpRequest, @@ -109,7 +122,7 @@ async fn delete_all_user_service_settings( } #[delete("/user/{username}/host/{host}/service/{service}/setting/{setting}")] -async fn delete_user_service_setting( +async fn delete_user_setting( app: web::Data, path: web::Path<( String, @@ -149,8 +162,26 @@ async fn list_group_hosts_with_settings( Ok(HttpResponse::Ok().json(hosts)) } -#[get("/group/{group_id}/host/{host}")] +#[get("/group/{group_id}/all")] async fn get_group_settings( + app: web::Data, + path: web::Path<(api::GroupId,)>, + req: HttpRequest, +) -> Result { + let (group_id,) = path.into_inner(); + + let auth_vgs = auth::try_view_group_settings(&app, &req, group_id).await?; + + let hosts = app + .as_settings_actions() + .get_group_settings(&auth_vgs) + .await?; + + Ok(HttpResponse::Ok().json(hosts)) +} + +#[get("/group/{group_id}/host/{host}")] +async fn get_group_settings_for_host( app: web::Data, path: web::Path<(api::GroupId, api::ServiceHostId)>, req: HttpRequest, @@ -167,7 +198,7 @@ async fn get_group_settings( } #[patch("/group/{group_id}/host/{host}")] -async fn set_group_settings( +async fn set_group_settings_for_host( app: web::Data, path: web::Path<(api::GroupId, api::ServiceHostId)>, body: web::Json, @@ -186,7 +217,7 @@ async fn set_group_settings( } #[delete("/group/{group_id}/host/{host}")] -async fn delete_group_settings( +async fn delete_group_settings_for_host( app: web::Data, path: web::Path<(api::GroupId, api::ServiceHostId)>, req: HttpRequest, @@ -203,7 +234,7 @@ async fn delete_group_settings( } #[delete("/group/{group_id}/host/{host}/service/{service}")] -async fn delete_all_group_service_settings( +async fn delete_group_settings_for_host_service( app: web::Data, path: web::Path<(api::GroupId, api::ServiceHostId, api::ServiceName)>, req: HttpRequest, @@ -219,7 +250,7 @@ async fn delete_all_group_service_settings( } #[delete("/group/{group_id}/host/{host}/service/{service}/setting/{setting}")] -async fn delete_group_service_setting( +async fn delete_group_setting( app: web::Data, path: web::Path<( api::GroupId, @@ -240,19 +271,21 @@ async fn delete_group_service_setting( } pub fn config(cfg: &mut web::ServiceConfig) { - cfg.service(get_user_settings) - .service(update_user_settings) - .service(list_user_hosts_with_settings) - .service(get_all_settings) - .service(delete_user_settings) - .service(delete_all_user_service_settings) - .service(delete_user_service_setting) - .service(get_group_settings) - .service(set_group_settings) + cfg.service(list_user_hosts_with_settings) + .service(get_user_settings) + .service(get_user_settings_for_host) + .service(get_all_user_settings_for_host) + .service(update_user_host_settings) + .service(delete_user_settings_for_host) + .service(delete_user_settings_for_host_service) + .service(delete_user_setting) .service(list_group_hosts_with_settings) - .service(delete_group_settings) - .service(delete_all_group_service_settings) - .service(delete_group_service_setting); + .service(get_group_settings) + .service(get_group_settings_for_host) + .service(set_group_settings_for_host) + .service(delete_group_settings_for_host) + .service(delete_group_settings_for_host_service) + .service(delete_group_setting); } #[cfg(test)] @@ -490,10 +523,12 @@ mod tests { user.service_settings = test_settings(&host_id, &service, &setting, &value); let visibility = api::ServiceHostScope::Public(Vec::new()); - let host = AuthorizedServiceHost::new(String::from("url"), host_id.clone(), visibility.clone()); + let host = + AuthorizedServiceHost::new(String::from("url"), host_id.clone(), visibility.clone()); let other_host_id = api::ServiceHostId::__from("other_host"); - let other_host = AuthorizedServiceHost::new(String::from("url"), other_host_id.clone(), visibility); + let other_host = + AuthorizedServiceHost::new(String::from("url"), other_host_id.clone(), visibility); test_utils::setup() .with_users(slice::from_ref(&user))