From 3469252cd326905e851523f87e2a71f60f62296d Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sun, 29 Sep 2024 15:01:46 +0200 Subject: [PATCH] Refactoring to move authentication out of the ResourceService layer --- crates/caldav/src/calendar/resource.rs | 14 ++++++-------- crates/caldav/src/event/resource.rs | 7 ++++--- crates/caldav/src/principal/mod.rs | 15 +++++---------- crates/caldav/src/root/mod.rs | 18 +++++------------- crates/dav/src/methods/delete.rs | 6 ++---- crates/dav/src/methods/propfind.rs | 7 +++---- crates/dav/src/methods/proppatch.rs | 5 ++--- crates/dav/src/resource.rs | 9 ++------- 8 files changed, 29 insertions(+), 52 deletions(-) diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index ea1b334..d06da3a 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -3,7 +3,6 @@ use crate::Error; use actix_web::{web::Data, HttpRequest}; use async_trait::async_trait; use derive_more::derive::{From, Into}; -use rustical_auth::AuthInfo; use rustical_dav::resource::{InvalidProperty, Resource, ResourceService}; use rustical_dav::xml::HrefElement; use rustical_store::calendar::Calendar; @@ -224,7 +223,10 @@ impl ResourceService for CalendarResourceService { type Resource = CalendarResource; type Error = Error; - async fn get_resource(&self) -> Result { + async fn get_resource(&self, principal: String) -> Result { + if self.principal != principal { + return Err(Error::Unauthorized); + } let calendar = self .cal_store .read() @@ -235,10 +237,7 @@ impl ResourceService for CalendarResourceService { Ok(calendar.into()) } - async fn get_members( - &self, - _auth_info: AuthInfo, - ) -> Result, Self::Error> { + async fn get_members(&self) -> Result, Self::Error> { // As of now the calendar resource has no members since events are shown with REPORT Ok(self .cal_store @@ -253,7 +252,6 @@ impl ResourceService for CalendarResourceService { async fn new( req: &HttpRequest, - auth_info: &AuthInfo, path_components: Self::PathComponents, ) -> Result { let cal_store = req @@ -264,7 +262,7 @@ impl ResourceService for CalendarResourceService { Ok(Self { path: req.path().to_owned(), - principal: auth_info.user_id.to_owned(), + principal: path_components.0, calendar_id: path_components.1, cal_store, }) diff --git a/crates/caldav/src/event/resource.rs b/crates/caldav/src/event/resource.rs index 6380c5c..a9cb96b 100644 --- a/crates/caldav/src/event/resource.rs +++ b/crates/caldav/src/event/resource.rs @@ -2,7 +2,6 @@ use crate::Error; use actix_web::{web::Data, HttpRequest}; use async_trait::async_trait; use derive_more::derive::{From, Into}; -use rustical_auth::AuthInfo; use rustical_dav::resource::{InvalidProperty, Resource, ResourceService}; use rustical_store::event::Event; use rustical_store::CalendarStore; @@ -72,7 +71,6 @@ impl ResourceService for EventResourceService { async fn new( req: &HttpRequest, - _auth_info: &AuthInfo, path_components: Self::PathComponents, ) -> Result { let (principal, cid, mut uid) = path_components; @@ -96,7 +94,10 @@ impl ResourceService for EventResourceService { }) } - async fn get_resource(&self) -> Result { + async fn get_resource(&self, principal: String) -> Result { + if self.principal != principal { + return Err(Error::Unauthorized); + } let event = self .cal_store .read() diff --git a/crates/caldav/src/principal/mod.rs b/crates/caldav/src/principal/mod.rs index d510c45..133283a 100644 --- a/crates/caldav/src/principal/mod.rs +++ b/crates/caldav/src/principal/mod.rs @@ -2,7 +2,6 @@ use crate::Error; use actix_web::web::Data; use actix_web::HttpRequest; use async_trait::async_trait; -use rustical_auth::AuthInfo; use rustical_dav::resource::{InvalidProperty, Resource, ResourceService}; use rustical_dav::xml::HrefElement; use rustical_store::CalendarStore; @@ -93,12 +92,8 @@ impl ResourceService for PrincipalResourceService async fn new( req: &HttpRequest, - auth_info: &AuthInfo, (principal,): Self::PathComponents, ) -> Result { - if auth_info.user_id != principal { - return Err(Error::Unauthorized); - } let cal_store = req .app_data::>>() .expect("no calendar store in app_data!") @@ -112,16 +107,16 @@ impl ResourceService for PrincipalResourceService }) } - async fn get_resource(&self) -> Result { + async fn get_resource(&self, principal: String) -> Result { + if self.principal != principal { + return Err(Error::Unauthorized); + } Ok(PrincipalResource { principal: self.principal.to_owned(), }) } - async fn get_members( - &self, - _auth_info: AuthInfo, - ) -> Result, Self::Error> { + async fn get_members(&self) -> Result, Self::Error> { let calendars = self .cal_store .read() diff --git a/crates/caldav/src/root/mod.rs b/crates/caldav/src/root/mod.rs index a89128b..d8a4ccc 100644 --- a/crates/caldav/src/root/mod.rs +++ b/crates/caldav/src/root/mod.rs @@ -1,15 +1,12 @@ use crate::Error; use actix_web::HttpRequest; use async_trait::async_trait; -use rustical_auth::AuthInfo; use rustical_dav::resource::{InvalidProperty, Resource, ResourceService}; use rustical_dav::xml::HrefElement; use serde::{Deserialize, Serialize}; use strum::{EnumString, VariantNames}; -pub struct RootResourceService { - principal: String, -} +pub struct RootResourceService; #[derive(EnumString, Debug, VariantNames, Clone)] #[strum(serialize_all = "kebab-case")] @@ -42,7 +39,7 @@ impl InvalidProperty for RootProp { #[derive(Clone)] pub struct RootResource { - pub principal: String, + principal: String, } impl Resource for RootResource { @@ -69,18 +66,13 @@ impl ResourceService for RootResourceService { async fn new( _req: &HttpRequest, - auth_info: &AuthInfo, _path_components: Self::PathComponents, ) -> Result { - Ok(Self { - principal: auth_info.user_id.to_owned(), - }) + Ok(Self) } - async fn get_resource(&self) -> Result { - Ok(RootResource { - principal: self.principal.to_owned(), - }) + async fn get_resource(&self, principal: String) -> Result { + Ok(RootResource { principal }) } async fn save_resource(&self, _file: Self::Resource) -> Result<(), Self::Error> { diff --git a/crates/dav/src/methods/delete.rs b/crates/dav/src/methods/delete.rs index 5850990..def2bd5 100644 --- a/crates/dav/src/methods/delete.rs +++ b/crates/dav/src/methods/delete.rs @@ -3,14 +3,12 @@ use actix_web::web::Path; use actix_web::HttpRequest; use actix_web::HttpResponse; use actix_web::Responder; -use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; +use rustical_auth::CheckAuthentication; pub async fn route_delete( path_components: Path, req: HttpRequest, - auth: AuthInfoExtractor, ) -> Result { - let auth_info = auth.inner; let path_components = path_components.into_inner(); let no_trash = req @@ -19,7 +17,7 @@ pub async fn route_delete( .map(|val| matches!(val.to_str(), Ok("1"))) .unwrap_or(false); - let resource_service = R::new(&req, &auth_info, path_components.clone()).await?; + let resource_service = R::new(&req, path_components.clone()).await?; resource_service.delete_resource(!no_trash).await?; Ok(HttpResponse::Ok().body("")) diff --git a/crates/dav/src/methods/propfind.rs b/crates/dav/src/methods/propfind.rs index 5a64d65..18683cf 100644 --- a/crates/dav/src/methods/propfind.rs +++ b/crates/dav/src/methods/propfind.rs @@ -54,11 +54,10 @@ pub async fn route_propfind( R::Error, > { debug!("{body}"); - let auth_info = auth.inner; let prefix = prefix.into_inner(); let path = req.path().to_owned(); - let resource_service = R::new(&req, &auth_info, path_components.into_inner()).await?; + let resource_service = R::new(&req, path_components.into_inner()).await?; // A request body is optional. If empty we MUST return all props let propfind: PropfindElement = if !body.is_empty() { @@ -83,12 +82,12 @@ pub async fn route_propfind( let mut member_responses = Vec::new(); if depth != Depth::Zero { - for (path, member) in resource_service.get_members(auth_info).await? { + for (path, member) in resource_service.get_members().await? { member_responses.push(member.propfind(&prefix, path, props.clone()).await?); } } - let resource = resource_service.get_resource().await?; + let resource = resource_service.get_resource(auth.inner.user_id).await?; let response = resource.propfind(&prefix, path, props).await?; Ok(MultistatusElement { diff --git a/crates/dav/src/methods/proppatch.rs b/crates/dav/src/methods/proppatch.rs index a666d29..b9f8f48 100644 --- a/crates/dav/src/methods/proppatch.rs +++ b/crates/dav/src/methods/proppatch.rs @@ -53,10 +53,9 @@ pub async fn route_proppatch( req: HttpRequest, auth: AuthInfoExtractor, ) -> Result, PropstatWrapper>, R::Error> { - let auth_info = auth.inner; let path_components = path.into_inner(); let href = req.path().to_owned(); - let resource_service = R::new(&req, &auth_info, path_components.clone()).await?; + let resource_service = R::new(&req, path_components.clone()).await?; debug!("{body}"); @@ -76,7 +75,7 @@ pub async fn route_proppatch( }) .collect(); - let mut resource = resource_service.get_resource().await?; + let mut resource = resource_service.get_resource(auth.inner.user_id).await?; let mut props_ok = Vec::new(); let mut props_conflict = Vec::new(); diff --git a/crates/dav/src/resource.rs b/crates/dav/src/resource.rs index 38a82df..effc7ae 100644 --- a/crates/dav/src/resource.rs +++ b/crates/dav/src/resource.rs @@ -5,7 +5,6 @@ use actix_web::{http::StatusCode, HttpRequest, ResponseError}; use async_trait::async_trait; use core::fmt; use itertools::Itertools; -use rustical_auth::AuthInfo; use serde::{Deserialize, Serialize}; use std::str::FromStr; use strum::VariantNames; @@ -47,18 +46,14 @@ pub trait ResourceService: Sized { async fn new( req: &HttpRequest, - auth_info: &AuthInfo, path_components: Self::PathComponents, ) -> Result; - async fn get_members( - &self, - _auth_info: AuthInfo, - ) -> Result, Self::Error> { + async fn get_members(&self) -> Result, Self::Error> { Ok(vec![]) } - async fn get_resource(&self) -> Result; + async fn get_resource(&self, principal: String) -> Result; async fn save_resource(&self, file: Self::Resource) -> Result<(), Self::Error>; async fn delete_resource(&self, _use_trashbin: bool) -> Result<(), Self::Error> { Err(crate::Error::Unauthorized.into())