mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-09-10 14:04:14 +08:00
Update account name when refreshing DAV caches (closes ##1694)
This commit is contained in:
parent
854bfcb249
commit
020bcaef8b
2 changed files with 110 additions and 55 deletions
151
crates/groupware/src/cache/mod.rs
vendored
151
crates/groupware/src/cache/mod.rs
vendored
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
use crate::{
|
||||
DavResourceName, RFC_3986,
|
||||
cache::calcard::{build_scheduling_resources, path_from_scheduling, resource_from_scheduling},
|
||||
calendar::{Calendar, CalendarEvent, CalendarPreferences},
|
||||
contact::{AddressBook, ContactCard},
|
||||
|
@ -16,6 +17,7 @@ use calcard::{
|
|||
resource_from_calendar, resource_from_card, resource_from_event,
|
||||
};
|
||||
use common::{CacheSwap, DavResource, DavResources, Server, auth::AccessToken};
|
||||
use directory::backend::internal::manage::ManageDirectory;
|
||||
use file::{build_file_resources, build_nested_hierarchy, resource_from_file};
|
||||
use jmap_proto::types::collection::{Collection, SyncCollection};
|
||||
use std::{sync::Arc, time::Instant};
|
||||
|
@ -174,62 +176,41 @@ impl GroupwareCache for Server {
|
|||
return Ok(cache);
|
||||
}
|
||||
|
||||
// Build base path
|
||||
let base_path = if access_token.primary_id() == account_id {
|
||||
format!(
|
||||
"{}/{}/",
|
||||
DavResourceName::from(collection).base_path(),
|
||||
percent_encoding::utf8_percent_encode(&access_token.name, RFC_3986)
|
||||
)
|
||||
} else {
|
||||
let name = self
|
||||
.store()
|
||||
.get_principal_name(account_id)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
.unwrap_or_else(|| format!("_{account_id}"));
|
||||
format!(
|
||||
"{}/{}/",
|
||||
DavResourceName::from(collection).base_path(),
|
||||
percent_encoding::utf8_percent_encode(&name, RFC_3986)
|
||||
)
|
||||
};
|
||||
|
||||
let num_changes = changes.changes.len();
|
||||
let cache = if !matches!(collection, SyncCollection::CalendarScheduling) {
|
||||
let mut updated_resources = AHashMap::with_capacity(8);
|
||||
let has_no_children = collection == SyncCollection::FileNode;
|
||||
|
||||
for change in changes.changes {
|
||||
match change {
|
||||
Change::InsertItem(id) | Change::UpdateItem(id) => {
|
||||
let document_id = id as u32;
|
||||
if let Some(archive) = self
|
||||
.get_archive(account_id, collection.collection(false), document_id)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
{
|
||||
updated_resources.insert(
|
||||
(has_no_children, document_id),
|
||||
Some(resource_from_archive(
|
||||
archive,
|
||||
document_id,
|
||||
collection,
|
||||
false,
|
||||
)?),
|
||||
);
|
||||
} else {
|
||||
updated_resources.insert((has_no_children, document_id), None);
|
||||
}
|
||||
}
|
||||
Change::DeleteItem(id) => {
|
||||
updated_resources.insert((has_no_children, id as u32), None);
|
||||
}
|
||||
Change::InsertContainer(id) | Change::UpdateContainer(id) => {
|
||||
let document_id = id as u32;
|
||||
if let Some(archive) = self
|
||||
.get_archive(account_id, collection.collection(true), document_id)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
{
|
||||
updated_resources.insert(
|
||||
(true, document_id),
|
||||
Some(resource_from_archive(
|
||||
archive,
|
||||
document_id,
|
||||
collection,
|
||||
true,
|
||||
)?),
|
||||
);
|
||||
} else {
|
||||
updated_resources.insert((true, document_id), None);
|
||||
}
|
||||
}
|
||||
Change::DeleteContainer(id) => {
|
||||
updated_resources.insert((true, id as u32), None);
|
||||
}
|
||||
Change::UpdateContainerProperty(_) => (),
|
||||
}
|
||||
}
|
||||
process_changes(
|
||||
self,
|
||||
account_id,
|
||||
collection,
|
||||
has_no_children,
|
||||
&mut updated_resources,
|
||||
changes.changes,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut rebuild_hierarchy = false;
|
||||
let mut resources = Vec::with_capacity(cache.resources.len());
|
||||
|
@ -260,7 +241,7 @@ impl GroupwareCache for Server {
|
|||
|
||||
if rebuild_hierarchy {
|
||||
let mut cache = DavResources {
|
||||
base_path: cache.base_path.clone(),
|
||||
base_path,
|
||||
paths: Default::default(),
|
||||
resources,
|
||||
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
||||
|
@ -280,7 +261,7 @@ impl GroupwareCache for Server {
|
|||
cache
|
||||
} else {
|
||||
DavResources {
|
||||
base_path: cache.base_path.clone(),
|
||||
base_path,
|
||||
paths: cache.paths.clone(),
|
||||
resources,
|
||||
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
||||
|
@ -323,7 +304,7 @@ impl GroupwareCache for Server {
|
|||
}
|
||||
|
||||
DavResources {
|
||||
base_path: cache.base_path.clone(),
|
||||
base_path,
|
||||
paths,
|
||||
resources,
|
||||
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
||||
|
@ -440,6 +421,68 @@ impl GroupwareCache for Server {
|
|||
}
|
||||
}
|
||||
|
||||
async fn process_changes(
|
||||
server: &Server,
|
||||
account_id: u32,
|
||||
collection: SyncCollection,
|
||||
has_no_children: bool,
|
||||
updated_resources: &mut AHashMap<(bool, u32), Option<DavResource>>,
|
||||
changes: Vec<Change>,
|
||||
) -> trc::Result<()> {
|
||||
for change in changes {
|
||||
match change {
|
||||
Change::InsertItem(id) | Change::UpdateItem(id) => {
|
||||
let document_id = id as u32;
|
||||
if let Some(archive) = server
|
||||
.get_archive(account_id, collection.collection(false), document_id)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
{
|
||||
updated_resources.insert(
|
||||
(has_no_children, document_id),
|
||||
Some(resource_from_archive(
|
||||
archive,
|
||||
document_id,
|
||||
collection,
|
||||
false,
|
||||
)?),
|
||||
);
|
||||
} else {
|
||||
updated_resources.insert((has_no_children, document_id), None);
|
||||
}
|
||||
}
|
||||
Change::DeleteItem(id) => {
|
||||
updated_resources.insert((has_no_children, id as u32), None);
|
||||
}
|
||||
Change::InsertContainer(id) | Change::UpdateContainer(id) => {
|
||||
let document_id = id as u32;
|
||||
if let Some(archive) = server
|
||||
.get_archive(account_id, collection.collection(true), document_id)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
{
|
||||
updated_resources.insert(
|
||||
(true, document_id),
|
||||
Some(resource_from_archive(
|
||||
archive,
|
||||
document_id,
|
||||
collection,
|
||||
true,
|
||||
)?),
|
||||
);
|
||||
} else {
|
||||
updated_resources.insert((true, document_id), None);
|
||||
}
|
||||
}
|
||||
Change::DeleteContainer(id) => {
|
||||
updated_resources.insert((true, id as u32), None);
|
||||
}
|
||||
Change::UpdateContainerProperty(_) => (),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn full_cache_build(
|
||||
server: &Server,
|
||||
account_id: u32,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use calcard::common::timezone::Tz;
|
||||
use common::DavResources;
|
||||
use jmap_proto::types::collection::Collection;
|
||||
use jmap_proto::types::collection::{Collection, SyncCollection};
|
||||
use percent_encoding::{AsciiSet, CONTROLS};
|
||||
|
||||
pub mod cache;
|
||||
|
@ -124,6 +124,18 @@ impl From<Collection> for DavResourceName {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<SyncCollection> for DavResourceName {
|
||||
fn from(value: SyncCollection) -> Self {
|
||||
match value {
|
||||
SyncCollection::AddressBook => DavResourceName::Card,
|
||||
SyncCollection::Calendar => DavResourceName::Cal,
|
||||
SyncCollection::FileNode => DavResourceName::File,
|
||||
SyncCollection::CalendarScheduling => DavResourceName::Scheduling,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DavCalendarResource {
|
||||
fn calendar_default_tz(&self, calendar_id: u32) -> Option<Tz>;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue