From 031d94c9d12bd5c50b00fdeca3d12c164bf63ff5 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sun, 2 Feb 2025 11:34:10 +0100 Subject: [PATCH] Some preparations for supporting principal memberships --- crates/caldav/src/calendar/methods/mkcalendar.rs | 2 +- crates/caldav/src/calendar/methods/post.rs | 2 +- crates/caldav/src/calendar/methods/report/mod.rs | 2 +- crates/caldav/src/calendar/resource.rs | 8 ++++++-- crates/caldav/src/calendar_object/methods.rs | 6 +++--- crates/caldav/src/calendar_object/resource.rs | 4 +++- crates/caldav/src/calendar_set/mod.rs | 4 ++-- crates/caldav/src/principal/mod.rs | 4 +++- crates/carddav/src/address_object/methods.rs | 10 +++++----- crates/carddav/src/address_object/resource.rs | 4 +++- crates/carddav/src/addressbook/methods/mkcol.rs | 2 +- crates/carddav/src/addressbook/methods/post.rs | 2 +- .../carddav/src/addressbook/methods/report/mod.rs | 2 +- crates/carddav/src/addressbook/resource.rs | 4 +++- crates/carddav/src/principal/mod.rs | 4 +++- crates/frontend/src/routes/addressbook.rs | 4 ++-- crates/frontend/src/routes/calendar.rs | 4 ++-- crates/store/src/auth/user.rs | 13 +++++++++++++ 18 files changed, 54 insertions(+), 27 deletions(-) diff --git a/crates/caldav/src/calendar/methods/mkcalendar.rs b/crates/caldav/src/calendar/methods/mkcalendar.rs index 2fe7be5..3631b95 100644 --- a/crates/caldav/src/calendar/methods/mkcalendar.rs +++ b/crates/caldav/src/calendar/methods/mkcalendar.rs @@ -57,7 +57,7 @@ pub async fn route_mkcalendar( root_span: RootSpan, ) -> Result { let (principal, cal_id) = path.into_inner(); - if principal != user.id { + if !user.is_principal(&principal) { return Err(Error::Unauthorized); } diff --git a/crates/caldav/src/calendar/methods/post.rs b/crates/caldav/src/calendar/methods/post.rs index 52a2e40..607c356 100644 --- a/crates/caldav/src/calendar/methods/post.rs +++ b/crates/caldav/src/calendar/methods/post.rs @@ -23,7 +23,7 @@ pub async fn route_post( req: HttpRequest, ) -> Result { let (principal, cal_id) = path.into_inner(); - if principal != user.id { + if !user.is_principal(&principal) { return Err(Error::Unauthorized); } diff --git a/crates/caldav/src/calendar/methods/report/mod.rs b/crates/caldav/src/calendar/methods/report/mod.rs index 7e927ce..e7007d1 100644 --- a/crates/caldav/src/calendar/methods/report/mod.rs +++ b/crates/caldav/src/calendar/methods/report/mod.rs @@ -34,7 +34,7 @@ pub async fn route_report_calendar( cal_store: Data, ) -> Result { let (principal, cal_id) = path.into_inner(); - if principal != user.id { + if !user.is_principal(&principal) { return Err(Error::Unauthorized); } diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index 1924829..cfbf8b3 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -300,10 +300,14 @@ impl Resource for CalendarResource { fn get_user_privileges(&self, user: &User) -> Result { if self.cal.subscription_url.is_some() || self.read_only { - return Ok(UserPrivilegeSet::owner_read(self.cal.principal == user.id)); + return Ok(UserPrivilegeSet::owner_read( + user.is_principal(&self.cal.principal), + )); } - Ok(UserPrivilegeSet::owner_only(self.cal.principal == user.id)) + Ok(UserPrivilegeSet::owner_only( + user.is_principal(&self.cal.principal), + )) } } diff --git a/crates/caldav/src/calendar_object/methods.rs b/crates/caldav/src/calendar_object/methods.rs index d60ac15..4037e1d 100644 --- a/crates/caldav/src/calendar_object/methods.rs +++ b/crates/caldav/src/calendar_object/methods.rs @@ -24,12 +24,12 @@ pub async fn get_event( object_id, } = path.into_inner(); - if user.id != principal { + if !user.is_principal(&principal) { return Ok(HttpResponse::Unauthorized().body("")); } let calendar = store.get_calendar(&principal, &cal_id).await?; - if user.id != calendar.principal { + if !user.is_principal(&calendar.principal) { return Ok(HttpResponse::Unauthorized().body("")); } @@ -56,7 +56,7 @@ pub async fn put_event( object_id, } = path.into_inner(); - if user.id != principal { + if !user.is_principal(&principal) { return Ok(HttpResponse::Unauthorized().body("")); } diff --git a/crates/caldav/src/calendar_object/resource.rs b/crates/caldav/src/calendar_object/resource.rs index e5f7770..84f2d04 100644 --- a/crates/caldav/src/calendar_object/resource.rs +++ b/crates/caldav/src/calendar_object/resource.rs @@ -91,7 +91,9 @@ impl Resource for CalendarObjectResource { } fn get_user_privileges(&self, user: &User) -> Result { - Ok(UserPrivilegeSet::owner_only(self.principal == user.id)) + Ok(UserPrivilegeSet::owner_only( + user.is_principal(&self.principal), + )) } } diff --git a/crates/caldav/src/calendar_set/mod.rs b/crates/caldav/src/calendar_set/mod.rs index e330e51..555db61 100644 --- a/crates/caldav/src/calendar_set/mod.rs +++ b/crates/caldav/src/calendar_set/mod.rs @@ -55,9 +55,9 @@ impl Resource for CalendarSetResource { fn get_user_privileges(&self, user: &User) -> Result { Ok(if self.read_only { - UserPrivilegeSet::owner_read(self.principal == user.id) + UserPrivilegeSet::owner_read(user.is_principal(&self.principal)) } else { - UserPrivilegeSet::owner_only(self.principal == user.id) + UserPrivilegeSet::owner_only(user.is_principal(&self.principal)) }) } } diff --git a/crates/caldav/src/principal/mod.rs b/crates/caldav/src/principal/mod.rs index e4c4533..7f8a998 100644 --- a/crates/caldav/src/principal/mod.rs +++ b/crates/caldav/src/principal/mod.rs @@ -113,7 +113,9 @@ impl Resource for PrincipalResource { } fn get_user_privileges(&self, user: &User) -> Result { - Ok(UserPrivilegeSet::owner_read(self.principal == user.id)) + Ok(UserPrivilegeSet::owner_read( + user.is_principal(&self.principal), + )) } } diff --git a/crates/carddav/src/address_object/methods.rs b/crates/carddav/src/address_object/methods.rs index e7a4c8f..e0bdc05 100644 --- a/crates/carddav/src/address_object/methods.rs +++ b/crates/carddav/src/address_object/methods.rs @@ -26,8 +26,8 @@ pub async fn get_object( object_id, } = path.into_inner(); - if user.id != principal { - return Ok(HttpResponse::Unauthorized().body("")); + if !user.is_principal(&principal) { + return Err(Error::Unauthorized); } let addressbook = store.get_addressbook(&principal, &addressbook_id).await?; @@ -64,8 +64,8 @@ pub async fn put_object( object_id, } = path.into_inner(); - if user.id != principal { - return Ok(HttpResponse::Unauthorized().body("")); + if !user.is_principal(&principal) { + return Err(Error::Unauthorized); } // TODO: implement If-Match @@ -79,5 +79,5 @@ pub async fn put_object( .put_object(principal, addressbook_id, object, overwrite) .await?; - Ok(HttpResponse::Created().body("")) + Ok(HttpResponse::Created().finish()) } diff --git a/crates/carddav/src/address_object/resource.rs b/crates/carddav/src/address_object/resource.rs index aec88d3..b170618 100644 --- a/crates/carddav/src/address_object/resource.rs +++ b/crates/carddav/src/address_object/resource.rs @@ -87,7 +87,9 @@ impl Resource for AddressObjectResource { } fn get_user_privileges(&self, user: &User) -> Result { - Ok(UserPrivilegeSet::owner_only(self.principal == user.id)) + Ok(UserPrivilegeSet::owner_only( + user.is_principal(&self.principal), + )) } } diff --git a/crates/carddav/src/addressbook/methods/mkcol.rs b/crates/carddav/src/addressbook/methods/mkcol.rs index bd801e0..e8cf323 100644 --- a/crates/carddav/src/addressbook/methods/mkcol.rs +++ b/crates/carddav/src/addressbook/methods/mkcol.rs @@ -48,7 +48,7 @@ pub async fn route_mkcol( root_span: RootSpan, ) -> Result { let (principal, addressbook_id) = path.into_inner(); - if principal != user.id { + if !user.is_principal(&principal) { return Err(Error::Unauthorized); } diff --git a/crates/carddav/src/addressbook/methods/post.rs b/crates/carddav/src/addressbook/methods/post.rs index 54a6815..33a14b6 100644 --- a/crates/carddav/src/addressbook/methods/post.rs +++ b/crates/carddav/src/addressbook/methods/post.rs @@ -20,7 +20,7 @@ pub async fn route_post( req: HttpRequest, ) -> Result { let (principal, addressbook_id) = path.into_inner(); - if principal != user.id { + if !user.is_principal(&principal) { return Err(Error::Unauthorized); } diff --git a/crates/carddav/src/addressbook/methods/report/mod.rs b/crates/carddav/src/addressbook/methods/report/mod.rs index 5349f5f..426217d 100644 --- a/crates/carddav/src/addressbook/methods/report/mod.rs +++ b/crates/carddav/src/addressbook/methods/report/mod.rs @@ -30,7 +30,7 @@ pub async fn route_report_addressbook( addr_store: Data, ) -> Result { let (principal, addressbook_id) = path.into_inner(); - if principal != user.id { + if !user.is_principal(&principal) { return Err(Error::Unauthorized); } diff --git a/crates/carddav/src/addressbook/resource.rs b/crates/carddav/src/addressbook/resource.rs index 7cbd0cf..e8a0a5c 100644 --- a/crates/carddav/src/addressbook/resource.rs +++ b/crates/carddav/src/addressbook/resource.rs @@ -185,7 +185,9 @@ impl Resource for AddressbookResource { } fn get_user_privileges(&self, user: &User) -> Result { - Ok(UserPrivilegeSet::owner_only(self.0.principal == user.id)) + Ok(UserPrivilegeSet::owner_only( + user.is_principal(&self.0.principal), + )) } } diff --git a/crates/carddav/src/principal/mod.rs b/crates/carddav/src/principal/mod.rs index d20610c..6901b13 100644 --- a/crates/carddav/src/principal/mod.rs +++ b/crates/carddav/src/principal/mod.rs @@ -108,7 +108,9 @@ impl Resource for PrincipalResource { } fn get_user_privileges(&self, user: &User) -> Result { - Ok(UserPrivilegeSet::owner_only(self.principal == user.id)) + Ok(UserPrivilegeSet::owner_only( + user.is_principal(&self.principal), + )) } } diff --git a/crates/frontend/src/routes/addressbook.rs b/crates/frontend/src/routes/addressbook.rs index e8d58a8..3d98dda 100644 --- a/crates/frontend/src/routes/addressbook.rs +++ b/crates/frontend/src/routes/addressbook.rs @@ -19,7 +19,7 @@ pub async fn route_addressbook( user: User, ) -> Result { let (owner, addrbook_id) = path.into_inner(); - if owner != user.id { + if !user.is_principal(&owner) { return Ok(HttpResponse::Unauthorized().body("Unauthorized")); } Ok(AddressbookPage { @@ -35,7 +35,7 @@ pub async fn route_addressbook_restore( user: User, ) -> Result { let (owner, addressbook_id) = path.into_inner(); - if owner != user.id { + if !user.is_principal(&owner) { return Ok(HttpResponse::Unauthorized().body("Unauthorized")); } store.restore_addressbook(&owner, &addressbook_id).await?; diff --git a/crates/frontend/src/routes/calendar.rs b/crates/frontend/src/routes/calendar.rs index a264217..f584eab 100644 --- a/crates/frontend/src/routes/calendar.rs +++ b/crates/frontend/src/routes/calendar.rs @@ -19,7 +19,7 @@ pub async fn route_calendar( user: User, ) -> Result { let (owner, cal_id) = path.into_inner(); - if owner != user.id { + if !user.is_principal(&owner) { return Ok(HttpResponse::Unauthorized().body("Unauthorized")); } Ok(CalendarPage { @@ -35,7 +35,7 @@ pub async fn route_calendar_restore( user: User, ) -> Result { let (owner, cal_id) = path.into_inner(); - if owner != user.id { + if !user.is_principal(&owner) { return Ok(HttpResponse::Unauthorized().body("Unauthorized")); } store.restore_calendar(&owner, &cal_id).await?; diff --git a/crates/store/src/auth/user.rs b/crates/store/src/auth/user.rs index bb7ed77..ec85916 100644 --- a/crates/store/src/auth/user.rs +++ b/crates/store/src/auth/user.rs @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; use std::future::{ready, Ready}; #[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] pub struct User { pub id: String, pub displayname: Option, @@ -16,6 +17,18 @@ pub struct User { pub app_tokens: Vec, } +impl User { + /// Returns true if the user is either + /// - the principal itself + /// - has full access to the prinicpal (is member) + pub fn is_principal(&self, principal: &str) -> bool { + if self.id == principal { + return true; + } + false + } +} + #[derive(Clone, Debug, Display)] pub struct UnauthorizedError;