diff --git a/crates/caldav/src/calendar/methods/get.rs b/crates/caldav/src/calendar/methods/get.rs index f24f67d..73addab 100644 --- a/crates/caldav/src/calendar/methods/get.rs +++ b/crates/caldav/src/calendar/methods/get.rs @@ -9,7 +9,7 @@ use ical::generator::{Emitter, IcalCalendarBuilder}; use ical::property::Property; use percent_encoding::{CONTROLS, utf8_percent_encode}; use rustical_ical::{CalendarObjectComponent, EventObject, JournalObject, TodoObject}; -use rustical_store::{CalendarStore, SubscriptionStore, auth::User}; +use rustical_store::{CalendarStore, SubscriptionStore, auth::Principal}; use std::collections::HashMap; use std::str::FromStr; use tracing::instrument; @@ -18,7 +18,7 @@ use tracing::instrument; pub async fn route_get( Path((principal, calendar_id)): Path<(String, String)>, State(CalendarResourceService { cal_store, .. }): State>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&principal) { return Err(crate::Error::Unauthorized); diff --git a/crates/caldav/src/calendar/methods/mkcalendar.rs b/crates/caldav/src/calendar/methods/mkcalendar.rs index 0b95231..da56afc 100644 --- a/crates/caldav/src/calendar/methods/mkcalendar.rs +++ b/crates/caldav/src/calendar/methods/mkcalendar.rs @@ -6,7 +6,7 @@ use axum::response::{IntoResponse, Response}; use http::{Method, StatusCode}; use rustical_dav::xml::HrefElement; use rustical_ical::CalendarObjectType; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use rustical_store::{Calendar, CalendarStore, SubscriptionStore}; use rustical_xml::{Unparsed, XmlDeserialize, XmlDocument, XmlRootTag}; use tracing::instrument; @@ -63,7 +63,7 @@ struct MkcolRequest { #[instrument(skip(cal_store))] pub async fn route_mkcalendar( Path((principal, cal_id)): Path<(String, String)>, - user: User, + user: Principal, State(CalendarResourceService { cal_store, .. }): State>, method: Method, body: String, diff --git a/crates/caldav/src/calendar/methods/post.rs b/crates/caldav/src/calendar/methods/post.rs index 511c9cb..cc7536c 100644 --- a/crates/caldav/src/calendar/methods/post.rs +++ b/crates/caldav/src/calendar/methods/post.rs @@ -7,7 +7,7 @@ use http::{HeaderMap, HeaderValue, StatusCode, header}; use rustical_dav::privileges::UserPrivilege; use rustical_dav::resource::Resource; use rustical_dav_push::register::PushRegister; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use rustical_store::{CalendarStore, Subscription, SubscriptionStore}; use rustical_xml::XmlDocument; use tracing::instrument; @@ -15,7 +15,7 @@ use tracing::instrument; #[instrument(skip(resource_service))] pub async fn route_post( Path((principal, cal_id)): Path<(String, String)>, - user: User, + user: Principal, State(resource_service): State>, body: String, ) -> Result { diff --git a/crates/caldav/src/calendar/methods/report/mod.rs b/crates/caldav/src/calendar/methods/report/mod.rs index 42ea102..f6de9b0 100644 --- a/crates/caldav/src/calendar/methods/report/mod.rs +++ b/crates/caldav/src/calendar/methods/report/mod.rs @@ -21,7 +21,7 @@ use rustical_dav::{ }, }; use rustical_ical::CalendarObject; -use rustical_store::{CalendarStore, SubscriptionStore, auth::User}; +use rustical_store::{CalendarStore, SubscriptionStore, auth::Principal}; use rustical_xml::{XmlDeserialize, XmlDocument}; use sync_collection::handle_sync_collection; use tracing::instrument; @@ -56,7 +56,7 @@ fn objects_response( path: &str, principal: &str, puri: &impl PrincipalUri, - user: &User, + user: &Principal, prop: &PropfindType, ) -> Result, Error> { let mut responses = Vec::new(); @@ -90,7 +90,7 @@ fn objects_response( #[instrument(skip(cal_store))] pub async fn route_report_calendar( Path((principal, cal_id)): Path<(String, String)>, - user: User, + user: Principal, Extension(puri): Extension, State(CalendarResourceService { cal_store, .. }): State>, OriginalUri(uri): OriginalUri, diff --git a/crates/caldav/src/calendar/methods/report/sync_collection.rs b/crates/caldav/src/calendar/methods/report/sync_collection.rs index 33c762d..fa0479f 100644 --- a/crates/caldav/src/calendar/methods/report/sync_collection.rs +++ b/crates/caldav/src/calendar/methods/report/sync_collection.rs @@ -13,7 +13,7 @@ use rustical_dav::{ }; use rustical_store::{ CalendarStore, - auth::User, + auth::Principal, synctoken::{format_synctoken, parse_synctoken}, }; @@ -21,7 +21,7 @@ pub async fn handle_sync_collection( sync_collection: &SyncCollectionRequest, path: &str, puri: &impl PrincipalUri, - user: &User, + user: &Principal, principal: &str, cal_id: &str, cal_store: &C, diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index 7ed8ca3..58b5343 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -12,7 +12,7 @@ use rustical_dav::xml::{HrefElement, Resourcetype, ResourcetypeInner, SupportedR use rustical_dav_push::{DavPushExtension, DavPushExtensionProp}; use rustical_ical::CalDateTime; use rustical_store::Calendar; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use rustical_xml::{EnumVariants, PropName}; use rustical_xml::{XmlDeserialize, XmlSerialize}; use std::str::FromStr; @@ -95,7 +95,7 @@ impl DavPushExtension for CalendarResource { impl Resource for CalendarResource { type Prop = CalendarPropWrapper; type Error = Error; - type Principal = User; + type Principal = Principal; fn is_collection(&self) -> bool { true @@ -121,7 +121,7 @@ impl Resource for CalendarResource { fn get_prop( &self, puri: &impl PrincipalUri, - user: &User, + user: &Principal, prop: &CalendarPropWrapperName, ) -> Result { Ok(match prop { @@ -291,7 +291,7 @@ impl Resource for CalendarResource { Some(&self.cal.principal) } - fn get_user_privileges(&self, user: &User) -> Result { + fn get_user_privileges(&self, user: &Principal) -> Result { if self.cal.subscription_url.is_some() || self.read_only { return Ok(UserPrivilegeSet::owner_read( user.is_principal(&self.cal.principal), diff --git a/crates/caldav/src/calendar/service.rs b/crates/caldav/src/calendar/service.rs index 0000f28..e4eb2d7 100644 --- a/crates/caldav/src/calendar/service.rs +++ b/crates/caldav/src/calendar/service.rs @@ -13,7 +13,7 @@ use axum::handler::Handler; use axum::response::Response; use futures_util::future::BoxFuture; use rustical_dav::resource::{AxumMethods, ResourceService}; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use rustical_store::{CalendarStore, SubscriptionStore}; use std::convert::Infallible; use std::sync::Arc; @@ -48,7 +48,7 @@ impl ResourceService for CalendarResourc type PathComponents = (String, String); // principal, calendar_id type Resource = CalendarResource; type Error = Error; - type Principal = User; + type Principal = Principal; type PrincipalUri = CalDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, calendar-access, calendar-proxy, webdav-push"; diff --git a/crates/caldav/src/calendar_object/methods.rs b/crates/caldav/src/calendar_object/methods.rs index 74366f3..3ee4fd1 100644 --- a/crates/caldav/src/calendar_object/methods.rs +++ b/crates/caldav/src/calendar_object/methods.rs @@ -9,7 +9,7 @@ use headers::{ContentType, ETag, HeaderMapExt, IfNoneMatch}; use http::{HeaderMap, StatusCode}; use rustical_ical::CalendarObject; use rustical_store::CalendarStore; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use std::str::FromStr; use tracing::instrument; @@ -21,7 +21,7 @@ pub async fn get_event( object_id, }): Path, State(CalendarObjectResourceService { cal_store }): State>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&principal) { return Err(crate::Error::Unauthorized); @@ -51,7 +51,7 @@ pub async fn put_event( object_id, }): Path, State(CalendarObjectResourceService { cal_store }): State>, - user: User, + user: Principal, mut if_none_match: Option>, header_map: HeaderMap, body: String, diff --git a/crates/caldav/src/calendar_object/resource.rs b/crates/caldav/src/calendar_object/resource.rs index 1e83d25..5834dc4 100644 --- a/crates/caldav/src/calendar_object/resource.rs +++ b/crates/caldav/src/calendar_object/resource.rs @@ -8,7 +8,7 @@ use rustical_dav::{ xml::Resourcetype, }; use rustical_ical::CalendarObject; -use rustical_store::auth::User; +use rustical_store::auth::Principal; #[derive(Clone, From, Into)] pub struct CalendarObjectResource { @@ -25,7 +25,7 @@ impl ResourceName for CalendarObjectResource { impl Resource for CalendarObjectResource { type Prop = CalendarObjectPropWrapper; type Error = Error; - type Principal = User; + type Principal = Principal; fn is_collection(&self) -> bool { false @@ -38,7 +38,7 @@ impl Resource for CalendarObjectResource { fn get_prop( &self, puri: &impl PrincipalUri, - user: &User, + user: &Principal, prop: &CalendarObjectPropWrapperName, ) -> Result { Ok(match prop { @@ -81,7 +81,7 @@ impl Resource for CalendarObjectResource { Some(self.object.get_etag()) } - fn get_user_privileges(&self, user: &User) -> Result { + fn get_user_privileges(&self, user: &Principal) -> Result { Ok(UserPrivilegeSet::owner_only( user.is_principal(&self.principal), )) diff --git a/crates/caldav/src/calendar_object/service.rs b/crates/caldav/src/calendar_object/service.rs index d9efed4..899ff88 100644 --- a/crates/caldav/src/calendar_object/service.rs +++ b/crates/caldav/src/calendar_object/service.rs @@ -9,7 +9,7 @@ use async_trait::async_trait; use axum::{extract::Request, handler::Handler, response::Response}; use futures_util::future::BoxFuture; use rustical_dav::resource::{AxumMethods, ResourceService}; -use rustical_store::{CalendarStore, auth::User}; +use rustical_store::{CalendarStore, auth::Principal}; use serde::{Deserialize, Deserializer}; use std::{convert::Infallible, sync::Arc}; use tower::Service; @@ -46,7 +46,7 @@ impl ResourceService for CalendarObjectResourceService { type Resource = CalendarObjectResource; type MemberType = CalendarObjectResource; type Error = Error; - type Principal = User; + type Principal = Principal; type PrincipalUri = CalDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, calendar-access"; diff --git a/crates/caldav/src/lib.rs b/crates/caldav/src/lib.rs index dc7c89b..3198808 100644 --- a/crates/caldav/src/lib.rs +++ b/crates/caldav/src/lib.rs @@ -6,7 +6,7 @@ use principal::PrincipalResourceService; use rustical_dav::resource::{PrincipalUri, ResourceService}; use rustical_dav::resources::RootResourceService; use rustical_store::auth::middleware::AuthenticationLayer; -use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::auth::{AuthenticationProvider, Principal}; use rustical_store::{CalendarStore, SubscriptionStore}; use std::sync::Arc; @@ -44,7 +44,7 @@ pub fn caldav_router::new(principal_service.clone()) + RootResourceService::<_, Principal, CalDavPrincipalUri>::new(principal_service.clone()) .axum_router() .layer(AuthenticationLayer::new(auth_provider)) .layer(Extension(CalDavPrincipalUri(prefix))), diff --git a/crates/caldav/src/principal/mod.rs b/crates/caldav/src/principal/mod.rs index ae1f16e..cb300c3 100644 --- a/crates/caldav/src/principal/mod.rs +++ b/crates/caldav/src/principal/mod.rs @@ -5,7 +5,7 @@ use rustical_dav::resource::{PrincipalUri, Resource, ResourceName}; use rustical_dav::xml::{ GroupMemberSet, GroupMembership, Resourcetype, ResourcetypeInner, SupportedReportSet, }; -use rustical_store::auth::User; +use rustical_store::auth::Principal; mod service; pub use service::*; @@ -14,7 +14,7 @@ pub use prop::*; #[derive(Clone)] pub struct PrincipalResource { - principal: User, + principal: Principal, members: Vec, } @@ -27,7 +27,7 @@ impl ResourceName for PrincipalResource { impl Resource for PrincipalResource { type Prop = PrincipalPropWrapper; type Error = Error; - type Principal = User; + type Principal = Principal; fn is_collection(&self) -> bool { true @@ -48,7 +48,7 @@ impl Resource for PrincipalResource { fn get_prop( &self, puri: &impl PrincipalUri, - user: &User, + user: &Principal, prop: &PrincipalPropWrapperName, ) -> Result { let principal_url = puri.principal_uri(&self.principal.id); @@ -113,7 +113,7 @@ impl Resource for PrincipalResource { Some(&self.principal.id) } - fn get_user_privileges(&self, user: &User) -> Result { + fn get_user_privileges(&self, user: &Principal) -> Result { Ok(UserPrivilegeSet::owner_read( user.is_principal(&self.principal.id), )) diff --git a/crates/caldav/src/principal/prop.rs b/crates/caldav/src/principal/prop.rs index 56c1d9c..6bd16a5 100644 --- a/crates/caldav/src/principal/prop.rs +++ b/crates/caldav/src/principal/prop.rs @@ -2,7 +2,7 @@ use rustical_dav::{ extensions::CommonPropertiesProp, xml::{GroupMemberSet, GroupMembership, HrefElement, SupportedReportSet}, }; -use rustical_store::auth::user::PrincipalType; +use rustical_store::auth::PrincipalType; use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; use strum_macros::VariantArray; diff --git a/crates/caldav/src/principal/service.rs b/crates/caldav/src/principal/service.rs index e8b72ef..e1f198d 100644 --- a/crates/caldav/src/principal/service.rs +++ b/crates/caldav/src/principal/service.rs @@ -5,7 +5,7 @@ use crate::{CalDavPrincipalUri, Error}; use async_trait::async_trait; use axum::Router; use rustical_dav::resource::{AxumMethods, ResourceService}; -use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::auth::{AuthenticationProvider, Principal}; use rustical_store::{CalendarStore, SubscriptionStore}; use std::sync::Arc; @@ -40,7 +40,7 @@ impl Resour type MemberType = CalendarResource; type Resource = PrincipalResource; type Error = Error; - type Principal = User; + type Principal = Principal; type PrincipalUri = CalDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, calendar-access, calendar-proxy"; diff --git a/crates/carddav/src/address_object/methods.rs b/crates/carddav/src/address_object/methods.rs index 5d76e3e..4a54f27 100644 --- a/crates/carddav/src/address_object/methods.rs +++ b/crates/carddav/src/address_object/methods.rs @@ -12,7 +12,7 @@ use rustical_dav::privileges::UserPrivilege; use rustical_dav::resource::Resource; use rustical_ical::AddressObject; use rustical_store::AddressbookStore; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use std::str::FromStr; use tracing::instrument; @@ -24,7 +24,7 @@ pub async fn get_object( object_id, }): Path, State(AddressObjectResourceService { addr_store }): State>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&principal) { return Err(Error::Unauthorized); @@ -60,7 +60,7 @@ pub async fn put_object( object_id, }): Path, State(AddressObjectResourceService { addr_store }): State>, - user: User, + user: Principal, mut if_none_match: Option>, header_map: HeaderMap, body: String, diff --git a/crates/carddav/src/address_object/resource.rs b/crates/carddav/src/address_object/resource.rs index 783c4e3..490a74d 100644 --- a/crates/carddav/src/address_object/resource.rs +++ b/crates/carddav/src/address_object/resource.rs @@ -13,7 +13,7 @@ use rustical_dav::{ xml::Resourcetype, }; use rustical_ical::AddressObject; -use rustical_store::auth::User; +use rustical_store::auth::Principal; #[derive(Clone, From, Into)] pub struct AddressObjectResource { @@ -30,7 +30,7 @@ impl ResourceName for AddressObjectResource { impl Resource for AddressObjectResource { type Prop = AddressObjectPropWrapper; type Error = Error; - type Principal = User; + type Principal = Principal; fn is_collection(&self) -> bool { false @@ -43,7 +43,7 @@ impl Resource for AddressObjectResource { fn get_prop( &self, puri: &impl PrincipalUri, - user: &User, + user: &Principal, prop: &AddressObjectPropWrapperName, ) -> Result { Ok(match prop { @@ -78,7 +78,7 @@ impl Resource for AddressObjectResource { Some(self.object.get_etag()) } - fn get_user_privileges(&self, user: &User) -> Result { + fn get_user_privileges(&self, user: &Principal) -> Result { Ok(UserPrivilegeSet::owner_only( user.is_principal(&self.principal), )) diff --git a/crates/carddav/src/address_object/service.rs b/crates/carddav/src/address_object/service.rs index f81754f..1d38df5 100644 --- a/crates/carddav/src/address_object/service.rs +++ b/crates/carddav/src/address_object/service.rs @@ -5,7 +5,7 @@ use axum::{extract::Request, handler::Handler, response::Response}; use derive_more::derive::Constructor; use futures_util::future::BoxFuture; use rustical_dav::resource::{AxumMethods, ResourceService}; -use rustical_store::{AddressbookStore, auth::User}; +use rustical_store::{AddressbookStore, auth::Principal}; use serde::{Deserialize, Deserializer}; use std::{convert::Infallible, sync::Arc}; use tower::Service; @@ -37,7 +37,7 @@ impl ResourceService for AddressObjectResourceService type Resource = AddressObjectResource; type MemberType = AddressObjectResource; type Error = Error; - type Principal = User; + type Principal = Principal; type PrincipalUri = CardDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, addressbook"; diff --git a/crates/carddav/src/addressbook/methods/get.rs b/crates/carddav/src/addressbook/methods/get.rs index 9df2d97..994f506 100644 --- a/crates/carddav/src/addressbook/methods/get.rs +++ b/crates/carddav/src/addressbook/methods/get.rs @@ -10,7 +10,7 @@ use percent_encoding::{CONTROLS, utf8_percent_encode}; use rustical_dav::privileges::UserPrivilege; use rustical_dav::resource::Resource; use rustical_ical::AddressObject; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use rustical_store::{AddressbookStore, SubscriptionStore}; use std::str::FromStr; use tracing::instrument; @@ -19,7 +19,7 @@ use tracing::instrument; pub async fn route_get( Path((principal, addressbook_id)): Path<(String, String)>, State(AddressbookResourceService { addr_store, .. }): State>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&principal) { return Err(Error::Unauthorized); diff --git a/crates/carddav/src/addressbook/methods/mkcol.rs b/crates/carddav/src/addressbook/methods/mkcol.rs index 61c6654..e1fbc2e 100644 --- a/crates/carddav/src/addressbook/methods/mkcol.rs +++ b/crates/carddav/src/addressbook/methods/mkcol.rs @@ -4,7 +4,7 @@ use axum::{ response::{IntoResponse, Response}, }; use http::StatusCode; -use rustical_store::{Addressbook, AddressbookStore, SubscriptionStore, auth::User}; +use rustical_store::{Addressbook, AddressbookStore, SubscriptionStore, auth::Principal}; use rustical_xml::{XmlDeserialize, XmlDocument, XmlRootTag}; use tracing::instrument; @@ -44,7 +44,7 @@ struct MkcolRequest { #[instrument(skip(addr_store))] pub async fn route_mkcol( Path((principal, addressbook_id)): Path<(String, String)>, - user: User, + user: Principal, State(AddressbookResourceService { addr_store, .. }): State>, body: String, ) -> Result { diff --git a/crates/carddav/src/addressbook/methods/post.rs b/crates/carddav/src/addressbook/methods/post.rs index 795865b..de6b9ec 100644 --- a/crates/carddav/src/addressbook/methods/post.rs +++ b/crates/carddav/src/addressbook/methods/post.rs @@ -7,7 +7,7 @@ use http::{HeaderMap, HeaderValue, StatusCode, header}; use rustical_dav::privileges::UserPrivilege; use rustical_dav::resource::Resource; use rustical_dav_push::register::PushRegister; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use rustical_store::{AddressbookStore, Subscription, SubscriptionStore}; use rustical_xml::XmlDocument; use tracing::instrument; @@ -15,7 +15,7 @@ use tracing::instrument; #[instrument(skip(resource_service))] pub async fn route_post( Path((principal, addr_id)): Path<(String, String)>, - user: User, + user: Principal, State(resource_service): State>, body: String, ) -> Result { diff --git a/crates/carddav/src/addressbook/methods/put.rs b/crates/carddav/src/addressbook/methods/put.rs index b632fcc..098c86a 100644 --- a/crates/carddav/src/addressbook/methods/put.rs +++ b/crates/carddav/src/addressbook/methods/put.rs @@ -9,14 +9,14 @@ use http::StatusCode; use ical::VcardParser; use rustical_ical::AddressObject; use rustical_store::Addressbook; -use rustical_store::{AddressbookStore, SubscriptionStore, auth::User}; +use rustical_store::{AddressbookStore, SubscriptionStore, auth::Principal}; use tracing::instrument; #[instrument(skip(addr_store))] pub async fn route_put( Path((principal, addressbook_id)): Path<(String, String)>, State(AddressbookResourceService { addr_store, .. }): State>, - user: User, + user: Principal, body: String, ) -> Result { if !user.is_principal(&principal) { diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs index 4c0da9e..49d7eaa 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs @@ -10,7 +10,7 @@ use rustical_dav::{ xml::{MultistatusElement, PropfindType, multistatus::ResponseElement}, }; use rustical_ical::AddressObject; -use rustical_store::{AddressbookStore, auth::User}; +use rustical_store::{AddressbookStore, auth::Principal}; use rustical_xml::XmlDeserialize; #[derive(XmlDeserialize, Clone, Debug, PartialEq)] @@ -63,7 +63,7 @@ pub async fn handle_addressbook_multiget( prop: &PropfindType, path: &str, puri: &impl PrincipalUri, - user: &User, + user: &Principal, principal: &str, cal_id: &str, addr_store: &AS, diff --git a/crates/carddav/src/addressbook/methods/report/mod.rs b/crates/carddav/src/addressbook/methods/report/mod.rs index 3ace036..a242783 100644 --- a/crates/carddav/src/addressbook/methods/report/mod.rs +++ b/crates/carddav/src/addressbook/methods/report/mod.rs @@ -9,7 +9,7 @@ use axum::{ response::IntoResponse, }; use rustical_dav::xml::{PropfindType, sync_collection::SyncCollectionRequest}; -use rustical_store::{AddressbookStore, SubscriptionStore, auth::User}; +use rustical_store::{AddressbookStore, SubscriptionStore, auth::Principal}; use rustical_xml::{XmlDeserialize, XmlDocument}; use sync_collection::handle_sync_collection; use tracing::instrument; @@ -37,7 +37,7 @@ impl ReportRequest { #[instrument(skip(addr_store))] pub async fn route_report_addressbook( Path((principal, addressbook_id)): Path<(String, String)>, - user: User, + user: Principal, OriginalUri(uri): OriginalUri, Extension(puri): Extension, State(AddressbookResourceService { addr_store, .. }): State>, diff --git a/crates/carddav/src/addressbook/methods/report/sync_collection.rs b/crates/carddav/src/addressbook/methods/report/sync_collection.rs index 25a15dc..b4dfd33 100644 --- a/crates/carddav/src/addressbook/methods/report/sync_collection.rs +++ b/crates/carddav/src/addressbook/methods/report/sync_collection.rs @@ -13,7 +13,7 @@ use rustical_dav::{ }; use rustical_store::{ AddressbookStore, - auth::User, + auth::Principal, synctoken::{format_synctoken, parse_synctoken}, }; @@ -21,7 +21,7 @@ pub async fn handle_sync_collection( sync_collection: &SyncCollectionRequest, path: &str, puri: &impl PrincipalUri, - user: &User, + user: &Principal, principal: &str, addressbook_id: &str, addr_store: &AS, diff --git a/crates/carddav/src/addressbook/resource.rs b/crates/carddav/src/addressbook/resource.rs index 752bddd..411698c 100644 --- a/crates/carddav/src/addressbook/resource.rs +++ b/crates/carddav/src/addressbook/resource.rs @@ -10,7 +10,7 @@ use rustical_dav::resource::{PrincipalUri, Resource, ResourceName}; use rustical_dav::xml::{Resourcetype, ResourcetypeInner, SupportedReportSet}; use rustical_dav_push::DavPushExtension; use rustical_store::Addressbook; -use rustical_store::auth::User; +use rustical_store::auth::Principal; #[derive(Clone, Debug, From, Into)] pub struct AddressbookResource(pub(crate) Addressbook); @@ -36,7 +36,7 @@ impl DavPushExtension for AddressbookResource { impl Resource for AddressbookResource { type Prop = AddressbookPropWrapper; type Error = Error; - type Principal = User; + type Principal = Principal; fn is_collection(&self) -> bool { true @@ -52,7 +52,7 @@ impl Resource for AddressbookResource { fn get_prop( &self, puri: &impl PrincipalUri, - user: &User, + user: &Principal, prop: &AddressbookPropWrapperName, ) -> Result { Ok(match prop { @@ -138,7 +138,7 @@ impl Resource for AddressbookResource { Some(&self.0.principal) } - fn get_user_privileges(&self, user: &User) -> Result { + fn get_user_privileges(&self, user: &Principal) -> Result { Ok(UserPrivilegeSet::owner_only( user.is_principal(&self.0.principal), )) diff --git a/crates/carddav/src/addressbook/service.rs b/crates/carddav/src/addressbook/service.rs index 4ce2911..d1d9d89 100644 --- a/crates/carddav/src/addressbook/service.rs +++ b/crates/carddav/src/addressbook/service.rs @@ -14,7 +14,7 @@ use axum::handler::Handler; use axum::response::Response; use futures_util::future::BoxFuture; use rustical_dav::resource::{AxumMethods, ResourceService}; -use rustical_store::auth::User; +use rustical_store::auth::Principal; use rustical_store::{AddressbookStore, SubscriptionStore}; use std::convert::Infallible; use std::sync::Arc; @@ -51,7 +51,7 @@ impl ResourceService type PathComponents = (String, String); // principal, addressbook_id type Resource = AddressbookResource; type Error = Error; - type Principal = User; + type Principal = Principal; type PrincipalUri = CardDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, addressbook, webdav-push"; diff --git a/crates/carddav/src/lib.rs b/crates/carddav/src/lib.rs index 5cfbc5f..1cb8f54 100644 --- a/crates/carddav/src/lib.rs +++ b/crates/carddav/src/lib.rs @@ -9,7 +9,7 @@ use rustical_dav::resources::RootResourceService; use rustical_store::auth::middleware::AuthenticationLayer; use rustical_store::{ AddressbookStore, SubscriptionStore, - auth::{AuthenticationProvider, User}, + auth::{AuthenticationProvider, Principal}, }; use std::sync::Arc; @@ -44,10 +44,12 @@ pub fn carddav_router::new(principal_service.clone()) - .axum_router() - .layer(AuthenticationLayer::new(auth_provider)) - .layer(Extension(CardDavPrincipalUri(prefix))), + RootResourceService::<_, Principal, CardDavPrincipalUri>::new( + principal_service.clone(), + ) + .axum_router() + .layer(AuthenticationLayer::new(auth_provider)) + .layer(Extension(CardDavPrincipalUri(prefix))), ) .route( "/.well-known/carddav", diff --git a/crates/carddav/src/principal/mod.rs b/crates/carddav/src/principal/mod.rs index 27c3955..0f0fdf2 100644 --- a/crates/carddav/src/principal/mod.rs +++ b/crates/carddav/src/principal/mod.rs @@ -5,7 +5,7 @@ use rustical_dav::resource::{PrincipalUri, Resource, ResourceName}; use rustical_dav::xml::{ GroupMemberSet, GroupMembership, HrefElement, Resourcetype, ResourcetypeInner, }; -use rustical_store::auth::User; +use rustical_store::auth::Principal; mod service; pub use service::*; @@ -14,7 +14,7 @@ pub use prop::*; #[derive(Debug, Clone)] pub struct PrincipalResource { - principal: User, + principal: Principal, members: Vec, } @@ -27,7 +27,7 @@ impl ResourceName for PrincipalResource { impl Resource for PrincipalResource { type Prop = PrincipalPropWrapper; type Error = Error; - type Principal = User; + type Principal = Principal; fn is_collection(&self) -> bool { true @@ -43,7 +43,7 @@ impl Resource for PrincipalResource { fn get_prop( &self, puri: &impl PrincipalUri, - user: &User, + user: &Principal, prop: &PrincipalPropWrapperName, ) -> Result { let principal_href = HrefElement::new(puri.principal_uri(&self.principal.id)); @@ -99,7 +99,7 @@ impl Resource for PrincipalResource { Some(&self.principal.id) } - fn get_user_privileges(&self, user: &User) -> Result { + fn get_user_privileges(&self, user: &Principal) -> Result { Ok(UserPrivilegeSet::owner_only( user.is_principal(&self.principal.id), )) diff --git a/crates/carddav/src/principal/service.rs b/crates/carddav/src/principal/service.rs index d607f0f..6be078e 100644 --- a/crates/carddav/src/principal/service.rs +++ b/crates/carddav/src/principal/service.rs @@ -5,7 +5,7 @@ use crate::{CardDavPrincipalUri, Error}; use async_trait::async_trait; use axum::Router; use rustical_dav::resource::{AxumMethods, ResourceService}; -use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::auth::{AuthenticationProvider, Principal}; use rustical_store::{AddressbookStore, SubscriptionStore}; use std::sync::Arc; @@ -51,7 +51,7 @@ impl Reso type MemberType = AddressbookResource; type Resource = PrincipalResource; type Error = Error; - type Principal = User; + type Principal = Principal; type PrincipalUri = CardDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, addressbook"; diff --git a/crates/frontend/src/nextcloud_login/routes.rs b/crates/frontend/src/nextcloud_login/routes.rs index 991cb0a..3510a75 100644 --- a/crates/frontend/src/nextcloud_login/routes.rs +++ b/crates/frontend/src/nextcloud_login/routes.rs @@ -13,7 +13,7 @@ use axum_extra::{TypedHeader, extract::Host}; use chrono::{Duration, Utc}; use headers::UserAgent; use http::StatusCode; -use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::auth::{AuthenticationProvider, Principal}; use serde::{Deserialize, Serialize}; use std::sync::Arc; use tracing::instrument; @@ -101,7 +101,7 @@ struct NextcloudLoginPage { pub(crate) async fn get_nextcloud_flow( Extension(state): Extension>, Path(flow_id): Path, - user: User, + user: Principal, ) -> Result { if let Some(flow) = state.flows.read().await.get(&flow_id) { Ok(Html( @@ -131,7 +131,7 @@ struct NextcloudLoginSuccessPage { #[instrument(skip(state))] pub(crate) async fn post_nextcloud_flow( - user: User, + user: Principal, Extension(state): Extension>, Path(flow_id): Path, Host(host): Host, diff --git a/crates/frontend/src/oidc_user_store.rs b/crates/frontend/src/oidc_user_store.rs index 24bcd8f..e40c7d8 100644 --- a/crates/frontend/src/oidc_user_store.rs +++ b/crates/frontend/src/oidc_user_store.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use async_trait::async_trait; use rustical_oidc::UserStore; -use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::auth::{AuthenticationProvider, Principal}; pub struct OidcUserStore(pub Arc); @@ -23,7 +23,7 @@ impl UserStore for OidcUserStore { async fn insert_user(&self, id: &str) -> Result<(), Self::Error> { self.0 .insert_principal( - User { + Principal { id: id.to_owned(), displayname: None, principal_type: Default::default(), diff --git a/crates/frontend/src/routes/addressbook.rs b/crates/frontend/src/routes/addressbook.rs index 1cd47f8..cf01891 100644 --- a/crates/frontend/src/routes/addressbook.rs +++ b/crates/frontend/src/routes/addressbook.rs @@ -10,7 +10,7 @@ use axum::{ use axum_extra::TypedHeader; use headers::Referer; use http::StatusCode; -use rustical_store::{Addressbook, AddressbookStore, auth::User}; +use rustical_store::{Addressbook, AddressbookStore, auth::Principal}; #[derive(Template, WebTemplate)] #[template(path = "pages/addressbook.html")] @@ -21,7 +21,7 @@ struct AddressbookPage { pub async fn route_addressbook( Path((owner, addrbook_id)): Path<(String, String)>, Extension(store): Extension>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&owner) { return Ok(StatusCode::UNAUTHORIZED.into_response()); @@ -35,7 +35,7 @@ pub async fn route_addressbook( pub async fn route_addressbook_restore( Path((owner, addressbook_id)): Path<(String, String)>, Extension(store): Extension>, - user: User, + user: Principal, referer: Option>, ) -> Result { if !user.is_principal(&owner) { @@ -51,7 +51,7 @@ pub async fn route_addressbook_restore( pub async fn route_delete_addressbook( Path((owner, addressbook_id)): Path<(String, String)>, Extension(store): Extension>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&owner) { return Ok(StatusCode::UNAUTHORIZED.into_response()); diff --git a/crates/frontend/src/routes/app_token.rs b/crates/frontend/src/routes/app_token.rs index 56c7a22..7fbec2b 100644 --- a/crates/frontend/src/routes/app_token.rs +++ b/crates/frontend/src/routes/app_token.rs @@ -12,7 +12,7 @@ use headers::{ContentType, HeaderMapExt}; use http::{HeaderValue, StatusCode, header}; use percent_encoding::{CONTROLS, utf8_percent_encode}; use rand::{Rng, distr::Alphanumeric}; -use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::auth::{AuthenticationProvider, Principal}; use serde::Deserialize; use uuid::Uuid; @@ -47,7 +47,7 @@ pub(crate) struct PostAppTokenForm { } pub async fn route_post_app_token( - user: User, + user: Principal, Extension(auth_provider): Extension>, Path(user_id): Path, Host(hostname): Host, @@ -96,7 +96,7 @@ pub async fn route_post_app_token( } pub async fn route_delete_app_token( - user: User, + user: Principal, Extension(auth_provider): Extension>, Path((user_id, token_id)): Path<(String, String)>, ) -> Result { diff --git a/crates/frontend/src/routes/calendar.rs b/crates/frontend/src/routes/calendar.rs index a6c2921..bb5f899 100644 --- a/crates/frontend/src/routes/calendar.rs +++ b/crates/frontend/src/routes/calendar.rs @@ -10,7 +10,7 @@ use axum::{ use axum_extra::TypedHeader; use headers::Referer; use http::StatusCode; -use rustical_store::{Calendar, CalendarStore, auth::User}; +use rustical_store::{Calendar, CalendarStore, auth::Principal}; #[derive(Template, WebTemplate)] #[template(path = "pages/calendar.html")] @@ -21,7 +21,7 @@ struct CalendarPage { pub async fn route_calendar( Path((owner, cal_id)): Path<(String, String)>, Extension(store): Extension>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&owner) { return Ok(StatusCode::UNAUTHORIZED.into_response()); @@ -35,7 +35,7 @@ pub async fn route_calendar( pub async fn route_calendar_restore( Path((owner, cal_id)): Path<(String, String)>, Extension(store): Extension>, - user: User, + user: Principal, referer: Option>, ) -> Result { if !user.is_principal(&owner) { @@ -51,7 +51,7 @@ pub async fn route_calendar_restore( pub async fn route_delete_calendar( Path((owner, cal_id)): Path<(String, String)>, Extension(store): Extension>, - user: User, + user: Principal, ) -> Result { if !user.is_principal(&owner) { return Ok(StatusCode::UNAUTHORIZED.into_response()); diff --git a/crates/frontend/src/routes/user.rs b/crates/frontend/src/routes/user.rs index 8c40b86..fb45cc8 100644 --- a/crates/frontend/src/routes/user.rs +++ b/crates/frontend/src/routes/user.rs @@ -12,13 +12,13 @@ use headers::UserAgent; use http::StatusCode; use rustical_store::{ Addressbook, AddressbookStore, Calendar, CalendarStore, - auth::{AuthenticationProvider, User, user::AppToken}, + auth::{AppToken, AuthenticationProvider, Principal}, }; #[derive(Template, WebTemplate)] #[template(path = "pages/user.html")] pub struct UserPage { - pub user: User, + pub user: Principal, pub app_tokens: Vec, pub calendars: Vec, pub deleted_calendars: Vec, @@ -39,7 +39,7 @@ pub async fn route_user_named< Extension(auth_provider): Extension>, TypedHeader(user_agent): TypedHeader, Host(host): Host, - user: User, + user: Principal, ) -> impl IntoResponse { if user_id != user.id { return StatusCode::UNAUTHORIZED.into_response(); @@ -81,11 +81,11 @@ pub async fn route_user_named< .into_response() } -pub async fn route_get_home(user: User) -> Redirect { +pub async fn route_get_home(user: Principal) -> Redirect { Redirect::to(&format!("/frontend/user/{}", user.id)) } -pub async fn route_root(user: Option) -> Redirect { +pub async fn route_root(user: Option) -> Redirect { match user { Some(user) => route_get_home(user).await, None => Redirect::to("/frontend/login"), diff --git a/crates/store/src/auth/mod.rs b/crates/store/src/auth/mod.rs index ae9ccaf..1b99c4d 100644 --- a/crates/store/src/auth/mod.rs +++ b/crates/store/src/auth/mod.rs @@ -1,17 +1,26 @@ pub mod middleware; -pub mod user; +mod principal; use crate::error::Error; use async_trait::async_trait; +pub use principal::{AppToken, Principal, PrincipalType}; + #[async_trait] pub trait AuthenticationProvider: Send + Sync + 'static { - async fn get_principals(&self) -> Result, crate::Error>; - async fn get_principal(&self, id: &str) -> Result, crate::Error>; + async fn get_principals(&self) -> Result, crate::Error>; + async fn get_principal(&self, id: &str) -> Result, crate::Error>; async fn remove_principal(&self, id: &str) -> Result<(), crate::Error>; - async fn insert_principal(&self, user: User, overwrite: bool) -> Result<(), crate::Error>; - async fn validate_password(&self, user_id: &str, password: &str) - -> Result, Error>; - async fn validate_app_token(&self, user_id: &str, token: &str) -> Result, Error>; + async fn insert_principal(&self, user: Principal, overwrite: bool) -> Result<(), crate::Error>; + async fn validate_password( + &self, + user_id: &str, + password: &str, + ) -> Result, Error>; + async fn validate_app_token( + &self, + user_id: &str, + token: &str, + ) -> Result, Error>; /// Returns a token identifier async fn add_app_token( &self, @@ -28,5 +37,3 @@ pub trait AuthenticationProvider: Send + Sync + 'static { } pub use middleware::AuthenticationMiddleware; -use user::AppToken; -pub use user::User; diff --git a/crates/store/src/auth/user.rs b/crates/store/src/auth/principal.rs similarity index 94% rename from crates/store/src/auth/user.rs rename to crates/store/src/auth/principal.rs index 284cc23..de15a1b 100644 --- a/crates/store/src/auth/user.rs +++ b/crates/store/src/auth/principal.rs @@ -78,8 +78,7 @@ pub struct AppToken { #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(deny_unknown_fields)] -// TODO: Rename this to Principal -pub struct User { +pub struct Principal { pub id: String, pub displayname: Option, #[serde(default)] @@ -89,7 +88,7 @@ pub struct User { pub memberships: Vec, } -impl User { +impl Principal { /// Returns true if the user is either /// - the principal itself /// - has full access to the prinicpal (is member) @@ -114,7 +113,7 @@ impl User { } } -impl rustical_dav::Principal for User { +impl rustical_dav::Principal for Principal { fn get_id(&self) -> &str { &self.id } @@ -134,7 +133,7 @@ impl IntoResponse for UnauthorizedError { } } -impl FromRequestParts for User { +impl FromRequestParts for Principal { type Rejection = UnauthorizedError; async fn from_request_parts( @@ -149,7 +148,7 @@ impl FromRequestParts for User { } } -impl OptionalFromRequestParts for User { +impl OptionalFromRequestParts for Principal { type Rejection = Infallible; async fn from_request_parts( diff --git a/crates/store_sqlite/src/principal_store.rs b/crates/store_sqlite/src/principal_store.rs index bdd6627..72f9337 100644 --- a/crates/store_sqlite/src/principal_store.rs +++ b/crates/store_sqlite/src/principal_store.rs @@ -7,7 +7,7 @@ use pbkdf2::{ }; use rustical_store::{ Error, Secret, - auth::{AuthenticationProvider, User, user::AppToken}, + auth::{AppToken, AuthenticationProvider, Principal}, }; use sqlx::{SqlitePool, types::Json}; use tracing::instrument; @@ -21,11 +21,11 @@ struct PrincipalRow { memberships: Option>>>, } -impl TryFrom for User { +impl TryFrom for Principal { type Error = Error; fn try_from(value: PrincipalRow) -> Result { - Ok(User { + Ok(Principal { id: value.id, displayname: value.displayname, password: value.password_hash.map(Secret::from), @@ -49,8 +49,8 @@ pub struct SqlitePrincipalStore { #[async_trait] impl AuthenticationProvider for SqlitePrincipalStore { #[instrument] - async fn get_principals(&self) -> Result, Error> { - let result: Result, Error> = sqlx::query_as!( + async fn get_principals(&self) -> Result, Error> { + let result: Result, Error> = sqlx::query_as!( PrincipalRow, r#" SELECT id, displayname, principal_type, password_hash, json_group_array(member_of) AS "memberships: Json>>" @@ -63,13 +63,13 @@ impl AuthenticationProvider for SqlitePrincipalStore { .await .map_err(crate::Error::from)? .into_iter() - .map(User::try_from) + .map(Principal::try_from) .collect(); Ok(result?) } #[instrument] - async fn get_principal(&self, id: &str) -> Result, Error> { + async fn get_principal(&self, id: &str) -> Result, Error> { let row= sqlx::query_as!( PrincipalRow, r#" @@ -83,7 +83,7 @@ impl AuthenticationProvider for SqlitePrincipalStore { .fetch_optional(&self.db) .await .map_err(crate::Error::from)? - .map(User::try_from); + .map(Principal::try_from); if let Some(row) = row { Ok(Some(row?)) } else { @@ -103,7 +103,7 @@ impl AuthenticationProvider for SqlitePrincipalStore { #[instrument] async fn insert_principal( &self, - user: User, + user: Principal, overwrite: bool, ) -> Result<(), rustical_store::Error> { // Would be cleaner to put this into a transaction but for now it will be fine @@ -142,7 +142,11 @@ impl AuthenticationProvider for SqlitePrincipalStore { } #[instrument(skip(token))] - async fn validate_app_token(&self, user_id: &str, token: &str) -> Result, Error> { + async fn validate_app_token( + &self, + user_id: &str, + token: &str, + ) -> Result, Error> { for app_token in &self.get_app_tokens(user_id).await? { if password_auth::verify_password(token, app_token.token.as_ref()).is_ok() { return self.get_principal(user_id).await; @@ -169,8 +173,8 @@ impl AuthenticationProvider for SqlitePrincipalStore { &self, user_id: &str, password_input: &str, - ) -> Result, Error> { - let user: User = match self.get_principal(user_id).await? { + ) -> Result, Error> { + let user: Principal = match self.get_principal(user_id).await? { Some(user) => user, None => return Ok(None), }; diff --git a/src/commands/principals.rs b/src/commands/principals.rs index 2d5ae0e..88e41e2 100644 --- a/src/commands/principals.rs +++ b/src/commands/principals.rs @@ -6,7 +6,7 @@ use figment::{ providers::{Env, Format, Toml}, }; use password_hash::{PasswordHasher, SaltString, rand_core::OsRng}; -use rustical_store::auth::{AuthenticationProvider, User, user::PrincipalType}; +use rustical_store::auth::{AuthenticationProvider, Principal, PrincipalType}; #[derive(Parser, Debug)] pub struct PrincipalsArgs { @@ -99,7 +99,7 @@ pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> { }; principal_store .insert_principal( - User { + Principal { id, displayname: name, principal_type: principal_type.unwrap_or_default(),