Add per-user CardDAV properties + fix per-user CalDAV properties (fixes #2058)
This commit is contained in:
@@ -80,4 +80,14 @@ impl DavResources {
|
||||
|
||||
account_acls
|
||||
}
|
||||
|
||||
pub fn document_ids(&self, is_container: bool) -> impl Iterator<Item = u32> {
|
||||
self.resources.iter().filter_map(move |resource| {
|
||||
if resource.is_container() == is_container {
|
||||
Some(resource.document_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ impl CalendarMkColRequestHandler for Server {
|
||||
let mut prop_stat = PropStatBuilder::default();
|
||||
is_mkcalendar = mkcol.is_mkcalendar;
|
||||
if !self.apply_calendar_properties(
|
||||
account_id,
|
||||
access_token,
|
||||
&mut calendar,
|
||||
false,
|
||||
mkcol.props,
|
||||
|
||||
@@ -47,7 +47,7 @@ pub(crate) trait CalendarPropPatchRequestHandler: Sync + Send {
|
||||
|
||||
fn apply_calendar_properties(
|
||||
&self,
|
||||
account_id: u32,
|
||||
access_token: &AccessToken,
|
||||
calendar: &mut Calendar,
|
||||
is_update: bool,
|
||||
properties: Vec<DavPropertyValue>,
|
||||
@@ -149,7 +149,7 @@ impl CalendarPropPatchRequestHandler for Server {
|
||||
// Remove properties
|
||||
if !request.set_first && !request.remove.is_empty() {
|
||||
remove_calendar_properties(
|
||||
account_id,
|
||||
access_token,
|
||||
&mut new_calendar,
|
||||
std::mem::take(&mut request.remove),
|
||||
&mut items,
|
||||
@@ -158,7 +158,7 @@ impl CalendarPropPatchRequestHandler for Server {
|
||||
|
||||
// Set properties
|
||||
is_success = self.apply_calendar_properties(
|
||||
account_id,
|
||||
access_token,
|
||||
&mut new_calendar,
|
||||
true,
|
||||
request.set,
|
||||
@@ -168,7 +168,7 @@ impl CalendarPropPatchRequestHandler for Server {
|
||||
// Remove properties
|
||||
if is_success && !request.remove.is_empty() {
|
||||
remove_calendar_properties(
|
||||
account_id,
|
||||
access_token,
|
||||
&mut new_calendar,
|
||||
request.remove,
|
||||
&mut items,
|
||||
@@ -238,7 +238,7 @@ impl CalendarPropPatchRequestHandler for Server {
|
||||
|
||||
fn apply_calendar_properties(
|
||||
&self,
|
||||
account_id: u32,
|
||||
access_token: &AccessToken,
|
||||
calendar: &mut Calendar,
|
||||
is_update: bool,
|
||||
properties: Vec<DavPropertyValue>,
|
||||
@@ -250,7 +250,7 @@ impl CalendarPropPatchRequestHandler for Server {
|
||||
match (&property.property, property.value) {
|
||||
(DavProperty::WebDav(WebDavProperty::DisplayName), DavValue::String(name)) => {
|
||||
if name.len() <= self.core.groupware.live_property_size {
|
||||
calendar.preferences_mut(account_id).name = name;
|
||||
calendar.preferences_mut(access_token).name = name;
|
||||
items.insert_ok(property.property);
|
||||
} else {
|
||||
items.insert_error_with_description(
|
||||
@@ -266,7 +266,7 @@ impl CalendarPropPatchRequestHandler for Server {
|
||||
DavValue::String(name),
|
||||
) => {
|
||||
if name.len() <= self.core.groupware.live_property_size {
|
||||
calendar.preferences_mut(account_id).description = Some(name);
|
||||
calendar.preferences_mut(access_token).description = Some(name);
|
||||
items.insert_ok(property.property);
|
||||
} else {
|
||||
items.insert_error_with_description(
|
||||
@@ -298,13 +298,14 @@ impl CalendarPropPatchRequestHandler for Server {
|
||||
);
|
||||
has_errors = true;
|
||||
} else {
|
||||
calendar.preferences_mut(account_id).time_zone = Timezone::Custom(ical);
|
||||
calendar.preferences_mut(access_token).time_zone = Timezone::Custom(ical);
|
||||
items.insert_ok(property.property);
|
||||
}
|
||||
}
|
||||
(DavProperty::CalDav(CalDavProperty::TimezoneId), DavValue::String(tz_id)) => {
|
||||
if let Ok(tz) = Tz::from_str(&tz_id) {
|
||||
calendar.preferences_mut(account_id).time_zone = Timezone::IANA(tz.as_id());
|
||||
calendar.preferences_mut(access_token).time_zone =
|
||||
Timezone::IANA(tz.as_id());
|
||||
items.insert_ok(property.property);
|
||||
} else {
|
||||
items.insert_precondition_failed_with_description(
|
||||
@@ -472,7 +473,7 @@ fn remove_event_properties(
|
||||
}
|
||||
|
||||
fn remove_calendar_properties(
|
||||
account_id: u32,
|
||||
access_token: &AccessToken,
|
||||
calendar: &mut Calendar,
|
||||
properties: Vec<DavProperty>,
|
||||
items: &mut PropStatBuilder,
|
||||
@@ -480,12 +481,12 @@ fn remove_calendar_properties(
|
||||
for property in properties {
|
||||
match &property {
|
||||
DavProperty::CalDav(CalDavProperty::CalendarDescription) => {
|
||||
calendar.preferences_mut(account_id).description = None;
|
||||
calendar.preferences_mut(access_token).description = None;
|
||||
items.insert_with_status(property, StatusCode::NO_CONTENT);
|
||||
}
|
||||
DavProperty::CalDav(CalDavProperty::CalendarTimezone)
|
||||
| DavProperty::CalDav(CalDavProperty::TimezoneId) => {
|
||||
calendar.preferences_mut(account_id).time_zone = Timezone::Default;
|
||||
calendar.preferences_mut(access_token).time_zone = Timezone::Default;
|
||||
items.insert_with_status(property, StatusCode::NO_CONTENT);
|
||||
}
|
||||
DavProperty::DeadProperty(dead) => {
|
||||
|
||||
@@ -18,7 +18,7 @@ use dav_proto::{Depth, RequestHeaders};
|
||||
use groupware::{
|
||||
DestroyArchive,
|
||||
cache::GroupwareCache,
|
||||
contact::{AddressBook, ContactCard},
|
||||
contact::{AddressBook, AddressBookPreferences, ContactCard},
|
||||
};
|
||||
use http_proto::HttpResponse;
|
||||
use hyper::StatusCode;
|
||||
@@ -759,10 +759,17 @@ async fn copy_container(
|
||||
.caused_by(trc::location!())?;
|
||||
}
|
||||
|
||||
let preference = book.preferences.into_iter().next().unwrap();
|
||||
book.name = new_name.to_string();
|
||||
book.subscribers.clear();
|
||||
book.acls.clear();
|
||||
book.is_default = false;
|
||||
book.preferences = vec![AddressBookPreferences {
|
||||
account_id: to_account_id,
|
||||
name: preference.name,
|
||||
description: preference.description,
|
||||
sort_order: 0,
|
||||
is_default: false,
|
||||
}];
|
||||
|
||||
let is_overwrite = to_document_id.is_some();
|
||||
let to_document_id = if let Some(to_document_id) = to_document_id {
|
||||
|
||||
@@ -89,7 +89,13 @@ impl CardMkColRequestHandler for Server {
|
||||
let mut return_prop_stat = None;
|
||||
if let Some(mkcol) = request {
|
||||
let mut prop_stat = PropStatBuilder::default();
|
||||
if !self.apply_addressbook_properties(&mut book, false, mkcol.props, &mut prop_stat) {
|
||||
if !self.apply_addressbook_properties(
|
||||
access_token,
|
||||
&mut book,
|
||||
false,
|
||||
mkcol.props,
|
||||
&mut prop_stat,
|
||||
) {
|
||||
return Ok(HttpResponse::new(StatusCode::FORBIDDEN).with_xml_body(
|
||||
MkColResponse::new(prop_stat.build())
|
||||
.with_namespace(Namespace::CardDav)
|
||||
|
||||
@@ -45,6 +45,7 @@ pub(crate) trait CardPropPatchRequestHandler: Sync + Send {
|
||||
|
||||
fn apply_addressbook_properties(
|
||||
&self,
|
||||
access_token: &AccessToken,
|
||||
address_book: &mut AddressBook,
|
||||
is_update: bool,
|
||||
properties: Vec<DavPropertyValue>,
|
||||
@@ -146,6 +147,7 @@ impl CardPropPatchRequestHandler for Server {
|
||||
// Remove properties
|
||||
if !request.set_first && !request.remove.is_empty() {
|
||||
remove_addressbook_properties(
|
||||
access_token,
|
||||
&mut new_book,
|
||||
std::mem::take(&mut request.remove),
|
||||
&mut items,
|
||||
@@ -153,12 +155,22 @@ impl CardPropPatchRequestHandler for Server {
|
||||
}
|
||||
|
||||
// Set properties
|
||||
is_success =
|
||||
self.apply_addressbook_properties(&mut new_book, true, request.set, &mut items);
|
||||
is_success = self.apply_addressbook_properties(
|
||||
access_token,
|
||||
&mut new_book,
|
||||
true,
|
||||
request.set,
|
||||
&mut items,
|
||||
);
|
||||
|
||||
// Remove properties
|
||||
if is_success && !request.remove.is_empty() {
|
||||
remove_addressbook_properties(&mut new_book, request.remove, &mut items);
|
||||
remove_addressbook_properties(
|
||||
access_token,
|
||||
&mut new_book,
|
||||
request.remove,
|
||||
&mut items,
|
||||
);
|
||||
}
|
||||
|
||||
if is_success {
|
||||
@@ -224,6 +236,7 @@ impl CardPropPatchRequestHandler for Server {
|
||||
|
||||
fn apply_addressbook_properties(
|
||||
&self,
|
||||
access_token: &AccessToken,
|
||||
address_book: &mut AddressBook,
|
||||
is_update: bool,
|
||||
properties: Vec<DavPropertyValue>,
|
||||
@@ -235,7 +248,7 @@ impl CardPropPatchRequestHandler for Server {
|
||||
match (&property.property, property.value) {
|
||||
(DavProperty::WebDav(WebDavProperty::DisplayName), DavValue::String(name)) => {
|
||||
if name.len() <= self.core.groupware.live_property_size {
|
||||
address_book.display_name = Some(name);
|
||||
address_book.preferences_mut(access_token).name = name;
|
||||
items.insert_ok(property.property);
|
||||
} else {
|
||||
items.insert_error_with_description(
|
||||
@@ -251,7 +264,7 @@ impl CardPropPatchRequestHandler for Server {
|
||||
DavValue::String(name),
|
||||
) => {
|
||||
if name.len() <= self.core.groupware.live_property_size {
|
||||
address_book.description = Some(name);
|
||||
address_book.preferences_mut(access_token).description = Some(name);
|
||||
items.insert_ok(property.property);
|
||||
} else {
|
||||
items.insert_error_with_description(
|
||||
@@ -418,6 +431,7 @@ fn remove_card_properties(
|
||||
}
|
||||
|
||||
fn remove_addressbook_properties(
|
||||
access_token: &AccessToken,
|
||||
book: &mut AddressBook,
|
||||
properties: Vec<DavProperty>,
|
||||
items: &mut PropStatBuilder,
|
||||
@@ -425,13 +439,13 @@ fn remove_addressbook_properties(
|
||||
for property in properties {
|
||||
match &property {
|
||||
DavProperty::CardDav(CardDavProperty::AddressbookDescription) => {
|
||||
book.description = None;
|
||||
book.preferences_mut(access_token).description = None;
|
||||
items.insert_with_status(property, StatusCode::NO_CONTENT);
|
||||
}
|
||||
DavProperty::WebDav(WebDavProperty::DisplayName) => {
|
||||
/*DavProperty::WebDav(WebDavProperty::DisplayName) => {
|
||||
book.display_name = None;
|
||||
items.insert_with_status(property, StatusCode::NO_CONTENT);
|
||||
}
|
||||
}*/
|
||||
DavProperty::DeadProperty(dead) => {
|
||||
book.dead_properties.remove_element(dead);
|
||||
items.insert_with_status(property, StatusCode::NO_CONTENT);
|
||||
|
||||
@@ -8,6 +8,7 @@ use calcard::{
|
||||
icalendar::{ICalendarComponentType, ICalendarParameterName, ICalendarProperty},
|
||||
vcard::{VCardParameterName, VCardVersion},
|
||||
};
|
||||
use common::auth::AccessToken;
|
||||
use dav_proto::{
|
||||
Depth, RequestHeaders, Return,
|
||||
schema::{
|
||||
@@ -418,13 +419,15 @@ impl<'x> ArchivedResource<'x> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_name(&self, account_id: u32) -> Option<&str> {
|
||||
pub fn display_name(&self, access_token: &AccessToken) -> Option<&str> {
|
||||
match self {
|
||||
ArchivedResource::Calendar(archive) => {
|
||||
Some(archive.inner.preferences(account_id).name.as_str())
|
||||
Some(archive.inner.preferences(access_token).name.as_str())
|
||||
}
|
||||
ArchivedResource::CalendarEvent(archive) => archive.inner.display_name.as_deref(),
|
||||
ArchivedResource::AddressBook(archive) => archive.inner.display_name.as_deref(),
|
||||
ArchivedResource::AddressBook(archive) => {
|
||||
Some(archive.inner.preferences(access_token).name.as_str())
|
||||
}
|
||||
ArchivedResource::ContactCard(archive) => archive.inner.display_name.as_deref(),
|
||||
ArchivedResource::FileNode(archive) => archive.inner.display_name.as_deref(),
|
||||
ArchivedResource::CalendarScheduling(_)
|
||||
|
||||
@@ -408,7 +408,6 @@ impl PropFindRequestHandler for Server {
|
||||
PropFind::Prop(items) => items.clone(),
|
||||
};
|
||||
|
||||
let view_as_id = access_token.primary_id();
|
||||
let is_scheduling = collection_container == Collection::CalendarScheduling;
|
||||
'outer: for item in paths {
|
||||
let account_id = item.account_id;
|
||||
@@ -491,7 +490,7 @@ impl PropFindRequestHandler for Server {
|
||||
));
|
||||
}
|
||||
WebDavProperty::DisplayName => {
|
||||
if let Some(name) = archive.display_name(view_as_id) {
|
||||
if let Some(name) = archive.display_name(access_token) {
|
||||
fields.push(DavPropertyValue::new(
|
||||
property.clone(),
|
||||
DavValue::String(name.to_string()),
|
||||
@@ -777,11 +776,17 @@ impl PropFindRequestHandler for Server {
|
||||
(
|
||||
CardDavProperty::AddressbookDescription,
|
||||
ArchivedResource::AddressBook(book),
|
||||
) if book.inner.description.is_some() => {
|
||||
fields.push(DavPropertyValue::new(
|
||||
property.clone(),
|
||||
book.inner.description.as_ref().unwrap().to_string(),
|
||||
));
|
||||
) => {
|
||||
if let Some(desc) =
|
||||
book.inner.preferences(access_token).description.as_deref()
|
||||
{
|
||||
fields.push(DavPropertyValue::new(
|
||||
property.clone(),
|
||||
desc.to_string(),
|
||||
));
|
||||
} else {
|
||||
fields_not_found.push(DavPropertyValue::empty(property.clone()));
|
||||
}
|
||||
}
|
||||
(
|
||||
CardDavProperty::SupportedAddressData,
|
||||
@@ -844,7 +849,7 @@ impl PropFindRequestHandler for Server {
|
||||
) => {
|
||||
if let Some(desc) = calendar
|
||||
.inner
|
||||
.preferences(account_id)
|
||||
.preferences(access_token)
|
||||
.description
|
||||
.as_deref()
|
||||
{
|
||||
@@ -861,7 +866,7 @@ impl PropFindRequestHandler for Server {
|
||||
ArchivedResource::Calendar(calendar),
|
||||
) => {
|
||||
if let ArchivedTimezone::Custom(tz) =
|
||||
&calendar.inner.preferences(account_id).time_zone
|
||||
&calendar.inner.preferences(access_token).time_zone
|
||||
{
|
||||
fields.push(DavPropertyValue::new(
|
||||
property.clone(),
|
||||
@@ -873,7 +878,7 @@ impl PropFindRequestHandler for Server {
|
||||
}
|
||||
(CalDavProperty::TimezoneId, ArchivedResource::Calendar(calendar)) => {
|
||||
if let ArchivedTimezone::IANA(tz) =
|
||||
&calendar.inner.preferences(account_id).time_zone
|
||||
&calendar.inner.preferences(access_token).time_zone
|
||||
{
|
||||
fields.push(DavPropertyValue::new(
|
||||
property.clone(),
|
||||
|
||||
26
crates/groupware/src/cache/mod.rs
vendored
26
crates/groupware/src/cache/mod.rs
vendored
@@ -7,7 +7,7 @@
|
||||
use crate::{
|
||||
cache::calcard::{build_scheduling_resources, path_from_scheduling, resource_from_scheduling},
|
||||
calendar::{Calendar, CalendarEvent, CalendarPreferences},
|
||||
contact::{AddressBook, ContactCard},
|
||||
contact::{AddressBook, AddressBookPreferences, ContactCard},
|
||||
file::FileNode,
|
||||
};
|
||||
use ahash::AHashSet;
|
||||
@@ -327,17 +327,19 @@ impl GroupwareCache for Server {
|
||||
.await?;
|
||||
AddressBook {
|
||||
name: name.clone(),
|
||||
display_name: format!(
|
||||
"{} ({})",
|
||||
self.core
|
||||
.groupware
|
||||
.default_addressbook_display_name
|
||||
.as_ref()
|
||||
.unwrap_or(name),
|
||||
account_name
|
||||
)
|
||||
.into(),
|
||||
is_default: true,
|
||||
preferences: vec![AddressBookPreferences {
|
||||
account_id,
|
||||
name: format!(
|
||||
"{} ({})",
|
||||
self.core
|
||||
.groupware
|
||||
.default_addressbook_display_name
|
||||
.as_ref()
|
||||
.unwrap_or(name),
|
||||
account_name
|
||||
),
|
||||
..Default::default()
|
||||
}],
|
||||
..Default::default()
|
||||
}
|
||||
.insert(access_token, account_id, document_id, &mut batch)?;
|
||||
|
||||
@@ -12,9 +12,9 @@ pub mod itip;
|
||||
pub mod storage;
|
||||
|
||||
use calcard::icalendar::ICalendar;
|
||||
use common::DavName;
|
||||
use common::{DavName, auth::AccessToken};
|
||||
use dav_proto::schema::request::DeadProperty;
|
||||
use types::acl::{Acl, AclGrant};
|
||||
use types::acl::AclGrant;
|
||||
|
||||
#[derive(
|
||||
rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq,
|
||||
@@ -154,55 +154,12 @@ pub enum Timezone {
|
||||
Default,
|
||||
}
|
||||
|
||||
pub enum CalendarRight {
|
||||
ReadFreeBusy,
|
||||
ReadItems,
|
||||
WriteAll,
|
||||
WriteOwn,
|
||||
UpdatePrivate,
|
||||
RSVP,
|
||||
Share,
|
||||
Delete,
|
||||
}
|
||||
|
||||
impl TryFrom<Acl> for CalendarRight {
|
||||
type Error = Acl;
|
||||
|
||||
fn try_from(value: Acl) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Acl::SchedulingReadFreeBusy => Ok(CalendarRight::ReadFreeBusy),
|
||||
Acl::ReadItems => Ok(CalendarRight::ReadItems),
|
||||
Acl::Modify => Ok(CalendarRight::WriteAll),
|
||||
Acl::ModifyItemsOwn => Ok(CalendarRight::WriteOwn),
|
||||
Acl::ModifyPrivateProperties => Ok(CalendarRight::UpdatePrivate),
|
||||
Acl::SchedulingReply => Ok(CalendarRight::RSVP),
|
||||
Acl::Administer => Ok(CalendarRight::Share),
|
||||
Acl::Delete => Ok(CalendarRight::Delete),
|
||||
_ => Err(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CalendarRight> for Acl {
|
||||
fn from(value: CalendarRight) -> Self {
|
||||
match value {
|
||||
CalendarRight::ReadFreeBusy => Acl::SchedulingReadFreeBusy,
|
||||
CalendarRight::ReadItems => Acl::ReadItems,
|
||||
CalendarRight::WriteAll => Acl::Modify,
|
||||
CalendarRight::WriteOwn => Acl::ModifyItemsOwn,
|
||||
CalendarRight::UpdatePrivate => Acl::ModifyPrivateProperties,
|
||||
CalendarRight::RSVP => Acl::SchedulingReply,
|
||||
CalendarRight::Share => Acl::Administer,
|
||||
CalendarRight::Delete => Acl::Delete,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Calendar {
|
||||
pub fn preferences(&self, account_id: u32) -> &CalendarPreferences {
|
||||
pub fn preferences(&self, access_token: &AccessToken) -> &CalendarPreferences {
|
||||
if self.preferences.len() == 1 {
|
||||
&self.preferences[0]
|
||||
} else {
|
||||
let account_id = access_token.primary_id();
|
||||
self.preferences
|
||||
.iter()
|
||||
.find(|p| p.account_id == account_id)
|
||||
@@ -211,10 +168,11 @@ impl Calendar {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preferences_mut(&mut self, account_id: u32) -> &mut CalendarPreferences {
|
||||
pub fn preferences_mut(&mut self, access_token: &AccessToken) -> &mut CalendarPreferences {
|
||||
if self.preferences.len() == 1 {
|
||||
&mut self.preferences[0]
|
||||
} else {
|
||||
let account_id = access_token.primary_id();
|
||||
let idx = self
|
||||
.preferences
|
||||
.iter()
|
||||
@@ -226,10 +184,11 @@ impl Calendar {
|
||||
}
|
||||
|
||||
impl ArchivedCalendar {
|
||||
pub fn preferences(&self, account_id: u32) -> &ArchivedCalendarPreferences {
|
||||
pub fn preferences(&self, access_token: &AccessToken) -> &ArchivedCalendarPreferences {
|
||||
if self.preferences.len() == 1 {
|
||||
&self.preferences[0]
|
||||
} else {
|
||||
let account_id = access_token.primary_id();
|
||||
self.preferences
|
||||
.iter()
|
||||
.find(|p| p.account_id == account_id)
|
||||
|
||||
@@ -21,8 +21,14 @@ impl IndexableObject for AddressBook {
|
||||
},
|
||||
IndexValue::Quota {
|
||||
used: self.dead_properties.size() as u32
|
||||
+ self.display_name.as_ref().map_or(0, |n| n.len() as u32)
|
||||
+ self.description.as_ref().map_or(0, |n| n.len() as u32)
|
||||
+ self
|
||||
.preferences
|
||||
.iter()
|
||||
.map(|p| {
|
||||
p.name.len() as u32
|
||||
+ p.description.as_ref().map_or(0, |n| n.len() as u32)
|
||||
})
|
||||
.sum::<u32>()
|
||||
+ self.name.len() as u32,
|
||||
},
|
||||
IndexValue::LogContainer {
|
||||
@@ -46,8 +52,14 @@ impl IndexableObject for &ArchivedAddressBook {
|
||||
},
|
||||
IndexValue::Quota {
|
||||
used: self.dead_properties.size() as u32
|
||||
+ self.display_name.as_ref().map_or(0, |n| n.len() as u32)
|
||||
+ self.description.as_ref().map_or(0, |n| n.len() as u32)
|
||||
+ self
|
||||
.preferences
|
||||
.iter()
|
||||
.map(|p| {
|
||||
p.name.len() as u32
|
||||
+ p.description.as_ref().map_or(0, |n| n.len() as u32)
|
||||
})
|
||||
.sum::<u32>()
|
||||
+ self.name.len() as u32,
|
||||
},
|
||||
IndexValue::LogContainer {
|
||||
|
||||
@@ -8,9 +8,9 @@ pub mod index;
|
||||
pub mod storage;
|
||||
|
||||
use calcard::vcard::VCard;
|
||||
use common::DavName;
|
||||
use common::{DavName, auth::AccessToken};
|
||||
use dav_proto::schema::request::DeadProperty;
|
||||
use types::acl::{Acl, AclGrant};
|
||||
use types::acl::AclGrant;
|
||||
|
||||
#[derive(
|
||||
rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq,
|
||||
@@ -18,10 +18,7 @@ use types::acl::{Acl, AclGrant};
|
||||
#[rkyv(derive(Debug))]
|
||||
pub struct AddressBook {
|
||||
pub name: String,
|
||||
pub display_name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub sort_order: u32,
|
||||
pub is_default: bool,
|
||||
pub preferences: Vec<AddressBookPreferences>,
|
||||
pub subscribers: Vec<u32>,
|
||||
pub dead_properties: DeadProperty,
|
||||
pub acls: Vec<AclGrant>,
|
||||
@@ -29,11 +26,16 @@ pub struct AddressBook {
|
||||
pub modified: i64,
|
||||
}
|
||||
|
||||
pub enum AddressBookRight {
|
||||
Read,
|
||||
Write,
|
||||
Share,
|
||||
Delete,
|
||||
#[derive(
|
||||
rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq,
|
||||
)]
|
||||
#[rkyv(derive(Debug))]
|
||||
pub struct AddressBookPreferences {
|
||||
pub account_id: u32,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub sort_order: u32,
|
||||
pub is_default: bool,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
@@ -49,27 +51,46 @@ pub struct ContactCard {
|
||||
pub size: u32,
|
||||
}
|
||||
|
||||
impl TryFrom<Acl> for AddressBookRight {
|
||||
type Error = Acl;
|
||||
impl AddressBook {
|
||||
pub fn preferences(&self, access_token: &AccessToken) -> &AddressBookPreferences {
|
||||
if self.preferences.len() == 1 {
|
||||
&self.preferences[0]
|
||||
} else {
|
||||
let account_id = access_token.primary_id();
|
||||
self.preferences
|
||||
.iter()
|
||||
.find(|p| p.account_id == account_id)
|
||||
.or_else(|| self.preferences.first())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from(value: Acl) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Acl::Read => Ok(AddressBookRight::Read),
|
||||
Acl::Modify => Ok(AddressBookRight::Write),
|
||||
Acl::Administer => Ok(AddressBookRight::Share),
|
||||
Acl::Delete => Ok(AddressBookRight::Delete),
|
||||
_ => Err(value),
|
||||
pub fn preferences_mut(&mut self, access_token: &AccessToken) -> &mut AddressBookPreferences {
|
||||
if self.preferences.len() == 1 {
|
||||
&mut self.preferences[0]
|
||||
} else {
|
||||
let account_id = access_token.primary_id();
|
||||
let idx = self
|
||||
.preferences
|
||||
.iter()
|
||||
.position(|p| p.account_id == account_id)
|
||||
.unwrap_or(0);
|
||||
&mut self.preferences[idx]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AddressBookRight> for Acl {
|
||||
fn from(value: AddressBookRight) -> Self {
|
||||
match value {
|
||||
AddressBookRight::Read => Acl::Read,
|
||||
AddressBookRight::Write => Acl::Modify,
|
||||
AddressBookRight::Share => Acl::Administer,
|
||||
AddressBookRight::Delete => Acl::Delete,
|
||||
impl ArchivedAddressBook {
|
||||
pub fn preferences(&self, access_token: &AccessToken) -> &ArchivedAddressBookPreferences {
|
||||
if self.preferences.len() == 1 {
|
||||
&self.preferences[0]
|
||||
} else {
|
||||
let account_id = access_token.primary_id();
|
||||
self.preferences
|
||||
.iter()
|
||||
.find(|p| p.account_id == account_id)
|
||||
.or_else(|| self.preferences.first())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,24 @@ const LOCK_WAIT_TIME_ACCOUNT: u64 = 3 * 60;
|
||||
const LOCK_WAIT_TIME_CORE: u64 = 5 * 60;
|
||||
const LOCK_RETRY_TIME: Duration = Duration::from_secs(30);
|
||||
|
||||
/*
|
||||
|
||||
pub struct AddressBook {
|
||||
pub name: String,
|
||||
pub display_name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub sort_order: u32,
|
||||
pub is_default: bool,
|
||||
pub subscribers: Vec<u32>,
|
||||
pub dead_properties: DeadProperty,
|
||||
pub acls: Vec<AclGrant>,
|
||||
pub created: i64,
|
||||
pub modified: i64,
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
pub async fn try_migrate(server: &Server) -> trc::Result<()> {
|
||||
if let Some(version) = std::env::var("FORCE_MIGRATE_QUEUE")
|
||||
.ok()
|
||||
|
||||
Reference in New Issue
Block a user