Working thunderbird autodetect
This commit is contained in:
parent
5bf3517acf
commit
fb6a379f43
8 changed files with 309 additions and 32 deletions
68
aero-dav/src/acldecoder.rs
Normal file
68
aero-dav/src/acldecoder.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use super::acltypes::*;
|
||||||
|
use super::types as dav;
|
||||||
|
use super::xml::{QRead, Reader, IRead, DAV_URN};
|
||||||
|
use super::error::ParsingError;
|
||||||
|
|
||||||
|
impl QRead<Property> for Property {
|
||||||
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||||
|
if xml.maybe_open_start(DAV_URN, "owner").await?.is_some() {
|
||||||
|
let href = xml.find().await?;
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::Owner(href))
|
||||||
|
}
|
||||||
|
if xml.maybe_open_start(DAV_URN, "current-user-principal").await?.is_some() {
|
||||||
|
let user = xml.find().await?;
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::CurrentUserPrincipal(user))
|
||||||
|
}
|
||||||
|
if xml.maybe_open_start(DAV_URN, "current-user-privilege-set").await?.is_some() {
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::CurrentUserPrivilegeSet(vec![]))
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(ParsingError::Recoverable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QRead<PropertyRequest> for PropertyRequest {
|
||||||
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||||
|
if xml.maybe_open(DAV_URN, "owner").await?.is_some() {
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::Owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
if xml.maybe_open(DAV_URN, "current-user-principal").await?.is_some() {
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::CurrentUserPrincipal)
|
||||||
|
}
|
||||||
|
|
||||||
|
if xml.maybe_open(DAV_URN, "current-user-privilege-set").await?.is_some() {
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::CurrentUserPrivilegeSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(ParsingError::Recoverable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QRead<ResourceType> for ResourceType {
|
||||||
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||||
|
if xml.maybe_open(DAV_URN, "principal").await?.is_some() {
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::Principal)
|
||||||
|
}
|
||||||
|
Err(ParsingError::Recoverable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----
|
||||||
|
impl QRead<User> for User {
|
||||||
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||||
|
if xml.maybe_open(DAV_URN, "unauthenticated").await?.is_some() {
|
||||||
|
xml.close().await?;
|
||||||
|
return Ok(Self::Unauthenticated)
|
||||||
|
}
|
||||||
|
|
||||||
|
dav::Href::qread(xml).await.map(Self::Authenticated)
|
||||||
|
}
|
||||||
|
}
|
71
aero-dav/src/aclencoder.rs
Normal file
71
aero-dav/src/aclencoder.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use quick_xml::Error as QError;
|
||||||
|
use quick_xml::events::Event;
|
||||||
|
|
||||||
|
use super::acltypes::*;
|
||||||
|
use super::xml::{QWrite, Writer, IWrite};
|
||||||
|
use super::error::ParsingError;
|
||||||
|
|
||||||
|
impl QWrite for Property {
|
||||||
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
|
match self {
|
||||||
|
Self::Owner(href) => {
|
||||||
|
let start = xml.create_dav_element("owner");
|
||||||
|
let end = start.to_end();
|
||||||
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
|
href.qwrite(xml).await?;
|
||||||
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
},
|
||||||
|
Self::CurrentUserPrincipal(user) => {
|
||||||
|
let start = xml.create_dav_element("current-user-principal");
|
||||||
|
let end = start.to_end();
|
||||||
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
|
user.qwrite(xml).await?;
|
||||||
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
},
|
||||||
|
Self::CurrentUserPrivilegeSet(_) => {
|
||||||
|
let empty_tag = xml.create_dav_element("current-user-privilege-set");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_tag)).await
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QWrite for PropertyRequest {
|
||||||
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
|
let mut atom = async |c| {
|
||||||
|
let empty_tag = xml.create_dav_element(c);
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_tag)).await
|
||||||
|
};
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Self::Owner => atom("owner").await,
|
||||||
|
Self::CurrentUserPrincipal => atom("current-user-principal").await,
|
||||||
|
Self::CurrentUserPrivilegeSet => atom("current-user-privilege-set").await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QWrite for ResourceType {
|
||||||
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
|
match self {
|
||||||
|
Self::Principal => {
|
||||||
|
let empty_tag = xml.create_dav_element("principal");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_tag)).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----
|
||||||
|
|
||||||
|
impl QWrite for User {
|
||||||
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
|
match self {
|
||||||
|
Self::Unauthenticated => {
|
||||||
|
let tag = xml.create_dav_element("unauthenticated");
|
||||||
|
xml.q.write_event_async(Event::Empty(tag)).await
|
||||||
|
},
|
||||||
|
Self::Authenticated(href) => href.qwrite(xml).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,40 @@
|
||||||
//@FIXME required for a full DAV implementation
|
use super::types as dav;
|
||||||
|
|
||||||
|
//RFC covered: RFC3744 (ACL core) + RFC5397 (ACL Current Principal Extension)
|
||||||
|
|
||||||
|
|
||||||
|
//@FIXME required for a full CalDAV implementation
|
||||||
// See section 6. of the CalDAV RFC
|
// See section 6. of the CalDAV RFC
|
||||||
// It seems mainly required for free-busy that I will not implement now.
|
// It seems mainly required for free-busy that I will not implement now.
|
||||||
// It can also be used for discovering main calendar, not sure it is used.
|
// It can also be used for discovering main calendar, not sure it is used.
|
||||||
|
// Note: it is used by Thunderbird
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum PropertyRequest {
|
||||||
|
Owner,
|
||||||
|
CurrentUserPrincipal,
|
||||||
|
CurrentUserPrivilegeSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum Property {
|
||||||
|
Owner(dav::Href),
|
||||||
|
CurrentUserPrincipal(User),
|
||||||
|
CurrentUserPrivilegeSet(Vec<Privilege>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum ResourceType {
|
||||||
|
Principal,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Not implemented, it's a placeholder
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Privilege(());
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum User {
|
||||||
|
Unauthenticated,
|
||||||
|
Authenticated(dav::Href),
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use chrono::{DateTime,Utc};
|
use chrono::{DateTime,Utc};
|
||||||
use super::types as dav;
|
use super::types as dav;
|
||||||
use super::xml;
|
|
||||||
|
|
||||||
pub const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ";
|
pub const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ";
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,12 @@ pub mod caltypes;
|
||||||
pub mod calencoder;
|
pub mod calencoder;
|
||||||
pub mod caldecoder;
|
pub mod caldecoder;
|
||||||
|
|
||||||
// wip
|
// acl (wip)
|
||||||
mod acltypes;
|
pub mod acltypes;
|
||||||
|
pub mod aclencoder;
|
||||||
|
pub mod acldecoder;
|
||||||
|
|
||||||
|
// versioning (wip)
|
||||||
mod versioningtypes;
|
mod versioningtypes;
|
||||||
|
|
||||||
// final type
|
// final type
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::types as dav;
|
use super::types as dav;
|
||||||
use super::caltypes as cal;
|
use super::caltypes as cal;
|
||||||
|
use super::acltypes as acl;
|
||||||
use super::xml;
|
use super::xml;
|
||||||
use super::error;
|
use super::error;
|
||||||
|
|
||||||
|
@ -11,8 +12,8 @@ impl xml::QRead<Disabled> for Disabled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl xml::QWrite for Disabled {
|
impl xml::QWrite for Disabled {
|
||||||
fn qwrite(&self, _xml: &mut xml::Writer<impl xml::IWrite>) -> impl futures::Future<Output = Result<(), quick_xml::Error>> + Send {
|
async fn qwrite(&self, _xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
|
||||||
async { unreachable!(); }
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,3 +41,92 @@ impl dav::Extension for Calendar
|
||||||
type ResourceType = cal::ResourceType;
|
type ResourceType = cal::ResourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ACL
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Acl {}
|
||||||
|
impl dav::Extension for Acl
|
||||||
|
{
|
||||||
|
type Error = Disabled;
|
||||||
|
type Property = acl::Property;
|
||||||
|
type PropertyRequest = acl::PropertyRequest;
|
||||||
|
type ResourceType = acl::ResourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All merged
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct All {}
|
||||||
|
impl dav::Extension for All {
|
||||||
|
type Error = cal::Violation;
|
||||||
|
type Property = Property;
|
||||||
|
type PropertyRequest = PropertyRequest;
|
||||||
|
type ResourceType = ResourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum Property {
|
||||||
|
Cal(cal::Property),
|
||||||
|
Acl(acl::Property),
|
||||||
|
}
|
||||||
|
impl xml::QRead<Property> for Property {
|
||||||
|
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
|
||||||
|
match cal::Property::qread(xml).await {
|
||||||
|
Err(error::ParsingError::Recoverable) => (),
|
||||||
|
otherwise => return otherwise.map(Property::Cal),
|
||||||
|
}
|
||||||
|
acl::Property::qread(xml).await.map(Property::Acl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl xml::QWrite for Property {
|
||||||
|
async fn qwrite(&self, xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Cal(c) => c.qwrite(xml).await,
|
||||||
|
Self::Acl(a) => a.qwrite(xml).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum PropertyRequest {
|
||||||
|
Cal(cal::PropertyRequest),
|
||||||
|
Acl(acl::PropertyRequest),
|
||||||
|
}
|
||||||
|
impl xml::QRead<PropertyRequest> for PropertyRequest {
|
||||||
|
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
|
||||||
|
match cal::PropertyRequest::qread(xml).await {
|
||||||
|
Err(error::ParsingError::Recoverable) => (),
|
||||||
|
otherwise => return otherwise.map(PropertyRequest::Cal),
|
||||||
|
}
|
||||||
|
acl::PropertyRequest::qread(xml).await.map(PropertyRequest::Acl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl xml::QWrite for PropertyRequest {
|
||||||
|
async fn qwrite(&self, xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Cal(c) => c.qwrite(xml).await,
|
||||||
|
Self::Acl(a) => a.qwrite(xml).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum ResourceType {
|
||||||
|
Cal(cal::ResourceType),
|
||||||
|
Acl(acl::ResourceType),
|
||||||
|
}
|
||||||
|
impl xml::QRead<ResourceType> for ResourceType {
|
||||||
|
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
|
||||||
|
match cal::ResourceType::qread(xml).await {
|
||||||
|
Err(error::ParsingError::Recoverable) => (),
|
||||||
|
otherwise => return otherwise.map(ResourceType::Cal),
|
||||||
|
}
|
||||||
|
acl::ResourceType::qread(xml).await.map(ResourceType::Acl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl xml::QWrite for ResourceType {
|
||||||
|
async fn qwrite(&self, xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Cal(c) => c.qwrite(xml).await,
|
||||||
|
Self::Acl(a) => a.qwrite(xml).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ impl<T: IRead> Reader<T> {
|
||||||
_ => return Err(ParsingError::Recoverable),
|
_ => return Err(ParsingError::Recoverable),
|
||||||
};
|
};
|
||||||
|
|
||||||
//println!("open tag {:?}", evt);
|
//println!("open start tag {:?}", evt);
|
||||||
self.parents.push(evt.clone());
|
self.parents.push(evt.clone());
|
||||||
Ok(evt)
|
Ok(evt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@ use aero_user::login::ArcLoginProvider;
|
||||||
use aero_collections::user::User;
|
use aero_collections::user::User;
|
||||||
use aero_dav::types as dav;
|
use aero_dav::types as dav;
|
||||||
use aero_dav::caltypes as cal;
|
use aero_dav::caltypes as cal;
|
||||||
use aero_dav::realization::Calendar;
|
use aero_dav::acltypes as acl;
|
||||||
|
use aero_dav::realization::{All, self as all};
|
||||||
use aero_dav::xml as dxml;
|
use aero_dav::xml as dxml;
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
|
@ -244,7 +245,7 @@ async fn router(user: std::sync::Arc<User>, req: Request<Incoming>) -> Result<Re
|
||||||
/// </D:prop>
|
/// </D:prop>
|
||||||
/// </D:propfind>
|
/// </D:propfind>
|
||||||
|
|
||||||
const ALLPROP: [dav::PropertyRequest<Calendar>; 10] = [
|
const ALLPROP: [dav::PropertyRequest<All>; 10] = [
|
||||||
dav::PropertyRequest::CreationDate,
|
dav::PropertyRequest::CreationDate,
|
||||||
dav::PropertyRequest::DisplayName,
|
dav::PropertyRequest::DisplayName,
|
||||||
dav::PropertyRequest::GetContentLanguage,
|
dav::PropertyRequest::GetContentLanguage,
|
||||||
|
@ -265,7 +266,7 @@ async fn propfind(user: std::sync::Arc<User>, req: Request<Incoming>, node: Box<
|
||||||
// request body MUST be treated as if it were an 'allprop' request.
|
// request body MUST be treated as if it were an 'allprop' request.
|
||||||
// @FIXME here we handle any invalid data as an allprop, an empty request is thus correctly
|
// @FIXME here we handle any invalid data as an allprop, an empty request is thus correctly
|
||||||
// handled, but corrupted requests are also silently handled as allprop.
|
// handled, but corrupted requests are also silently handled as allprop.
|
||||||
let propfind = deserialize::<dav::PropFind<Calendar>>(req).await.unwrap_or_else(|_| dav::PropFind::<Calendar>::AllProp(None));
|
let propfind = deserialize::<dav::PropFind<All>>(req).await.unwrap_or_else(|_| dav::PropFind::<All>::AllProp(None));
|
||||||
tracing::debug!(recv=?propfind, "inferred propfind request");
|
tracing::debug!(recv=?propfind, "inferred propfind request");
|
||||||
|
|
||||||
if matches!(propfind, dav::PropFind::PropName) {
|
if matches!(propfind, dav::PropFind::PropName) {
|
||||||
|
@ -370,19 +371,19 @@ trait DavNode: Send {
|
||||||
|
|
||||||
// node properties
|
// node properties
|
||||||
fn path(&self, user: &ArcUser) -> String;
|
fn path(&self, user: &ArcUser) -> String;
|
||||||
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<Calendar>;
|
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<All>;
|
||||||
fn properties(&self, user: &ArcUser, prop: dav::PropName<Calendar>) -> Vec<dav::AnyProperty<Calendar>>;
|
fn properties(&self, user: &ArcUser, prop: dav::PropName<All>) -> Vec<dav::AnyProperty<All>>;
|
||||||
|
|
||||||
// ----- common
|
// ----- common
|
||||||
|
|
||||||
/// building DAV responses
|
/// building DAV responses
|
||||||
fn multistatus_name(&self, user: &ArcUser, depth: dav::Depth) -> dav::Multistatus<Calendar> {
|
fn multistatus_name(&self, user: &ArcUser, depth: dav::Depth) -> dav::Multistatus<All> {
|
||||||
let mut names = vec![(self.path(user), self.supported_properties(user))];
|
let mut names = vec![(self.path(user), self.supported_properties(user))];
|
||||||
if matches!(depth, dav::Depth::One | dav::Depth::Infinity) {
|
if matches!(depth, dav::Depth::One | dav::Depth::Infinity) {
|
||||||
names.extend(self.children(user).iter().map(|c| (c.path(user), c.supported_properties(user))));
|
names.extend(self.children(user).iter().map(|c| (c.path(user), c.supported_properties(user))));
|
||||||
}
|
}
|
||||||
|
|
||||||
dav::Multistatus::<Calendar> {
|
dav::Multistatus::<All> {
|
||||||
responses: names.into_iter().map(|(url, names)| dav::Response {
|
responses: names.into_iter().map(|(url, names)| dav::Response {
|
||||||
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
||||||
dav::Href(url),
|
dav::Href(url),
|
||||||
|
@ -401,7 +402,7 @@ trait DavNode: Send {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multistatus_val(&self, user: &ArcUser, props: dav::PropName<Calendar>, depth: dav::Depth) -> dav::Multistatus<Calendar> {
|
fn multistatus_val(&self, user: &ArcUser, props: dav::PropName<All>, depth: dav::Depth) -> dav::Multistatus<All> {
|
||||||
// Collect properties
|
// Collect properties
|
||||||
let mut values = vec![(self.path(user), self.properties(user, props.clone()))];
|
let mut values = vec![(self.path(user), self.properties(user, props.clone()))];
|
||||||
if matches!(depth, dav::Depth::One | dav::Depth::Infinity) {
|
if matches!(depth, dav::Depth::One | dav::Depth::Infinity) {
|
||||||
|
@ -426,7 +427,7 @@ trait DavNode: Send {
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
// Build response
|
// Build response
|
||||||
dav::Multistatus::<Calendar> {
|
dav::Multistatus::<All> {
|
||||||
responses: values.into_iter().map(|(url, propdesc)| dav::Response {
|
responses: values.into_iter().map(|(url, propdesc)| dav::Response {
|
||||||
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
||||||
dav::Href(url),
|
dav::Href(url),
|
||||||
|
@ -468,18 +469,23 @@ impl DavNode for RootNode {
|
||||||
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
||||||
vec![Box::new(HomeNode { })]
|
vec![Box::new(HomeNode { })]
|
||||||
}
|
}
|
||||||
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<Calendar> {
|
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<All> {
|
||||||
dav::PropName(vec![
|
dav::PropName(vec![
|
||||||
dav::PropertyRequest::DisplayName,
|
dav::PropertyRequest::DisplayName,
|
||||||
dav::PropertyRequest::ResourceType,
|
dav::PropertyRequest::ResourceType,
|
||||||
dav::PropertyRequest::GetContentType,
|
dav::PropertyRequest::GetContentType,
|
||||||
|
dav::PropertyRequest::Extension(all::PropertyRequest::Acl(acl::PropertyRequest::CurrentUserPrincipal)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
fn properties(&self, _user: &ArcUser, prop: dav::PropName<Calendar>) -> Vec<dav::AnyProperty<Calendar>> {
|
fn properties(&self, user: &ArcUser, prop: dav::PropName<All>) -> Vec<dav::AnyProperty<All>> {
|
||||||
prop.0.into_iter().map(|n| match n {
|
prop.0.into_iter().map(|n| match n {
|
||||||
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName("DAV Root".to_string())),
|
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName("DAV Root".to_string())),
|
||||||
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![dav::ResourceType::Collection])),
|
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![
|
||||||
|
dav::ResourceType::Collection,
|
||||||
|
])),
|
||||||
dav::PropertyRequest::GetContentType => dav::AnyProperty::Value(dav::Property::GetContentType("httpd/unix-directory".into())),
|
dav::PropertyRequest::GetContentType => dav::AnyProperty::Value(dav::Property::GetContentType("httpd/unix-directory".into())),
|
||||||
|
dav::PropertyRequest::Extension(all::PropertyRequest::Acl(acl::PropertyRequest::CurrentUserPrincipal)) =>
|
||||||
|
dav::AnyProperty::Value(dav::Property::Extension(all::Property::Acl(acl::Property::CurrentUserPrincipal(acl::User::Authenticated(dav::Href(HomeNode{}.path(user))))))),
|
||||||
v => dav::AnyProperty::Request(v),
|
v => dav::AnyProperty::Request(v),
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
@ -507,21 +513,24 @@ impl DavNode for HomeNode {
|
||||||
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
||||||
vec![Box::new(CalendarListNode { })]
|
vec![Box::new(CalendarListNode { })]
|
||||||
}
|
}
|
||||||
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<Calendar> {
|
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<All> {
|
||||||
dav::PropName(vec![
|
dav::PropName(vec![
|
||||||
dav::PropertyRequest::DisplayName,
|
dav::PropertyRequest::DisplayName,
|
||||||
dav::PropertyRequest::ResourceType,
|
dav::PropertyRequest::ResourceType,
|
||||||
dav::PropertyRequest::GetContentType,
|
dav::PropertyRequest::GetContentType,
|
||||||
dav::PropertyRequest::Extension(cal::PropertyRequest::CalendarHomeSet),
|
dav::PropertyRequest::Extension(all::PropertyRequest::Cal(cal::PropertyRequest::CalendarHomeSet)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
fn properties(&self, user: &ArcUser, prop: dav::PropName<Calendar>) -> Vec<dav::AnyProperty<Calendar>> {
|
fn properties(&self, user: &ArcUser, prop: dav::PropName<All>) -> Vec<dav::AnyProperty<All>> {
|
||||||
prop.0.into_iter().map(|n| match n {
|
prop.0.into_iter().map(|n| match n {
|
||||||
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} home", user.username))),
|
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} home", user.username))),
|
||||||
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![dav::ResourceType::Collection])),
|
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![
|
||||||
|
dav::ResourceType::Collection,
|
||||||
|
dav::ResourceType::Extension(all::ResourceType::Acl(acl::ResourceType::Principal)),
|
||||||
|
])),
|
||||||
dav::PropertyRequest::GetContentType => dav::AnyProperty::Value(dav::Property::GetContentType("httpd/unix-directory".into())),
|
dav::PropertyRequest::GetContentType => dav::AnyProperty::Value(dav::Property::GetContentType("httpd/unix-directory".into())),
|
||||||
dav::PropertyRequest::Extension(cal::PropertyRequest::CalendarHomeSet) =>
|
dav::PropertyRequest::Extension(all::PropertyRequest::Cal(cal::PropertyRequest::CalendarHomeSet)) =>
|
||||||
dav::AnyProperty::Value(dav::Property::Extension(cal::Property::CalendarHomeSet(dav::Href(CalendarListNode{}.path(user))))),
|
dav::AnyProperty::Value(dav::Property::Extension(all::Property::Cal(cal::Property::CalendarHomeSet(dav::Href(CalendarListNode{}.path(user)))))),
|
||||||
v => dav::AnyProperty::Request(v),
|
v => dav::AnyProperty::Request(v),
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
@ -550,14 +559,14 @@ impl DavNode for CalendarListNode {
|
||||||
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
||||||
vec![Box::new(CalendarNode { name: "personal".into() })]
|
vec![Box::new(CalendarNode { name: "personal".into() })]
|
||||||
}
|
}
|
||||||
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<Calendar> {
|
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<All> {
|
||||||
dav::PropName(vec![
|
dav::PropName(vec![
|
||||||
dav::PropertyRequest::DisplayName,
|
dav::PropertyRequest::DisplayName,
|
||||||
dav::PropertyRequest::ResourceType,
|
dav::PropertyRequest::ResourceType,
|
||||||
dav::PropertyRequest::GetContentType,
|
dav::PropertyRequest::GetContentType,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
fn properties(&self, user: &ArcUser, prop: dav::PropName<Calendar>) -> Vec<dav::AnyProperty<Calendar>> {
|
fn properties(&self, user: &ArcUser, prop: dav::PropName<All>) -> Vec<dav::AnyProperty<All>> {
|
||||||
prop.0.into_iter().map(|n| match n {
|
prop.0.into_iter().map(|n| match n {
|
||||||
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} calendars", user.username))),
|
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} calendars", user.username))),
|
||||||
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![dav::ResourceType::Collection])),
|
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![dav::ResourceType::Collection])),
|
||||||
|
@ -595,19 +604,19 @@ impl DavNode for CalendarNode {
|
||||||
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
||||||
vec![Box::new(EventNode { calendar: self.name.to_string(), event_file: "something.ics".into() })]
|
vec![Box::new(EventNode { calendar: self.name.to_string(), event_file: "something.ics".into() })]
|
||||||
}
|
}
|
||||||
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<Calendar> {
|
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<All> {
|
||||||
dav::PropName(vec![
|
dav::PropName(vec![
|
||||||
dav::PropertyRequest::DisplayName,
|
dav::PropertyRequest::DisplayName,
|
||||||
dav::PropertyRequest::ResourceType,
|
dav::PropertyRequest::ResourceType,
|
||||||
dav::PropertyRequest::GetContentType,
|
dav::PropertyRequest::GetContentType,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
fn properties(&self, _user: &ArcUser, prop: dav::PropName<Calendar>) -> Vec<dav::AnyProperty<Calendar>> {
|
fn properties(&self, _user: &ArcUser, prop: dav::PropName<All>) -> Vec<dav::AnyProperty<All>> {
|
||||||
prop.0.into_iter().map(|n| match n {
|
prop.0.into_iter().map(|n| match n {
|
||||||
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} calendar", self.name))),
|
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} calendar", self.name))),
|
||||||
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![
|
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![
|
||||||
dav::ResourceType::Collection,
|
dav::ResourceType::Collection,
|
||||||
dav::ResourceType::Extension(cal::ResourceType::Calendar),
|
dav::ResourceType::Extension(all::ResourceType::Cal(cal::ResourceType::Calendar)),
|
||||||
])),
|
])),
|
||||||
//dav::PropertyRequest::GetContentType => dav::AnyProperty::Value(dav::Property::GetContentType("httpd/unix-directory".into())),
|
//dav::PropertyRequest::GetContentType => dav::AnyProperty::Value(dav::Property::GetContentType("httpd/unix-directory".into())),
|
||||||
//@FIXME seems wrong but seems to be what Thunderbird expects...
|
//@FIXME seems wrong but seems to be what Thunderbird expects...
|
||||||
|
@ -637,13 +646,13 @@ impl DavNode for EventNode {
|
||||||
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
fn children(&self, user: &ArcUser) -> Vec<Box<dyn DavNode>> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<Calendar> {
|
fn supported_properties(&self, user: &ArcUser) -> dav::PropName<All> {
|
||||||
dav::PropName(vec![
|
dav::PropName(vec![
|
||||||
dav::PropertyRequest::DisplayName,
|
dav::PropertyRequest::DisplayName,
|
||||||
dav::PropertyRequest::ResourceType,
|
dav::PropertyRequest::ResourceType,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
fn properties(&self, _user: &ArcUser, prop: dav::PropName<Calendar>) -> Vec<dav::AnyProperty<Calendar>> {
|
fn properties(&self, _user: &ArcUser, prop: dav::PropName<All>) -> Vec<dav::AnyProperty<All>> {
|
||||||
prop.0.into_iter().map(|n| match n {
|
prop.0.into_iter().map(|n| match n {
|
||||||
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} event", self.event_file))),
|
dav::PropertyRequest::DisplayName => dav::AnyProperty::Value(dav::Property::DisplayName(format!("{} event", self.event_file))),
|
||||||
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![])),
|
dav::PropertyRequest::ResourceType => dav::AnyProperty::Value(dav::Property::ResourceType(vec![])),
|
||||||
|
|
Loading…
Reference in a new issue