mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-11-10 13:51:08 +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::{
|
use crate::{
|
||||||
|
DavResourceName, RFC_3986,
|
||||||
cache::calcard::{build_scheduling_resources, path_from_scheduling, resource_from_scheduling},
|
cache::calcard::{build_scheduling_resources, path_from_scheduling, resource_from_scheduling},
|
||||||
calendar::{Calendar, CalendarEvent, CalendarPreferences},
|
calendar::{Calendar, CalendarEvent, CalendarPreferences},
|
||||||
contact::{AddressBook, ContactCard},
|
contact::{AddressBook, ContactCard},
|
||||||
|
|
@ -16,6 +17,7 @@ use calcard::{
|
||||||
resource_from_calendar, resource_from_card, resource_from_event,
|
resource_from_calendar, resource_from_card, resource_from_event,
|
||||||
};
|
};
|
||||||
use common::{CacheSwap, DavResource, DavResources, Server, auth::AccessToken};
|
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 file::{build_file_resources, build_nested_hierarchy, resource_from_file};
|
||||||
use jmap_proto::types::collection::{Collection, SyncCollection};
|
use jmap_proto::types::collection::{Collection, SyncCollection};
|
||||||
use std::{sync::Arc, time::Instant};
|
use std::{sync::Arc, time::Instant};
|
||||||
|
|
@ -174,62 +176,41 @@ impl GroupwareCache for Server {
|
||||||
return Ok(cache);
|
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 num_changes = changes.changes.len();
|
||||||
let cache = if !matches!(collection, SyncCollection::CalendarScheduling) {
|
let cache = if !matches!(collection, SyncCollection::CalendarScheduling) {
|
||||||
let mut updated_resources = AHashMap::with_capacity(8);
|
let mut updated_resources = AHashMap::with_capacity(8);
|
||||||
let has_no_children = collection == SyncCollection::FileNode;
|
let has_no_children = collection == SyncCollection::FileNode;
|
||||||
|
|
||||||
for change in changes.changes {
|
process_changes(
|
||||||
match change {
|
self,
|
||||||
Change::InsertItem(id) | Change::UpdateItem(id) => {
|
account_id,
|
||||||
let document_id = id as u32;
|
collection,
|
||||||
if let Some(archive) = self
|
has_no_children,
|
||||||
.get_archive(account_id, collection.collection(false), document_id)
|
&mut updated_resources,
|
||||||
.await
|
changes.changes,
|
||||||
.caused_by(trc::location!())?
|
)
|
||||||
{
|
.await?;
|
||||||
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(_) => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut rebuild_hierarchy = false;
|
let mut rebuild_hierarchy = false;
|
||||||
let mut resources = Vec::with_capacity(cache.resources.len());
|
let mut resources = Vec::with_capacity(cache.resources.len());
|
||||||
|
|
@ -260,7 +241,7 @@ impl GroupwareCache for Server {
|
||||||
|
|
||||||
if rebuild_hierarchy {
|
if rebuild_hierarchy {
|
||||||
let mut cache = DavResources {
|
let mut cache = DavResources {
|
||||||
base_path: cache.base_path.clone(),
|
base_path,
|
||||||
paths: Default::default(),
|
paths: Default::default(),
|
||||||
resources,
|
resources,
|
||||||
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
||||||
|
|
@ -280,7 +261,7 @@ impl GroupwareCache for Server {
|
||||||
cache
|
cache
|
||||||
} else {
|
} else {
|
||||||
DavResources {
|
DavResources {
|
||||||
base_path: cache.base_path.clone(),
|
base_path,
|
||||||
paths: cache.paths.clone(),
|
paths: cache.paths.clone(),
|
||||||
resources,
|
resources,
|
||||||
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
||||||
|
|
@ -323,7 +304,7 @@ impl GroupwareCache for Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
DavResources {
|
DavResources {
|
||||||
base_path: cache.base_path.clone(),
|
base_path,
|
||||||
paths,
|
paths,
|
||||||
resources,
|
resources,
|
||||||
item_change_id: changes.item_change_id.unwrap_or(cache.item_change_id),
|
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(
|
async fn full_cache_build(
|
||||||
server: &Server,
|
server: &Server,
|
||||||
account_id: u32,
|
account_id: u32,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use calcard::common::timezone::Tz;
|
use calcard::common::timezone::Tz;
|
||||||
use common::DavResources;
|
use common::DavResources;
|
||||||
use jmap_proto::types::collection::Collection;
|
use jmap_proto::types::collection::{Collection, SyncCollection};
|
||||||
use percent_encoding::{AsciiSet, CONTROLS};
|
use percent_encoding::{AsciiSet, CONTROLS};
|
||||||
|
|
||||||
pub mod cache;
|
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 {
|
pub trait DavCalendarResource {
|
||||||
fn calendar_default_tz(&self, calendar_id: u32) -> Option<Tz>;
|
fn calendar_default_tz(&self, calendar_id: u32) -> Option<Tz>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue