mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 14:42:30 +00:00
Rename User struct to Principal
This commit is contained in:
@@ -9,7 +9,7 @@ use ical::generator::{Emitter, IcalCalendarBuilder};
|
|||||||
use ical::property::Property;
|
use ical::property::Property;
|
||||||
use percent_encoding::{CONTROLS, utf8_percent_encode};
|
use percent_encoding::{CONTROLS, utf8_percent_encode};
|
||||||
use rustical_ical::{CalendarObjectComponent, EventObject, JournalObject, TodoObject};
|
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::collections::HashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -18,7 +18,7 @@ use tracing::instrument;
|
|||||||
pub async fn route_get<C: CalendarStore, S: SubscriptionStore>(
|
pub async fn route_get<C: CalendarStore, S: SubscriptionStore>(
|
||||||
Path((principal, calendar_id)): Path<(String, String)>,
|
Path((principal, calendar_id)): Path<(String, String)>,
|
||||||
State(CalendarResourceService { cal_store, .. }): State<CalendarResourceService<C, S>>,
|
State(CalendarResourceService { cal_store, .. }): State<CalendarResourceService<C, S>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
if !user.is_principal(&principal) {
|
if !user.is_principal(&principal) {
|
||||||
return Err(crate::Error::Unauthorized);
|
return Err(crate::Error::Unauthorized);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use axum::response::{IntoResponse, Response};
|
|||||||
use http::{Method, StatusCode};
|
use http::{Method, StatusCode};
|
||||||
use rustical_dav::xml::HrefElement;
|
use rustical_dav::xml::HrefElement;
|
||||||
use rustical_ical::CalendarObjectType;
|
use rustical_ical::CalendarObjectType;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use rustical_store::{Calendar, CalendarStore, SubscriptionStore};
|
use rustical_store::{Calendar, CalendarStore, SubscriptionStore};
|
||||||
use rustical_xml::{Unparsed, XmlDeserialize, XmlDocument, XmlRootTag};
|
use rustical_xml::{Unparsed, XmlDeserialize, XmlDocument, XmlRootTag};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -63,7 +63,7 @@ struct MkcolRequest {
|
|||||||
#[instrument(skip(cal_store))]
|
#[instrument(skip(cal_store))]
|
||||||
pub async fn route_mkcalendar<C: CalendarStore, S: SubscriptionStore>(
|
pub async fn route_mkcalendar<C: CalendarStore, S: SubscriptionStore>(
|
||||||
Path((principal, cal_id)): Path<(String, String)>,
|
Path((principal, cal_id)): Path<(String, String)>,
|
||||||
user: User,
|
user: Principal,
|
||||||
State(CalendarResourceService { cal_store, .. }): State<CalendarResourceService<C, S>>,
|
State(CalendarResourceService { cal_store, .. }): State<CalendarResourceService<C, S>>,
|
||||||
method: Method,
|
method: Method,
|
||||||
body: String,
|
body: String,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use http::{HeaderMap, HeaderValue, StatusCode, header};
|
|||||||
use rustical_dav::privileges::UserPrivilege;
|
use rustical_dav::privileges::UserPrivilege;
|
||||||
use rustical_dav::resource::Resource;
|
use rustical_dav::resource::Resource;
|
||||||
use rustical_dav_push::register::PushRegister;
|
use rustical_dav_push::register::PushRegister;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use rustical_store::{CalendarStore, Subscription, SubscriptionStore};
|
use rustical_store::{CalendarStore, Subscription, SubscriptionStore};
|
||||||
use rustical_xml::XmlDocument;
|
use rustical_xml::XmlDocument;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -15,7 +15,7 @@ use tracing::instrument;
|
|||||||
#[instrument(skip(resource_service))]
|
#[instrument(skip(resource_service))]
|
||||||
pub async fn route_post<C: CalendarStore, S: SubscriptionStore>(
|
pub async fn route_post<C: CalendarStore, S: SubscriptionStore>(
|
||||||
Path((principal, cal_id)): Path<(String, String)>,
|
Path((principal, cal_id)): Path<(String, String)>,
|
||||||
user: User,
|
user: Principal,
|
||||||
State(resource_service): State<CalendarResourceService<C, S>>,
|
State(resource_service): State<CalendarResourceService<C, S>>,
|
||||||
body: String,
|
body: String,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use rustical_dav::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use rustical_ical::CalendarObject;
|
use rustical_ical::CalendarObject;
|
||||||
use rustical_store::{CalendarStore, SubscriptionStore, auth::User};
|
use rustical_store::{CalendarStore, SubscriptionStore, auth::Principal};
|
||||||
use rustical_xml::{XmlDeserialize, XmlDocument};
|
use rustical_xml::{XmlDeserialize, XmlDocument};
|
||||||
use sync_collection::handle_sync_collection;
|
use sync_collection::handle_sync_collection;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -56,7 +56,7 @@ fn objects_response(
|
|||||||
path: &str,
|
path: &str,
|
||||||
principal: &str,
|
principal: &str,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
prop: &PropfindType<CalendarObjectPropWrapperName>,
|
prop: &PropfindType<CalendarObjectPropWrapperName>,
|
||||||
) -> Result<MultistatusElement<CalendarObjectPropWrapper, String>, Error> {
|
) -> Result<MultistatusElement<CalendarObjectPropWrapper, String>, Error> {
|
||||||
let mut responses = Vec::new();
|
let mut responses = Vec::new();
|
||||||
@@ -90,7 +90,7 @@ fn objects_response(
|
|||||||
#[instrument(skip(cal_store))]
|
#[instrument(skip(cal_store))]
|
||||||
pub async fn route_report_calendar<C: CalendarStore, S: SubscriptionStore>(
|
pub async fn route_report_calendar<C: CalendarStore, S: SubscriptionStore>(
|
||||||
Path((principal, cal_id)): Path<(String, String)>,
|
Path((principal, cal_id)): Path<(String, String)>,
|
||||||
user: User,
|
user: Principal,
|
||||||
Extension(puri): Extension<CalDavPrincipalUri>,
|
Extension(puri): Extension<CalDavPrincipalUri>,
|
||||||
State(CalendarResourceService { cal_store, .. }): State<CalendarResourceService<C, S>>,
|
State(CalendarResourceService { cal_store, .. }): State<CalendarResourceService<C, S>>,
|
||||||
OriginalUri(uri): OriginalUri,
|
OriginalUri(uri): OriginalUri,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use rustical_dav::{
|
|||||||
};
|
};
|
||||||
use rustical_store::{
|
use rustical_store::{
|
||||||
CalendarStore,
|
CalendarStore,
|
||||||
auth::User,
|
auth::Principal,
|
||||||
synctoken::{format_synctoken, parse_synctoken},
|
synctoken::{format_synctoken, parse_synctoken},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ pub async fn handle_sync_collection<C: CalendarStore>(
|
|||||||
sync_collection: &SyncCollectionRequest<CalendarObjectPropWrapperName>,
|
sync_collection: &SyncCollectionRequest<CalendarObjectPropWrapperName>,
|
||||||
path: &str,
|
path: &str,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
principal: &str,
|
principal: &str,
|
||||||
cal_id: &str,
|
cal_id: &str,
|
||||||
cal_store: &C,
|
cal_store: &C,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use rustical_dav::xml::{HrefElement, Resourcetype, ResourcetypeInner, SupportedR
|
|||||||
use rustical_dav_push::{DavPushExtension, DavPushExtensionProp};
|
use rustical_dav_push::{DavPushExtension, DavPushExtensionProp};
|
||||||
use rustical_ical::CalDateTime;
|
use rustical_ical::CalDateTime;
|
||||||
use rustical_store::Calendar;
|
use rustical_store::Calendar;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use rustical_xml::{EnumVariants, PropName};
|
use rustical_xml::{EnumVariants, PropName};
|
||||||
use rustical_xml::{XmlDeserialize, XmlSerialize};
|
use rustical_xml::{XmlDeserialize, XmlSerialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@@ -95,7 +95,7 @@ impl DavPushExtension for CalendarResource {
|
|||||||
impl Resource for CalendarResource {
|
impl Resource for CalendarResource {
|
||||||
type Prop = CalendarPropWrapper;
|
type Prop = CalendarPropWrapper;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
|
|
||||||
fn is_collection(&self) -> bool {
|
fn is_collection(&self) -> bool {
|
||||||
true
|
true
|
||||||
@@ -121,7 +121,7 @@ impl Resource for CalendarResource {
|
|||||||
fn get_prop(
|
fn get_prop(
|
||||||
&self,
|
&self,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
prop: &CalendarPropWrapperName,
|
prop: &CalendarPropWrapperName,
|
||||||
) -> Result<Self::Prop, Self::Error> {
|
) -> Result<Self::Prop, Self::Error> {
|
||||||
Ok(match prop {
|
Ok(match prop {
|
||||||
@@ -291,7 +291,7 @@ impl Resource for CalendarResource {
|
|||||||
Some(&self.cal.principal)
|
Some(&self.cal.principal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_privileges(&self, user: &User) -> Result<UserPrivilegeSet, Self::Error> {
|
fn get_user_privileges(&self, user: &Principal) -> Result<UserPrivilegeSet, Self::Error> {
|
||||||
if self.cal.subscription_url.is_some() || self.read_only {
|
if self.cal.subscription_url.is_some() || self.read_only {
|
||||||
return Ok(UserPrivilegeSet::owner_read(
|
return Ok(UserPrivilegeSet::owner_read(
|
||||||
user.is_principal(&self.cal.principal),
|
user.is_principal(&self.cal.principal),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use axum::handler::Handler;
|
|||||||
use axum::response::Response;
|
use axum::response::Response;
|
||||||
use futures_util::future::BoxFuture;
|
use futures_util::future::BoxFuture;
|
||||||
use rustical_dav::resource::{AxumMethods, ResourceService};
|
use rustical_dav::resource::{AxumMethods, ResourceService};
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use rustical_store::{CalendarStore, SubscriptionStore};
|
use rustical_store::{CalendarStore, SubscriptionStore};
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -48,7 +48,7 @@ impl<C: CalendarStore, S: SubscriptionStore> ResourceService for CalendarResourc
|
|||||||
type PathComponents = (String, String); // principal, calendar_id
|
type PathComponents = (String, String); // principal, calendar_id
|
||||||
type Resource = CalendarResource;
|
type Resource = CalendarResource;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
type PrincipalUri = CalDavPrincipalUri;
|
type PrincipalUri = CalDavPrincipalUri;
|
||||||
|
|
||||||
const DAV_HEADER: &str = "1, 3, access-control, calendar-access, calendar-proxy, webdav-push";
|
const DAV_HEADER: &str = "1, 3, access-control, calendar-access, calendar-proxy, webdav-push";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use headers::{ContentType, ETag, HeaderMapExt, IfNoneMatch};
|
|||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
use rustical_ical::CalendarObject;
|
use rustical_ical::CalendarObject;
|
||||||
use rustical_store::CalendarStore;
|
use rustical_store::CalendarStore;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ pub async fn get_event<C: CalendarStore>(
|
|||||||
object_id,
|
object_id,
|
||||||
}): Path<CalendarObjectPathComponents>,
|
}): Path<CalendarObjectPathComponents>,
|
||||||
State(CalendarObjectResourceService { cal_store }): State<CalendarObjectResourceService<C>>,
|
State(CalendarObjectResourceService { cal_store }): State<CalendarObjectResourceService<C>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
if !user.is_principal(&principal) {
|
if !user.is_principal(&principal) {
|
||||||
return Err(crate::Error::Unauthorized);
|
return Err(crate::Error::Unauthorized);
|
||||||
@@ -51,7 +51,7 @@ pub async fn put_event<C: CalendarStore>(
|
|||||||
object_id,
|
object_id,
|
||||||
}): Path<CalendarObjectPathComponents>,
|
}): Path<CalendarObjectPathComponents>,
|
||||||
State(CalendarObjectResourceService { cal_store }): State<CalendarObjectResourceService<C>>,
|
State(CalendarObjectResourceService { cal_store }): State<CalendarObjectResourceService<C>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
mut if_none_match: Option<TypedHeader<IfNoneMatch>>,
|
mut if_none_match: Option<TypedHeader<IfNoneMatch>>,
|
||||||
header_map: HeaderMap,
|
header_map: HeaderMap,
|
||||||
body: String,
|
body: String,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use rustical_dav::{
|
|||||||
xml::Resourcetype,
|
xml::Resourcetype,
|
||||||
};
|
};
|
||||||
use rustical_ical::CalendarObject;
|
use rustical_ical::CalendarObject;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
|
|
||||||
#[derive(Clone, From, Into)]
|
#[derive(Clone, From, Into)]
|
||||||
pub struct CalendarObjectResource {
|
pub struct CalendarObjectResource {
|
||||||
@@ -25,7 +25,7 @@ impl ResourceName for CalendarObjectResource {
|
|||||||
impl Resource for CalendarObjectResource {
|
impl Resource for CalendarObjectResource {
|
||||||
type Prop = CalendarObjectPropWrapper;
|
type Prop = CalendarObjectPropWrapper;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
|
|
||||||
fn is_collection(&self) -> bool {
|
fn is_collection(&self) -> bool {
|
||||||
false
|
false
|
||||||
@@ -38,7 +38,7 @@ impl Resource for CalendarObjectResource {
|
|||||||
fn get_prop(
|
fn get_prop(
|
||||||
&self,
|
&self,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
prop: &CalendarObjectPropWrapperName,
|
prop: &CalendarObjectPropWrapperName,
|
||||||
) -> Result<Self::Prop, Self::Error> {
|
) -> Result<Self::Prop, Self::Error> {
|
||||||
Ok(match prop {
|
Ok(match prop {
|
||||||
@@ -81,7 +81,7 @@ impl Resource for CalendarObjectResource {
|
|||||||
Some(self.object.get_etag())
|
Some(self.object.get_etag())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_privileges(&self, user: &User) -> Result<UserPrivilegeSet, Self::Error> {
|
fn get_user_privileges(&self, user: &Principal) -> Result<UserPrivilegeSet, Self::Error> {
|
||||||
Ok(UserPrivilegeSet::owner_only(
|
Ok(UserPrivilegeSet::owner_only(
|
||||||
user.is_principal(&self.principal),
|
user.is_principal(&self.principal),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use async_trait::async_trait;
|
|||||||
use axum::{extract::Request, handler::Handler, response::Response};
|
use axum::{extract::Request, handler::Handler, response::Response};
|
||||||
use futures_util::future::BoxFuture;
|
use futures_util::future::BoxFuture;
|
||||||
use rustical_dav::resource::{AxumMethods, ResourceService};
|
use rustical_dav::resource::{AxumMethods, ResourceService};
|
||||||
use rustical_store::{CalendarStore, auth::User};
|
use rustical_store::{CalendarStore, auth::Principal};
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
use std::{convert::Infallible, sync::Arc};
|
use std::{convert::Infallible, sync::Arc};
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
@@ -46,7 +46,7 @@ impl<C: CalendarStore> ResourceService for CalendarObjectResourceService<C> {
|
|||||||
type Resource = CalendarObjectResource;
|
type Resource = CalendarObjectResource;
|
||||||
type MemberType = CalendarObjectResource;
|
type MemberType = CalendarObjectResource;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
type PrincipalUri = CalDavPrincipalUri;
|
type PrincipalUri = CalDavPrincipalUri;
|
||||||
|
|
||||||
const DAV_HEADER: &str = "1, 3, access-control, calendar-access";
|
const DAV_HEADER: &str = "1, 3, access-control, calendar-access";
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use principal::PrincipalResourceService;
|
|||||||
use rustical_dav::resource::{PrincipalUri, ResourceService};
|
use rustical_dav::resource::{PrincipalUri, ResourceService};
|
||||||
use rustical_dav::resources::RootResourceService;
|
use rustical_dav::resources::RootResourceService;
|
||||||
use rustical_store::auth::middleware::AuthenticationLayer;
|
use rustical_store::auth::middleware::AuthenticationLayer;
|
||||||
use rustical_store::auth::{AuthenticationProvider, User};
|
use rustical_store::auth::{AuthenticationProvider, Principal};
|
||||||
use rustical_store::{CalendarStore, SubscriptionStore};
|
use rustical_store::{CalendarStore, SubscriptionStore};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ pub fn caldav_router<AP: AuthenticationProvider, C: CalendarStore, S: Subscripti
|
|||||||
Router::new()
|
Router::new()
|
||||||
.nest(
|
.nest(
|
||||||
prefix,
|
prefix,
|
||||||
RootResourceService::<_, User, CalDavPrincipalUri>::new(principal_service.clone())
|
RootResourceService::<_, Principal, CalDavPrincipalUri>::new(principal_service.clone())
|
||||||
.axum_router()
|
.axum_router()
|
||||||
.layer(AuthenticationLayer::new(auth_provider))
|
.layer(AuthenticationLayer::new(auth_provider))
|
||||||
.layer(Extension(CalDavPrincipalUri(prefix))),
|
.layer(Extension(CalDavPrincipalUri(prefix))),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use rustical_dav::resource::{PrincipalUri, Resource, ResourceName};
|
|||||||
use rustical_dav::xml::{
|
use rustical_dav::xml::{
|
||||||
GroupMemberSet, GroupMembership, Resourcetype, ResourcetypeInner, SupportedReportSet,
|
GroupMemberSet, GroupMembership, Resourcetype, ResourcetypeInner, SupportedReportSet,
|
||||||
};
|
};
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
|
|
||||||
mod service;
|
mod service;
|
||||||
pub use service::*;
|
pub use service::*;
|
||||||
@@ -14,7 +14,7 @@ pub use prop::*;
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PrincipalResource {
|
pub struct PrincipalResource {
|
||||||
principal: User,
|
principal: Principal,
|
||||||
members: Vec<String>,
|
members: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ impl ResourceName for PrincipalResource {
|
|||||||
impl Resource for PrincipalResource {
|
impl Resource for PrincipalResource {
|
||||||
type Prop = PrincipalPropWrapper;
|
type Prop = PrincipalPropWrapper;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
|
|
||||||
fn is_collection(&self) -> bool {
|
fn is_collection(&self) -> bool {
|
||||||
true
|
true
|
||||||
@@ -48,7 +48,7 @@ impl Resource for PrincipalResource {
|
|||||||
fn get_prop(
|
fn get_prop(
|
||||||
&self,
|
&self,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
prop: &PrincipalPropWrapperName,
|
prop: &PrincipalPropWrapperName,
|
||||||
) -> Result<Self::Prop, Self::Error> {
|
) -> Result<Self::Prop, Self::Error> {
|
||||||
let principal_url = puri.principal_uri(&self.principal.id);
|
let principal_url = puri.principal_uri(&self.principal.id);
|
||||||
@@ -113,7 +113,7 @@ impl Resource for PrincipalResource {
|
|||||||
Some(&self.principal.id)
|
Some(&self.principal.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_privileges(&self, user: &User) -> Result<UserPrivilegeSet, Self::Error> {
|
fn get_user_privileges(&self, user: &Principal) -> Result<UserPrivilegeSet, Self::Error> {
|
||||||
Ok(UserPrivilegeSet::owner_read(
|
Ok(UserPrivilegeSet::owner_read(
|
||||||
user.is_principal(&self.principal.id),
|
user.is_principal(&self.principal.id),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use rustical_dav::{
|
|||||||
extensions::CommonPropertiesProp,
|
extensions::CommonPropertiesProp,
|
||||||
xml::{GroupMemberSet, GroupMembership, HrefElement, SupportedReportSet},
|
xml::{GroupMemberSet, GroupMembership, HrefElement, SupportedReportSet},
|
||||||
};
|
};
|
||||||
use rustical_store::auth::user::PrincipalType;
|
use rustical_store::auth::PrincipalType;
|
||||||
use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize};
|
use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize};
|
||||||
use strum_macros::VariantArray;
|
use strum_macros::VariantArray;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::{CalDavPrincipalUri, Error};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
use rustical_dav::resource::{AxumMethods, ResourceService};
|
use rustical_dav::resource::{AxumMethods, ResourceService};
|
||||||
use rustical_store::auth::{AuthenticationProvider, User};
|
use rustical_store::auth::{AuthenticationProvider, Principal};
|
||||||
use rustical_store::{CalendarStore, SubscriptionStore};
|
use rustical_store::{CalendarStore, SubscriptionStore};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ impl<AP: AuthenticationProvider, S: SubscriptionStore, CS: CalendarStore> Resour
|
|||||||
type MemberType = CalendarResource;
|
type MemberType = CalendarResource;
|
||||||
type Resource = PrincipalResource;
|
type Resource = PrincipalResource;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
type PrincipalUri = CalDavPrincipalUri;
|
type PrincipalUri = CalDavPrincipalUri;
|
||||||
|
|
||||||
const DAV_HEADER: &str = "1, 3, access-control, calendar-access, calendar-proxy";
|
const DAV_HEADER: &str = "1, 3, access-control, calendar-access, calendar-proxy";
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use rustical_dav::privileges::UserPrivilege;
|
|||||||
use rustical_dav::resource::Resource;
|
use rustical_dav::resource::Resource;
|
||||||
use rustical_ical::AddressObject;
|
use rustical_ical::AddressObject;
|
||||||
use rustical_store::AddressbookStore;
|
use rustical_store::AddressbookStore;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ pub async fn get_object<AS: AddressbookStore>(
|
|||||||
object_id,
|
object_id,
|
||||||
}): Path<AddressObjectPathComponents>,
|
}): Path<AddressObjectPathComponents>,
|
||||||
State(AddressObjectResourceService { addr_store }): State<AddressObjectResourceService<AS>>,
|
State(AddressObjectResourceService { addr_store }): State<AddressObjectResourceService<AS>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
if !user.is_principal(&principal) {
|
if !user.is_principal(&principal) {
|
||||||
return Err(Error::Unauthorized);
|
return Err(Error::Unauthorized);
|
||||||
@@ -60,7 +60,7 @@ pub async fn put_object<AS: AddressbookStore>(
|
|||||||
object_id,
|
object_id,
|
||||||
}): Path<AddressObjectPathComponents>,
|
}): Path<AddressObjectPathComponents>,
|
||||||
State(AddressObjectResourceService { addr_store }): State<AddressObjectResourceService<AS>>,
|
State(AddressObjectResourceService { addr_store }): State<AddressObjectResourceService<AS>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
mut if_none_match: Option<TypedHeader<IfNoneMatch>>,
|
mut if_none_match: Option<TypedHeader<IfNoneMatch>>,
|
||||||
header_map: HeaderMap,
|
header_map: HeaderMap,
|
||||||
body: String,
|
body: String,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use rustical_dav::{
|
|||||||
xml::Resourcetype,
|
xml::Resourcetype,
|
||||||
};
|
};
|
||||||
use rustical_ical::AddressObject;
|
use rustical_ical::AddressObject;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
|
|
||||||
#[derive(Clone, From, Into)]
|
#[derive(Clone, From, Into)]
|
||||||
pub struct AddressObjectResource {
|
pub struct AddressObjectResource {
|
||||||
@@ -30,7 +30,7 @@ impl ResourceName for AddressObjectResource {
|
|||||||
impl Resource for AddressObjectResource {
|
impl Resource for AddressObjectResource {
|
||||||
type Prop = AddressObjectPropWrapper;
|
type Prop = AddressObjectPropWrapper;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
|
|
||||||
fn is_collection(&self) -> bool {
|
fn is_collection(&self) -> bool {
|
||||||
false
|
false
|
||||||
@@ -43,7 +43,7 @@ impl Resource for AddressObjectResource {
|
|||||||
fn get_prop(
|
fn get_prop(
|
||||||
&self,
|
&self,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
prop: &AddressObjectPropWrapperName,
|
prop: &AddressObjectPropWrapperName,
|
||||||
) -> Result<Self::Prop, Self::Error> {
|
) -> Result<Self::Prop, Self::Error> {
|
||||||
Ok(match prop {
|
Ok(match prop {
|
||||||
@@ -78,7 +78,7 @@ impl Resource for AddressObjectResource {
|
|||||||
Some(self.object.get_etag())
|
Some(self.object.get_etag())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_privileges(&self, user: &User) -> Result<UserPrivilegeSet, Self::Error> {
|
fn get_user_privileges(&self, user: &Principal) -> Result<UserPrivilegeSet, Self::Error> {
|
||||||
Ok(UserPrivilegeSet::owner_only(
|
Ok(UserPrivilegeSet::owner_only(
|
||||||
user.is_principal(&self.principal),
|
user.is_principal(&self.principal),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use axum::{extract::Request, handler::Handler, response::Response};
|
|||||||
use derive_more::derive::Constructor;
|
use derive_more::derive::Constructor;
|
||||||
use futures_util::future::BoxFuture;
|
use futures_util::future::BoxFuture;
|
||||||
use rustical_dav::resource::{AxumMethods, ResourceService};
|
use rustical_dav::resource::{AxumMethods, ResourceService};
|
||||||
use rustical_store::{AddressbookStore, auth::User};
|
use rustical_store::{AddressbookStore, auth::Principal};
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
use std::{convert::Infallible, sync::Arc};
|
use std::{convert::Infallible, sync::Arc};
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
@@ -37,7 +37,7 @@ impl<AS: AddressbookStore> ResourceService for AddressObjectResourceService<AS>
|
|||||||
type Resource = AddressObjectResource;
|
type Resource = AddressObjectResource;
|
||||||
type MemberType = AddressObjectResource;
|
type MemberType = AddressObjectResource;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
type PrincipalUri = CardDavPrincipalUri;
|
type PrincipalUri = CardDavPrincipalUri;
|
||||||
|
|
||||||
const DAV_HEADER: &str = "1, 3, access-control, addressbook";
|
const DAV_HEADER: &str = "1, 3, access-control, addressbook";
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use percent_encoding::{CONTROLS, utf8_percent_encode};
|
|||||||
use rustical_dav::privileges::UserPrivilege;
|
use rustical_dav::privileges::UserPrivilege;
|
||||||
use rustical_dav::resource::Resource;
|
use rustical_dav::resource::Resource;
|
||||||
use rustical_ical::AddressObject;
|
use rustical_ical::AddressObject;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use rustical_store::{AddressbookStore, SubscriptionStore};
|
use rustical_store::{AddressbookStore, SubscriptionStore};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -19,7 +19,7 @@ use tracing::instrument;
|
|||||||
pub async fn route_get<AS: AddressbookStore, S: SubscriptionStore>(
|
pub async fn route_get<AS: AddressbookStore, S: SubscriptionStore>(
|
||||||
Path((principal, addressbook_id)): Path<(String, String)>,
|
Path((principal, addressbook_id)): Path<(String, String)>,
|
||||||
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
if !user.is_principal(&principal) {
|
if !user.is_principal(&principal) {
|
||||||
return Err(Error::Unauthorized);
|
return Err(Error::Unauthorized);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use axum::{
|
|||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
};
|
};
|
||||||
use http::StatusCode;
|
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 rustical_xml::{XmlDeserialize, XmlDocument, XmlRootTag};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ struct MkcolRequest {
|
|||||||
#[instrument(skip(addr_store))]
|
#[instrument(skip(addr_store))]
|
||||||
pub async fn route_mkcol<AS: AddressbookStore, S: SubscriptionStore>(
|
pub async fn route_mkcol<AS: AddressbookStore, S: SubscriptionStore>(
|
||||||
Path((principal, addressbook_id)): Path<(String, String)>,
|
Path((principal, addressbook_id)): Path<(String, String)>,
|
||||||
user: User,
|
user: Principal,
|
||||||
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
||||||
body: String,
|
body: String,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use http::{HeaderMap, HeaderValue, StatusCode, header};
|
|||||||
use rustical_dav::privileges::UserPrivilege;
|
use rustical_dav::privileges::UserPrivilege;
|
||||||
use rustical_dav::resource::Resource;
|
use rustical_dav::resource::Resource;
|
||||||
use rustical_dav_push::register::PushRegister;
|
use rustical_dav_push::register::PushRegister;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use rustical_store::{AddressbookStore, Subscription, SubscriptionStore};
|
use rustical_store::{AddressbookStore, Subscription, SubscriptionStore};
|
||||||
use rustical_xml::XmlDocument;
|
use rustical_xml::XmlDocument;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -15,7 +15,7 @@ use tracing::instrument;
|
|||||||
#[instrument(skip(resource_service))]
|
#[instrument(skip(resource_service))]
|
||||||
pub async fn route_post<AS: AddressbookStore, S: SubscriptionStore>(
|
pub async fn route_post<AS: AddressbookStore, S: SubscriptionStore>(
|
||||||
Path((principal, addr_id)): Path<(String, String)>,
|
Path((principal, addr_id)): Path<(String, String)>,
|
||||||
user: User,
|
user: Principal,
|
||||||
State(resource_service): State<AddressbookResourceService<AS, S>>,
|
State(resource_service): State<AddressbookResourceService<AS, S>>,
|
||||||
body: String,
|
body: String,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ use http::StatusCode;
|
|||||||
use ical::VcardParser;
|
use ical::VcardParser;
|
||||||
use rustical_ical::AddressObject;
|
use rustical_ical::AddressObject;
|
||||||
use rustical_store::Addressbook;
|
use rustical_store::Addressbook;
|
||||||
use rustical_store::{AddressbookStore, SubscriptionStore, auth::User};
|
use rustical_store::{AddressbookStore, SubscriptionStore, auth::Principal};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
#[instrument(skip(addr_store))]
|
#[instrument(skip(addr_store))]
|
||||||
pub async fn route_put<AS: AddressbookStore, S: SubscriptionStore>(
|
pub async fn route_put<AS: AddressbookStore, S: SubscriptionStore>(
|
||||||
Path((principal, addressbook_id)): Path<(String, String)>,
|
Path((principal, addressbook_id)): Path<(String, String)>,
|
||||||
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
body: String,
|
body: String,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
if !user.is_principal(&principal) {
|
if !user.is_principal(&principal) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use rustical_dav::{
|
|||||||
xml::{MultistatusElement, PropfindType, multistatus::ResponseElement},
|
xml::{MultistatusElement, PropfindType, multistatus::ResponseElement},
|
||||||
};
|
};
|
||||||
use rustical_ical::AddressObject;
|
use rustical_ical::AddressObject;
|
||||||
use rustical_store::{AddressbookStore, auth::User};
|
use rustical_store::{AddressbookStore, auth::Principal};
|
||||||
use rustical_xml::XmlDeserialize;
|
use rustical_xml::XmlDeserialize;
|
||||||
|
|
||||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||||
@@ -63,7 +63,7 @@ pub async fn handle_addressbook_multiget<AS: AddressbookStore>(
|
|||||||
prop: &PropfindType<AddressObjectPropWrapperName>,
|
prop: &PropfindType<AddressObjectPropWrapperName>,
|
||||||
path: &str,
|
path: &str,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
principal: &str,
|
principal: &str,
|
||||||
cal_id: &str,
|
cal_id: &str,
|
||||||
addr_store: &AS,
|
addr_store: &AS,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use axum::{
|
|||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
use rustical_dav::xml::{PropfindType, sync_collection::SyncCollectionRequest};
|
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 rustical_xml::{XmlDeserialize, XmlDocument};
|
||||||
use sync_collection::handle_sync_collection;
|
use sync_collection::handle_sync_collection;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -37,7 +37,7 @@ impl ReportRequest {
|
|||||||
#[instrument(skip(addr_store))]
|
#[instrument(skip(addr_store))]
|
||||||
pub async fn route_report_addressbook<AS: AddressbookStore, S: SubscriptionStore>(
|
pub async fn route_report_addressbook<AS: AddressbookStore, S: SubscriptionStore>(
|
||||||
Path((principal, addressbook_id)): Path<(String, String)>,
|
Path((principal, addressbook_id)): Path<(String, String)>,
|
||||||
user: User,
|
user: Principal,
|
||||||
OriginalUri(uri): OriginalUri,
|
OriginalUri(uri): OriginalUri,
|
||||||
Extension(puri): Extension<CardDavPrincipalUri>,
|
Extension(puri): Extension<CardDavPrincipalUri>,
|
||||||
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
State(AddressbookResourceService { addr_store, .. }): State<AddressbookResourceService<AS, S>>,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use rustical_dav::{
|
|||||||
};
|
};
|
||||||
use rustical_store::{
|
use rustical_store::{
|
||||||
AddressbookStore,
|
AddressbookStore,
|
||||||
auth::User,
|
auth::Principal,
|
||||||
synctoken::{format_synctoken, parse_synctoken},
|
synctoken::{format_synctoken, parse_synctoken},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ pub async fn handle_sync_collection<AS: AddressbookStore>(
|
|||||||
sync_collection: &SyncCollectionRequest<AddressObjectPropWrapperName>,
|
sync_collection: &SyncCollectionRequest<AddressObjectPropWrapperName>,
|
||||||
path: &str,
|
path: &str,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
principal: &str,
|
principal: &str,
|
||||||
addressbook_id: &str,
|
addressbook_id: &str,
|
||||||
addr_store: &AS,
|
addr_store: &AS,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use rustical_dav::resource::{PrincipalUri, Resource, ResourceName};
|
|||||||
use rustical_dav::xml::{Resourcetype, ResourcetypeInner, SupportedReportSet};
|
use rustical_dav::xml::{Resourcetype, ResourcetypeInner, SupportedReportSet};
|
||||||
use rustical_dav_push::DavPushExtension;
|
use rustical_dav_push::DavPushExtension;
|
||||||
use rustical_store::Addressbook;
|
use rustical_store::Addressbook;
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
|
|
||||||
#[derive(Clone, Debug, From, Into)]
|
#[derive(Clone, Debug, From, Into)]
|
||||||
pub struct AddressbookResource(pub(crate) Addressbook);
|
pub struct AddressbookResource(pub(crate) Addressbook);
|
||||||
@@ -36,7 +36,7 @@ impl DavPushExtension for AddressbookResource {
|
|||||||
impl Resource for AddressbookResource {
|
impl Resource for AddressbookResource {
|
||||||
type Prop = AddressbookPropWrapper;
|
type Prop = AddressbookPropWrapper;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
|
|
||||||
fn is_collection(&self) -> bool {
|
fn is_collection(&self) -> bool {
|
||||||
true
|
true
|
||||||
@@ -52,7 +52,7 @@ impl Resource for AddressbookResource {
|
|||||||
fn get_prop(
|
fn get_prop(
|
||||||
&self,
|
&self,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
prop: &AddressbookPropWrapperName,
|
prop: &AddressbookPropWrapperName,
|
||||||
) -> Result<Self::Prop, Self::Error> {
|
) -> Result<Self::Prop, Self::Error> {
|
||||||
Ok(match prop {
|
Ok(match prop {
|
||||||
@@ -138,7 +138,7 @@ impl Resource for AddressbookResource {
|
|||||||
Some(&self.0.principal)
|
Some(&self.0.principal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_privileges(&self, user: &User) -> Result<UserPrivilegeSet, Self::Error> {
|
fn get_user_privileges(&self, user: &Principal) -> Result<UserPrivilegeSet, Self::Error> {
|
||||||
Ok(UserPrivilegeSet::owner_only(
|
Ok(UserPrivilegeSet::owner_only(
|
||||||
user.is_principal(&self.0.principal),
|
user.is_principal(&self.0.principal),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use axum::handler::Handler;
|
|||||||
use axum::response::Response;
|
use axum::response::Response;
|
||||||
use futures_util::future::BoxFuture;
|
use futures_util::future::BoxFuture;
|
||||||
use rustical_dav::resource::{AxumMethods, ResourceService};
|
use rustical_dav::resource::{AxumMethods, ResourceService};
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
use rustical_store::{AddressbookStore, SubscriptionStore};
|
use rustical_store::{AddressbookStore, SubscriptionStore};
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -51,7 +51,7 @@ impl<AS: AddressbookStore, S: SubscriptionStore> ResourceService
|
|||||||
type PathComponents = (String, String); // principal, addressbook_id
|
type PathComponents = (String, String); // principal, addressbook_id
|
||||||
type Resource = AddressbookResource;
|
type Resource = AddressbookResource;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
type PrincipalUri = CardDavPrincipalUri;
|
type PrincipalUri = CardDavPrincipalUri;
|
||||||
|
|
||||||
const DAV_HEADER: &str = "1, 3, access-control, addressbook, webdav-push";
|
const DAV_HEADER: &str = "1, 3, access-control, addressbook, webdav-push";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use rustical_dav::resources::RootResourceService;
|
|||||||
use rustical_store::auth::middleware::AuthenticationLayer;
|
use rustical_store::auth::middleware::AuthenticationLayer;
|
||||||
use rustical_store::{
|
use rustical_store::{
|
||||||
AddressbookStore, SubscriptionStore,
|
AddressbookStore, SubscriptionStore,
|
||||||
auth::{AuthenticationProvider, User},
|
auth::{AuthenticationProvider, Principal},
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -44,10 +44,12 @@ pub fn carddav_router<AP: AuthenticationProvider, A: AddressbookStore, S: Subscr
|
|||||||
Router::new()
|
Router::new()
|
||||||
.nest(
|
.nest(
|
||||||
prefix,
|
prefix,
|
||||||
RootResourceService::<_, User, CardDavPrincipalUri>::new(principal_service.clone())
|
RootResourceService::<_, Principal, CardDavPrincipalUri>::new(
|
||||||
.axum_router()
|
principal_service.clone(),
|
||||||
.layer(AuthenticationLayer::new(auth_provider))
|
)
|
||||||
.layer(Extension(CardDavPrincipalUri(prefix))),
|
.axum_router()
|
||||||
|
.layer(AuthenticationLayer::new(auth_provider))
|
||||||
|
.layer(Extension(CardDavPrincipalUri(prefix))),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/.well-known/carddav",
|
"/.well-known/carddav",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use rustical_dav::resource::{PrincipalUri, Resource, ResourceName};
|
|||||||
use rustical_dav::xml::{
|
use rustical_dav::xml::{
|
||||||
GroupMemberSet, GroupMembership, HrefElement, Resourcetype, ResourcetypeInner,
|
GroupMemberSet, GroupMembership, HrefElement, Resourcetype, ResourcetypeInner,
|
||||||
};
|
};
|
||||||
use rustical_store::auth::User;
|
use rustical_store::auth::Principal;
|
||||||
|
|
||||||
mod service;
|
mod service;
|
||||||
pub use service::*;
|
pub use service::*;
|
||||||
@@ -14,7 +14,7 @@ pub use prop::*;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PrincipalResource {
|
pub struct PrincipalResource {
|
||||||
principal: User,
|
principal: Principal,
|
||||||
members: Vec<String>,
|
members: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ impl ResourceName for PrincipalResource {
|
|||||||
impl Resource for PrincipalResource {
|
impl Resource for PrincipalResource {
|
||||||
type Prop = PrincipalPropWrapper;
|
type Prop = PrincipalPropWrapper;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
|
|
||||||
fn is_collection(&self) -> bool {
|
fn is_collection(&self) -> bool {
|
||||||
true
|
true
|
||||||
@@ -43,7 +43,7 @@ impl Resource for PrincipalResource {
|
|||||||
fn get_prop(
|
fn get_prop(
|
||||||
&self,
|
&self,
|
||||||
puri: &impl PrincipalUri,
|
puri: &impl PrincipalUri,
|
||||||
user: &User,
|
user: &Principal,
|
||||||
prop: &PrincipalPropWrapperName,
|
prop: &PrincipalPropWrapperName,
|
||||||
) -> Result<Self::Prop, Self::Error> {
|
) -> Result<Self::Prop, Self::Error> {
|
||||||
let principal_href = HrefElement::new(puri.principal_uri(&self.principal.id));
|
let principal_href = HrefElement::new(puri.principal_uri(&self.principal.id));
|
||||||
@@ -99,7 +99,7 @@ impl Resource for PrincipalResource {
|
|||||||
Some(&self.principal.id)
|
Some(&self.principal.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_privileges(&self, user: &User) -> Result<UserPrivilegeSet, Self::Error> {
|
fn get_user_privileges(&self, user: &Principal) -> Result<UserPrivilegeSet, Self::Error> {
|
||||||
Ok(UserPrivilegeSet::owner_only(
|
Ok(UserPrivilegeSet::owner_only(
|
||||||
user.is_principal(&self.principal.id),
|
user.is_principal(&self.principal.id),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::{CardDavPrincipalUri, Error};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
use rustical_dav::resource::{AxumMethods, ResourceService};
|
use rustical_dav::resource::{AxumMethods, ResourceService};
|
||||||
use rustical_store::auth::{AuthenticationProvider, User};
|
use rustical_store::auth::{AuthenticationProvider, Principal};
|
||||||
use rustical_store::{AddressbookStore, SubscriptionStore};
|
use rustical_store::{AddressbookStore, SubscriptionStore};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ impl<A: AddressbookStore, AP: AuthenticationProvider, S: SubscriptionStore> Reso
|
|||||||
type MemberType = AddressbookResource;
|
type MemberType = AddressbookResource;
|
||||||
type Resource = PrincipalResource;
|
type Resource = PrincipalResource;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Principal = User;
|
type Principal = Principal;
|
||||||
type PrincipalUri = CardDavPrincipalUri;
|
type PrincipalUri = CardDavPrincipalUri;
|
||||||
|
|
||||||
const DAV_HEADER: &str = "1, 3, access-control, addressbook";
|
const DAV_HEADER: &str = "1, 3, access-control, addressbook";
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use axum_extra::{TypedHeader, extract::Host};
|
|||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use headers::UserAgent;
|
use headers::UserAgent;
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use rustical_store::auth::{AuthenticationProvider, User};
|
use rustical_store::auth::{AuthenticationProvider, Principal};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -101,7 +101,7 @@ struct NextcloudLoginPage {
|
|||||||
pub(crate) async fn get_nextcloud_flow(
|
pub(crate) async fn get_nextcloud_flow(
|
||||||
Extension(state): Extension<Arc<NextcloudFlows>>,
|
Extension(state): Extension<Arc<NextcloudFlows>>,
|
||||||
Path(flow_id): Path<String>,
|
Path(flow_id): Path<String>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, rustical_store::Error> {
|
) -> Result<Response, rustical_store::Error> {
|
||||||
if let Some(flow) = state.flows.read().await.get(&flow_id) {
|
if let Some(flow) = state.flows.read().await.get(&flow_id) {
|
||||||
Ok(Html(
|
Ok(Html(
|
||||||
@@ -131,7 +131,7 @@ struct NextcloudLoginSuccessPage {
|
|||||||
|
|
||||||
#[instrument(skip(state))]
|
#[instrument(skip(state))]
|
||||||
pub(crate) async fn post_nextcloud_flow(
|
pub(crate) async fn post_nextcloud_flow(
|
||||||
user: User,
|
user: Principal,
|
||||||
Extension(state): Extension<Arc<NextcloudFlows>>,
|
Extension(state): Extension<Arc<NextcloudFlows>>,
|
||||||
Path(flow_id): Path<String>,
|
Path(flow_id): Path<String>,
|
||||||
Host(host): Host,
|
Host(host): Host,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use rustical_oidc::UserStore;
|
use rustical_oidc::UserStore;
|
||||||
use rustical_store::auth::{AuthenticationProvider, User};
|
use rustical_store::auth::{AuthenticationProvider, Principal};
|
||||||
|
|
||||||
pub struct OidcUserStore<AP: AuthenticationProvider>(pub Arc<AP>);
|
pub struct OidcUserStore<AP: AuthenticationProvider>(pub Arc<AP>);
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ impl<AP: AuthenticationProvider> UserStore for OidcUserStore<AP> {
|
|||||||
async fn insert_user(&self, id: &str) -> Result<(), Self::Error> {
|
async fn insert_user(&self, id: &str) -> Result<(), Self::Error> {
|
||||||
self.0
|
self.0
|
||||||
.insert_principal(
|
.insert_principal(
|
||||||
User {
|
Principal {
|
||||||
id: id.to_owned(),
|
id: id.to_owned(),
|
||||||
displayname: None,
|
displayname: None,
|
||||||
principal_type: Default::default(),
|
principal_type: Default::default(),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use axum::{
|
|||||||
use axum_extra::TypedHeader;
|
use axum_extra::TypedHeader;
|
||||||
use headers::Referer;
|
use headers::Referer;
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use rustical_store::{Addressbook, AddressbookStore, auth::User};
|
use rustical_store::{Addressbook, AddressbookStore, auth::Principal};
|
||||||
|
|
||||||
#[derive(Template, WebTemplate)]
|
#[derive(Template, WebTemplate)]
|
||||||
#[template(path = "pages/addressbook.html")]
|
#[template(path = "pages/addressbook.html")]
|
||||||
@@ -21,7 +21,7 @@ struct AddressbookPage {
|
|||||||
pub async fn route_addressbook<AS: AddressbookStore>(
|
pub async fn route_addressbook<AS: AddressbookStore>(
|
||||||
Path((owner, addrbook_id)): Path<(String, String)>,
|
Path((owner, addrbook_id)): Path<(String, String)>,
|
||||||
Extension(store): Extension<Arc<AS>>,
|
Extension(store): Extension<Arc<AS>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, rustical_store::Error> {
|
) -> Result<Response, rustical_store::Error> {
|
||||||
if !user.is_principal(&owner) {
|
if !user.is_principal(&owner) {
|
||||||
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
||||||
@@ -35,7 +35,7 @@ pub async fn route_addressbook<AS: AddressbookStore>(
|
|||||||
pub async fn route_addressbook_restore<AS: AddressbookStore>(
|
pub async fn route_addressbook_restore<AS: AddressbookStore>(
|
||||||
Path((owner, addressbook_id)): Path<(String, String)>,
|
Path((owner, addressbook_id)): Path<(String, String)>,
|
||||||
Extension(store): Extension<Arc<AS>>,
|
Extension(store): Extension<Arc<AS>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
referer: Option<TypedHeader<Referer>>,
|
referer: Option<TypedHeader<Referer>>,
|
||||||
) -> Result<Response, rustical_store::Error> {
|
) -> Result<Response, rustical_store::Error> {
|
||||||
if !user.is_principal(&owner) {
|
if !user.is_principal(&owner) {
|
||||||
@@ -51,7 +51,7 @@ pub async fn route_addressbook_restore<AS: AddressbookStore>(
|
|||||||
pub async fn route_delete_addressbook<AS: AddressbookStore>(
|
pub async fn route_delete_addressbook<AS: AddressbookStore>(
|
||||||
Path((owner, addressbook_id)): Path<(String, String)>,
|
Path((owner, addressbook_id)): Path<(String, String)>,
|
||||||
Extension(store): Extension<Arc<AS>>,
|
Extension(store): Extension<Arc<AS>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, rustical_store::Error> {
|
) -> Result<Response, rustical_store::Error> {
|
||||||
if !user.is_principal(&owner) {
|
if !user.is_principal(&owner) {
|
||||||
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use headers::{ContentType, HeaderMapExt};
|
|||||||
use http::{HeaderValue, StatusCode, header};
|
use http::{HeaderValue, StatusCode, header};
|
||||||
use percent_encoding::{CONTROLS, utf8_percent_encode};
|
use percent_encoding::{CONTROLS, utf8_percent_encode};
|
||||||
use rand::{Rng, distr::Alphanumeric};
|
use rand::{Rng, distr::Alphanumeric};
|
||||||
use rustical_store::auth::{AuthenticationProvider, User};
|
use rustical_store::auth::{AuthenticationProvider, Principal};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ pub(crate) struct PostAppTokenForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn route_post_app_token<AP: AuthenticationProvider>(
|
pub async fn route_post_app_token<AP: AuthenticationProvider>(
|
||||||
user: User,
|
user: Principal,
|
||||||
Extension(auth_provider): Extension<Arc<AP>>,
|
Extension(auth_provider): Extension<Arc<AP>>,
|
||||||
Path(user_id): Path<String>,
|
Path(user_id): Path<String>,
|
||||||
Host(hostname): Host,
|
Host(hostname): Host,
|
||||||
@@ -96,7 +96,7 @@ pub async fn route_post_app_token<AP: AuthenticationProvider>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn route_delete_app_token<AP: AuthenticationProvider>(
|
pub async fn route_delete_app_token<AP: AuthenticationProvider>(
|
||||||
user: User,
|
user: Principal,
|
||||||
Extension(auth_provider): Extension<Arc<AP>>,
|
Extension(auth_provider): Extension<Arc<AP>>,
|
||||||
Path((user_id, token_id)): Path<(String, String)>,
|
Path((user_id, token_id)): Path<(String, String)>,
|
||||||
) -> Result<Redirect, rustical_store::Error> {
|
) -> Result<Redirect, rustical_store::Error> {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use axum::{
|
|||||||
use axum_extra::TypedHeader;
|
use axum_extra::TypedHeader;
|
||||||
use headers::Referer;
|
use headers::Referer;
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use rustical_store::{Calendar, CalendarStore, auth::User};
|
use rustical_store::{Calendar, CalendarStore, auth::Principal};
|
||||||
|
|
||||||
#[derive(Template, WebTemplate)]
|
#[derive(Template, WebTemplate)]
|
||||||
#[template(path = "pages/calendar.html")]
|
#[template(path = "pages/calendar.html")]
|
||||||
@@ -21,7 +21,7 @@ struct CalendarPage {
|
|||||||
pub async fn route_calendar<C: CalendarStore>(
|
pub async fn route_calendar<C: CalendarStore>(
|
||||||
Path((owner, cal_id)): Path<(String, String)>,
|
Path((owner, cal_id)): Path<(String, String)>,
|
||||||
Extension(store): Extension<Arc<C>>,
|
Extension(store): Extension<Arc<C>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, rustical_store::Error> {
|
) -> Result<Response, rustical_store::Error> {
|
||||||
if !user.is_principal(&owner) {
|
if !user.is_principal(&owner) {
|
||||||
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
||||||
@@ -35,7 +35,7 @@ pub async fn route_calendar<C: CalendarStore>(
|
|||||||
pub async fn route_calendar_restore<CS: CalendarStore>(
|
pub async fn route_calendar_restore<CS: CalendarStore>(
|
||||||
Path((owner, cal_id)): Path<(String, String)>,
|
Path((owner, cal_id)): Path<(String, String)>,
|
||||||
Extension(store): Extension<Arc<CS>>,
|
Extension(store): Extension<Arc<CS>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
referer: Option<TypedHeader<Referer>>,
|
referer: Option<TypedHeader<Referer>>,
|
||||||
) -> Result<Response, rustical_store::Error> {
|
) -> Result<Response, rustical_store::Error> {
|
||||||
if !user.is_principal(&owner) {
|
if !user.is_principal(&owner) {
|
||||||
@@ -51,7 +51,7 @@ pub async fn route_calendar_restore<CS: CalendarStore>(
|
|||||||
pub async fn route_delete_calendar<C: CalendarStore>(
|
pub async fn route_delete_calendar<C: CalendarStore>(
|
||||||
Path((owner, cal_id)): Path<(String, String)>,
|
Path((owner, cal_id)): Path<(String, String)>,
|
||||||
Extension(store): Extension<Arc<C>>,
|
Extension(store): Extension<Arc<C>>,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> Result<Response, rustical_store::Error> {
|
) -> Result<Response, rustical_store::Error> {
|
||||||
if !user.is_principal(&owner) {
|
if !user.is_principal(&owner) {
|
||||||
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ use headers::UserAgent;
|
|||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use rustical_store::{
|
use rustical_store::{
|
||||||
Addressbook, AddressbookStore, Calendar, CalendarStore,
|
Addressbook, AddressbookStore, Calendar, CalendarStore,
|
||||||
auth::{AuthenticationProvider, User, user::AppToken},
|
auth::{AppToken, AuthenticationProvider, Principal},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Template, WebTemplate)]
|
#[derive(Template, WebTemplate)]
|
||||||
#[template(path = "pages/user.html")]
|
#[template(path = "pages/user.html")]
|
||||||
pub struct UserPage {
|
pub struct UserPage {
|
||||||
pub user: User,
|
pub user: Principal,
|
||||||
pub app_tokens: Vec<AppToken>,
|
pub app_tokens: Vec<AppToken>,
|
||||||
pub calendars: Vec<Calendar>,
|
pub calendars: Vec<Calendar>,
|
||||||
pub deleted_calendars: Vec<Calendar>,
|
pub deleted_calendars: Vec<Calendar>,
|
||||||
@@ -39,7 +39,7 @@ pub async fn route_user_named<
|
|||||||
Extension(auth_provider): Extension<Arc<AP>>,
|
Extension(auth_provider): Extension<Arc<AP>>,
|
||||||
TypedHeader(user_agent): TypedHeader<UserAgent>,
|
TypedHeader(user_agent): TypedHeader<UserAgent>,
|
||||||
Host(host): Host,
|
Host(host): Host,
|
||||||
user: User,
|
user: Principal,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
if user_id != user.id {
|
if user_id != user.id {
|
||||||
return StatusCode::UNAUTHORIZED.into_response();
|
return StatusCode::UNAUTHORIZED.into_response();
|
||||||
@@ -81,11 +81,11 @@ pub async fn route_user_named<
|
|||||||
.into_response()
|
.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))
|
Redirect::to(&format!("/frontend/user/{}", user.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn route_root(user: Option<User>) -> Redirect {
|
pub async fn route_root(user: Option<Principal>) -> Redirect {
|
||||||
match user {
|
match user {
|
||||||
Some(user) => route_get_home(user).await,
|
Some(user) => route_get_home(user).await,
|
||||||
None => Redirect::to("/frontend/login"),
|
None => Redirect::to("/frontend/login"),
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
pub mod user;
|
mod principal;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
pub use principal::{AppToken, Principal, PrincipalType};
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait AuthenticationProvider: Send + Sync + 'static {
|
pub trait AuthenticationProvider: Send + Sync + 'static {
|
||||||
async fn get_principals(&self) -> Result<Vec<User>, crate::Error>;
|
async fn get_principals(&self) -> Result<Vec<Principal>, crate::Error>;
|
||||||
async fn get_principal(&self, id: &str) -> Result<Option<User>, crate::Error>;
|
async fn get_principal(&self, id: &str) -> Result<Option<Principal>, crate::Error>;
|
||||||
async fn remove_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 insert_principal(&self, user: Principal, overwrite: bool) -> Result<(), crate::Error>;
|
||||||
async fn validate_password(&self, user_id: &str, password: &str)
|
async fn validate_password(
|
||||||
-> Result<Option<User>, Error>;
|
&self,
|
||||||
async fn validate_app_token(&self, user_id: &str, token: &str) -> Result<Option<User>, Error>;
|
user_id: &str,
|
||||||
|
password: &str,
|
||||||
|
) -> Result<Option<Principal>, Error>;
|
||||||
|
async fn validate_app_token(
|
||||||
|
&self,
|
||||||
|
user_id: &str,
|
||||||
|
token: &str,
|
||||||
|
) -> Result<Option<Principal>, Error>;
|
||||||
/// Returns a token identifier
|
/// Returns a token identifier
|
||||||
async fn add_app_token(
|
async fn add_app_token(
|
||||||
&self,
|
&self,
|
||||||
@@ -28,5 +37,3 @@ pub trait AuthenticationProvider: Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub use middleware::AuthenticationMiddleware;
|
pub use middleware::AuthenticationMiddleware;
|
||||||
use user::AppToken;
|
|
||||||
pub use user::User;
|
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ pub struct AppToken {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
// TODO: Rename this to Principal
|
pub struct Principal {
|
||||||
pub struct User {
|
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub displayname: Option<String>,
|
pub displayname: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -89,7 +88,7 @@ pub struct User {
|
|||||||
pub memberships: Vec<String>,
|
pub memberships: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl Principal {
|
||||||
/// Returns true if the user is either
|
/// Returns true if the user is either
|
||||||
/// - the principal itself
|
/// - the principal itself
|
||||||
/// - has full access to the prinicpal (is member)
|
/// - 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 {
|
fn get_id(&self) -> &str {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
@@ -134,7 +133,7 @@ impl IntoResponse for UnauthorizedError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Send + Sync + Clone> FromRequestParts<S> for User {
|
impl<S: Send + Sync + Clone> FromRequestParts<S> for Principal {
|
||||||
type Rejection = UnauthorizedError;
|
type Rejection = UnauthorizedError;
|
||||||
|
|
||||||
async fn from_request_parts(
|
async fn from_request_parts(
|
||||||
@@ -149,7 +148,7 @@ impl<S: Send + Sync + Clone> FromRequestParts<S> for User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Send + Sync + Clone> OptionalFromRequestParts<S> for User {
|
impl<S: Send + Sync + Clone> OptionalFromRequestParts<S> for Principal {
|
||||||
type Rejection = Infallible;
|
type Rejection = Infallible;
|
||||||
|
|
||||||
async fn from_request_parts(
|
async fn from_request_parts(
|
||||||
@@ -7,7 +7,7 @@ use pbkdf2::{
|
|||||||
};
|
};
|
||||||
use rustical_store::{
|
use rustical_store::{
|
||||||
Error, Secret,
|
Error, Secret,
|
||||||
auth::{AuthenticationProvider, User, user::AppToken},
|
auth::{AppToken, AuthenticationProvider, Principal},
|
||||||
};
|
};
|
||||||
use sqlx::{SqlitePool, types::Json};
|
use sqlx::{SqlitePool, types::Json};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
@@ -21,11 +21,11 @@ struct PrincipalRow {
|
|||||||
memberships: Option<Json<Vec<Option<String>>>>,
|
memberships: Option<Json<Vec<Option<String>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<PrincipalRow> for User {
|
impl TryFrom<PrincipalRow> for Principal {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: PrincipalRow) -> Result<Self, Self::Error> {
|
fn try_from(value: PrincipalRow) -> Result<Self, Self::Error> {
|
||||||
Ok(User {
|
Ok(Principal {
|
||||||
id: value.id,
|
id: value.id,
|
||||||
displayname: value.displayname,
|
displayname: value.displayname,
|
||||||
password: value.password_hash.map(Secret::from),
|
password: value.password_hash.map(Secret::from),
|
||||||
@@ -49,8 +49,8 @@ pub struct SqlitePrincipalStore {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AuthenticationProvider for SqlitePrincipalStore {
|
impl AuthenticationProvider for SqlitePrincipalStore {
|
||||||
#[instrument]
|
#[instrument]
|
||||||
async fn get_principals(&self) -> Result<Vec<User>, Error> {
|
async fn get_principals(&self) -> Result<Vec<Principal>, Error> {
|
||||||
let result: Result<Vec<User>, Error> = sqlx::query_as!(
|
let result: Result<Vec<Principal>, Error> = sqlx::query_as!(
|
||||||
PrincipalRow,
|
PrincipalRow,
|
||||||
r#"
|
r#"
|
||||||
SELECT id, displayname, principal_type, password_hash, json_group_array(member_of) AS "memberships: Json<Vec<Option<String>>>"
|
SELECT id, displayname, principal_type, password_hash, json_group_array(member_of) AS "memberships: Json<Vec<Option<String>>>"
|
||||||
@@ -63,13 +63,13 @@ impl AuthenticationProvider for SqlitePrincipalStore {
|
|||||||
.await
|
.await
|
||||||
.map_err(crate::Error::from)?
|
.map_err(crate::Error::from)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(User::try_from)
|
.map(Principal::try_from)
|
||||||
.collect();
|
.collect();
|
||||||
Ok(result?)
|
Ok(result?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
async fn get_principal(&self, id: &str) -> Result<Option<User>, Error> {
|
async fn get_principal(&self, id: &str) -> Result<Option<Principal>, Error> {
|
||||||
let row= sqlx::query_as!(
|
let row= sqlx::query_as!(
|
||||||
PrincipalRow,
|
PrincipalRow,
|
||||||
r#"
|
r#"
|
||||||
@@ -83,7 +83,7 @@ impl AuthenticationProvider for SqlitePrincipalStore {
|
|||||||
.fetch_optional(&self.db)
|
.fetch_optional(&self.db)
|
||||||
.await
|
.await
|
||||||
.map_err(crate::Error::from)?
|
.map_err(crate::Error::from)?
|
||||||
.map(User::try_from);
|
.map(Principal::try_from);
|
||||||
if let Some(row) = row {
|
if let Some(row) = row {
|
||||||
Ok(Some(row?))
|
Ok(Some(row?))
|
||||||
} else {
|
} else {
|
||||||
@@ -103,7 +103,7 @@ impl AuthenticationProvider for SqlitePrincipalStore {
|
|||||||
#[instrument]
|
#[instrument]
|
||||||
async fn insert_principal(
|
async fn insert_principal(
|
||||||
&self,
|
&self,
|
||||||
user: User,
|
user: Principal,
|
||||||
overwrite: bool,
|
overwrite: bool,
|
||||||
) -> Result<(), rustical_store::Error> {
|
) -> Result<(), rustical_store::Error> {
|
||||||
// Would be cleaner to put this into a transaction but for now it will be fine
|
// 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))]
|
#[instrument(skip(token))]
|
||||||
async fn validate_app_token(&self, user_id: &str, token: &str) -> Result<Option<User>, Error> {
|
async fn validate_app_token(
|
||||||
|
&self,
|
||||||
|
user_id: &str,
|
||||||
|
token: &str,
|
||||||
|
) -> Result<Option<Principal>, Error> {
|
||||||
for app_token in &self.get_app_tokens(user_id).await? {
|
for app_token in &self.get_app_tokens(user_id).await? {
|
||||||
if password_auth::verify_password(token, app_token.token.as_ref()).is_ok() {
|
if password_auth::verify_password(token, app_token.token.as_ref()).is_ok() {
|
||||||
return self.get_principal(user_id).await;
|
return self.get_principal(user_id).await;
|
||||||
@@ -169,8 +173,8 @@ impl AuthenticationProvider for SqlitePrincipalStore {
|
|||||||
&self,
|
&self,
|
||||||
user_id: &str,
|
user_id: &str,
|
||||||
password_input: &str,
|
password_input: &str,
|
||||||
) -> Result<Option<User>, Error> {
|
) -> Result<Option<Principal>, Error> {
|
||||||
let user: User = match self.get_principal(user_id).await? {
|
let user: Principal = match self.get_principal(user_id).await? {
|
||||||
Some(user) => user,
|
Some(user) => user,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use figment::{
|
|||||||
providers::{Env, Format, Toml},
|
providers::{Env, Format, Toml},
|
||||||
};
|
};
|
||||||
use password_hash::{PasswordHasher, SaltString, rand_core::OsRng};
|
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)]
|
#[derive(Parser, Debug)]
|
||||||
pub struct PrincipalsArgs {
|
pub struct PrincipalsArgs {
|
||||||
@@ -99,7 +99,7 @@ pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> {
|
|||||||
};
|
};
|
||||||
principal_store
|
principal_store
|
||||||
.insert_principal(
|
.insert_principal(
|
||||||
User {
|
Principal {
|
||||||
id,
|
id,
|
||||||
displayname: name,
|
displayname: name,
|
||||||
principal_type: principal_type.unwrap_or_default(),
|
principal_type: principal_type.unwrap_or_default(),
|
||||||
|
|||||||
Reference in New Issue
Block a user