/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use crate::{ responses::XmlEscape, schema::{ Namespace, Namespaces, property::{DavProperty, Privilege}, response::{ Ace, AclRestrictions, GrantDeny, Href, List, Principal, PrincipalSearchProperty, PrincipalSearchPropertySet, RequiredPrincipal, Resource, SupportedPrivilege, }, }, }; use std::fmt::Display; impl Display for SupportedPrivilege { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.privilege)?; if self.abstract_ { write!(f, "")?; } write!(f, "")?; self.description.write_escaped_to(f)?; write!( f, "{}", self.supported_privilege ) } } impl SupportedPrivilege { pub fn new(privilege: Privilege, description: impl Into) -> Self { SupportedPrivilege { privilege, abstract_: false, description: description.into(), supported_privilege: List(vec![]), } } pub fn with_abstract(mut self) -> Self { self.abstract_ = true; self } pub fn with_supported_privilege(mut self, supported_privilege: SupportedPrivilege) -> Self { self.supported_privilege.0.push(supported_privilege); self } pub fn with_opt_supported_privilege( mut self, supported_privilege: Option, ) -> Self { if let Some(supported_privilege) = supported_privilege { self.supported_privilege.0.push(supported_privilege); } self } pub fn all_privileges(is_calendar: bool) -> SupportedPrivilege { SupportedPrivilege::new(Privilege::All, "Any operation") .with_abstract() .with_supported_privilege( SupportedPrivilege::new(Privilege::Read, "Read objects").with_supported_privilege( SupportedPrivilege::new( Privilege::ReadCurrentUserPrivilegeSet, "Read current user privileges", ), ), ) .with_supported_privilege( SupportedPrivilege::new(Privilege::Write, "Write objects") .with_supported_privilege(SupportedPrivilege::new( Privilege::WriteProperties, "Write properties", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::WriteContent, "Write object contents", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::Bind, "Add resources to a collection", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::Unbind, "Remove resources from a collection", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::Unlock, "Unlock resources", )), ) .with_supported_privilege(SupportedPrivilege::new(Privilege::ReadAcl, "Read ACL")) .with_supported_privilege(SupportedPrivilege::new(Privilege::WriteAcl, "Write ACL")) .with_opt_supported_privilege((is_calendar).then(|| { SupportedPrivilege::new(Privilege::ReadFreeBusy, "Read free/busy information") })) } pub fn all_scheduling_privileges(is_inbox: bool) -> SupportedPrivilege { let privilege = SupportedPrivilege::new(Privilege::All, "Any operation") .with_abstract() .with_supported_privilege( SupportedPrivilege::new(Privilege::Read, "Read objects").with_supported_privilege( SupportedPrivilege::new( Privilege::ReadCurrentUserPrivilegeSet, "Read current user privileges", ), ), ); if is_inbox { privilege.with_supported_privilege( SupportedPrivilege::new( Privilege::ScheduleDeliver, "Deliver calendar scheduling messages", ) .with_supported_privilege(SupportedPrivilege::new( Privilege::ScheduleDeliverInvite, "Deliver calendar scheduling invites", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::ScheduleDeliverReply, "Deliver calendar scheduling replies", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::ScheduleQueryFreeBusy, "Query free/busy information", )), ) } else { privilege.with_supported_privilege( SupportedPrivilege::new( Privilege::ScheduleSend, "Send calendar scheduling messages", ) .with_supported_privilege(SupportedPrivilege::new( Privilege::ScheduleSendInvite, "Send calendar scheduling invites", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::ScheduleSendReply, "Send calendar scheduling replies", )) .with_supported_privilege(SupportedPrivilege::new( Privilege::ScheduleSendFreeBusy, "Send free/busy information", )), ) } } } impl Display for Ace { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "")?; if self.invert { write!(f, "")?; } self.principal.fmt(f)?; if self.invert { write!(f, "")?; } self.grant_deny.fmt(f)?; if self.protected { write!(f, "")?; } if let Some(inherited) = &self.inherited { write!(f, "")?; inherited.fmt(f)?; write!(f, "")?; } write!(f, "") } } impl Display for Principal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "")?; match self { Principal::Href(href) => href.fmt(f), Principal::Response(response) => response.fmt(f), Principal::All => "".fmt(f), Principal::Authenticated => "".fmt(f), Principal::Unauthenticated => "".fmt(f), Principal::Property(property) => { write!(f, "{}", property) } Principal::Self_ => "".fmt(f), }?; write!(f, "") } } impl Display for GrantDeny { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { GrantDeny::Grant(privileges) => { write!(f, "")?; privileges.fmt(f)?; write!(f, "") } GrantDeny::Deny(privileges) => { write!(f, "")?; privileges.fmt(f)?; write!(f, "") } } } } impl Display for AclRestrictions { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if self.grant_only { write!(f, "")?; } if self.no_invert { write!(f, "")?; } if self.deny_before_grant { write!(f, "")?; } if let Some(required_principal) = &self.required_principal { required_principal.fmt(f)?; } Ok(()) } } impl Display for RequiredPrincipal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "")?; match self { RequiredPrincipal::All => "".fmt(f)?, RequiredPrincipal::Authenticated => "".fmt(f)?, RequiredPrincipal::Unauthenticated => "".fmt(f)?, RequiredPrincipal::Self_ => "".fmt(f)?, RequiredPrincipal::Href(hrefs) => hrefs.fmt(f)?, RequiredPrincipal::Property(properties) => { for property in properties { write!(f, "{}", property)?; } } } write!(f, "") } } impl Display for Privilege { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Privilege::Read => "".fmt(f), Privilege::Write => "".fmt(f), Privilege::WriteProperties => "".fmt(f), Privilege::WriteContent => "".fmt(f), Privilege::Unlock => "".fmt(f), Privilege::ReadAcl => "".fmt(f), Privilege::ReadCurrentUserPrivilegeSet => { "".fmt(f) } Privilege::WriteAcl => "".fmt(f), Privilege::Bind => "".fmt(f), Privilege::Unbind => "".fmt(f), Privilege::All => "".fmt(f), Privilege::ReadFreeBusy => "".fmt(f), Privilege::ScheduleDeliver => "".fmt(f), Privilege::ScheduleDeliverInvite => { "".fmt(f) } Privilege::ScheduleDeliverReply => { "".fmt(f) } Privilege::ScheduleQueryFreeBusy => { "".fmt(f) } Privilege::ScheduleSend => "".fmt(f), Privilege::ScheduleSendInvite => { "".fmt(f) } Privilege::ScheduleSendReply => { "".fmt(f) } Privilege::ScheduleSendFreeBusy => { "".fmt(f) } } } } impl Display for Resource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{}{}", self.href, self.privilege ) } } impl Display for PrincipalSearchPropertySet { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "")?; write!( f, "{}", self.namespaces, self.properties ) } } impl Display for PrincipalSearchProperty { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{}", self.name )?; write!( f, "{}", self.description ) } } impl Resource { pub fn new(href: impl Into, privilege: Privilege) -> Self { Resource { href: Href(href.into()), privilege, } } } impl PrincipalSearchPropertySet { pub fn new(properties: Vec) -> Self { PrincipalSearchPropertySet { namespaces: Namespaces::default(), properties: List(properties), } } pub fn with_namespace(mut self, namespace: Namespace) -> Self { self.namespaces.set(namespace); self } } impl PrincipalSearchProperty { pub fn new(name: impl Into, description: impl Into) -> Self { PrincipalSearchProperty { name: name.into(), description: description.into(), } } } impl Ace { pub fn new(principal: Principal, grant_deny: GrantDeny) -> Self { Ace { principal, invert: false, grant_deny, protected: false, inherited: None, } } pub fn with_invert(mut self) -> Self { self.invert = true; self } pub fn with_protected(mut self) -> Self { self.protected = true; self } pub fn with_inherited(mut self, inherited: impl Into) -> Self { self.inherited = Some(Href(inherited.into())); self } } impl GrantDeny { pub fn grant(privileges: Vec) -> Self { GrantDeny::Grant(List(privileges)) } pub fn deny(privileges: Vec) -> Self { GrantDeny::Deny(List(privileges)) } } impl AclRestrictions { pub fn new() -> Self { Self::default() } pub fn with_grant_only(mut self) -> Self { self.grant_only = true; self } pub fn with_no_invert(mut self) -> Self { self.no_invert = true; self } pub fn with_deny_before_grant(mut self) -> Self { self.deny_before_grant = true; self } pub fn with_required_principal(mut self, required_principal: RequiredPrincipal) -> Self { self.required_principal = Some(required_principal); self } }