JMAP Registry API implementation - part 2
This commit is contained in:
@@ -21,20 +21,24 @@ use common::{
|
||||
auth::{AccountInfo, AccountTenantIds},
|
||||
storage::index::ObjectIndexBuilder,
|
||||
};
|
||||
use registry::{
|
||||
pickle::Pickle,
|
||||
schema::structs::{Task, TaskCalendarAlarmEmail, TaskCalendarAlarmNotification, TaskStatus},
|
||||
types::{EnumImpl, datetime::UTCDateTime},
|
||||
};
|
||||
use store::{
|
||||
IterateParams, U16_LEN, U32_LEN, U64_LEN, ValueKey,
|
||||
IterateParams, SerializeInfallible, U32_LEN, ValueKey,
|
||||
roaring::RoaringBitmap,
|
||||
write::{
|
||||
AlignedBytes, Archive, BatchBuilder, IndexPropertyClass, TaskEpoch, TaskQueueClass,
|
||||
ValueClass,
|
||||
key::{DeserializeBigEndian, KeySerializer},
|
||||
now,
|
||||
AlignedBytes, Archive, BatchBuilder, IndexPropertyClass, Operation, TaskQueueClass,
|
||||
ValueClass, ValueOp, key::DeserializeBigEndian, now,
|
||||
},
|
||||
};
|
||||
use trc::AddContext;
|
||||
use types::{
|
||||
collection::{Collection, VanishedCollection},
|
||||
field::CalendarNotificationField,
|
||||
id::Id,
|
||||
};
|
||||
|
||||
pub trait ItipAutoExpunge: Sync + Send {
|
||||
@@ -526,52 +530,70 @@ impl DestroyArchive<Archive<&ArchivedCalendarEventNotification>> {
|
||||
}
|
||||
|
||||
impl CalendarAlarm {
|
||||
pub fn write_task(&self, batch: &mut BatchBuilder) {
|
||||
match &self.typ {
|
||||
pub fn build_write_ops(&self, account_id: u32, document_id: u32) -> [Operation; 2] {
|
||||
let task = match &self.typ {
|
||||
CalendarAlarmType::Email {
|
||||
event_start,
|
||||
event_start_tz,
|
||||
event_end,
|
||||
event_end_tz,
|
||||
} => {
|
||||
batch.set(
|
||||
ValueClass::TaskQueue(TaskQueueClass::SendAlarm {
|
||||
due: TaskEpoch::new(self.alarm_time as u64),
|
||||
event_id: self.event_id,
|
||||
alarm_id: self.alarm_id,
|
||||
is_email_alert: true,
|
||||
}),
|
||||
KeySerializer::new((U64_LEN * 2) + (U16_LEN * 2))
|
||||
.write(*event_start as u64)
|
||||
.write(*event_end as u64)
|
||||
.write(*event_start_tz)
|
||||
.write(*event_end_tz)
|
||||
.finalize(),
|
||||
);
|
||||
}
|
||||
} => Task::CalendarAlarmEmail(TaskCalendarAlarmEmail {
|
||||
account_id: account_id.into(),
|
||||
document_id: document_id.into(),
|
||||
alarm_id: self.alarm_id.into(),
|
||||
event_id: self.event_id.into(),
|
||||
event_end: UTCDateTime::from_timestamp(*event_end),
|
||||
event_end_tz: (*event_end_tz).into(),
|
||||
event_start: UTCDateTime::from_timestamp(*event_start),
|
||||
event_start_tz: (*event_start_tz).into(),
|
||||
status: TaskStatus::at(self.alarm_time),
|
||||
}),
|
||||
CalendarAlarmType::Display { recurrence_id } => {
|
||||
batch.set(
|
||||
ValueClass::TaskQueue(TaskQueueClass::SendAlarm {
|
||||
due: TaskEpoch::new(self.alarm_time as u64),
|
||||
event_id: self.event_id,
|
||||
alarm_id: self.alarm_id,
|
||||
is_email_alert: false,
|
||||
}),
|
||||
KeySerializer::new(U64_LEN)
|
||||
.write(recurrence_id.unwrap_or_default() as u64)
|
||||
.finalize(),
|
||||
);
|
||||
Task::CalendarAlarmNotification(TaskCalendarAlarmNotification {
|
||||
account_id: account_id.into(),
|
||||
document_id: document_id.into(),
|
||||
alarm_id: self.alarm_id.into(),
|
||||
event_id: self.event_id.into(),
|
||||
recurrence_id: *recurrence_id,
|
||||
status: TaskStatus::at(self.alarm_time),
|
||||
})
|
||||
}
|
||||
};
|
||||
let id = Id::from_parts(account_id, document_id).id();
|
||||
[
|
||||
Operation::Value {
|
||||
class: ValueClass::TaskQueue(TaskQueueClass::Due {
|
||||
id,
|
||||
due: self.alarm_time as u64,
|
||||
}),
|
||||
op: ValueOp::Set(task.object_type().to_id().serialize()),
|
||||
},
|
||||
Operation::Value {
|
||||
class: ValueClass::TaskQueue(TaskQueueClass::Task { id }),
|
||||
op: ValueOp::Set(task.to_pickled_vec()),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
pub fn write_task(&self, batch: &mut BatchBuilder) {
|
||||
let account_id = batch.last_account_id().unwrap();
|
||||
let document_id = batch.last_document_id().unwrap();
|
||||
|
||||
for op in self.build_write_ops(account_id, document_id) {
|
||||
batch.any_op(op);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_task(&self, batch: &mut BatchBuilder) {
|
||||
batch.clear(ValueClass::TaskQueue(TaskQueueClass::SendAlarm {
|
||||
due: TaskEpoch::new(self.alarm_time as u64),
|
||||
event_id: self.event_id,
|
||||
alarm_id: self.alarm_id,
|
||||
is_email_alert: matches!(self.typ, CalendarAlarmType::Email { .. }),
|
||||
}));
|
||||
let account_id = batch.last_account_id().unwrap();
|
||||
let document_id = batch.last_document_id().unwrap();
|
||||
let id = Id::from_parts(account_id, document_id).id();
|
||||
batch
|
||||
.clear(ValueClass::TaskQueue(TaskQueueClass::Task { id }))
|
||||
.clear(ValueClass::TaskQueue(TaskQueueClass::Due {
|
||||
id,
|
||||
due: self.alarm_time as u64,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::scheduling::{ArchivedItipSummary, ItipMessage, ItipMessages};
|
||||
use crate::scheduling::{ItipMessage, ItipMessages, ItipSummary};
|
||||
use calcard::{
|
||||
common::{IanaString, PartialDateTime},
|
||||
icalendar::{
|
||||
@@ -14,11 +14,10 @@ use calcard::{
|
||||
},
|
||||
};
|
||||
use common::PROD_ID;
|
||||
use store::{
|
||||
Serialize,
|
||||
write::{Archiver, BatchBuilder, TaskEpoch, TaskQueueClass, ValueClass},
|
||||
use registry::schema::structs::{
|
||||
Task, TaskCalendarItipContents, TaskCalendarItipMessage, TaskStatus,
|
||||
};
|
||||
use trc::AddContext;
|
||||
use store::write::BatchBuilder;
|
||||
|
||||
pub(crate) fn itip_build_envelope(method: ICalendarMethod) -> ICalendarComponent {
|
||||
ICalendarComponent {
|
||||
@@ -273,28 +272,26 @@ pub(crate) fn can_attendee_modify_property(
|
||||
impl ItipMessages {
|
||||
pub fn new(messages: Vec<ItipMessage<ICalendar>>) -> Self {
|
||||
ItipMessages {
|
||||
messages: messages.into_iter().map(|m| m.into()).collect(),
|
||||
messages: messages
|
||||
.into_iter()
|
||||
.map(|m| TaskCalendarItipContents {
|
||||
from: m.from,
|
||||
i_calendar_data: m.message.to_string(),
|
||||
is_from_organizer: m.from_organizer,
|
||||
summary: serde_json::to_string(&m.summary).unwrap_or_default(),
|
||||
to: m.to,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn queue(self, batch: &mut BatchBuilder) -> trc::Result<()> {
|
||||
let due = TaskEpoch::now().with_random_sequence_id();
|
||||
batch.set(
|
||||
ValueClass::TaskQueue(TaskQueueClass::SendImip {
|
||||
due,
|
||||
is_payload: false,
|
||||
}),
|
||||
vec![],
|
||||
);
|
||||
batch.set(
|
||||
ValueClass::TaskQueue(TaskQueueClass::SendImip {
|
||||
due,
|
||||
is_payload: true,
|
||||
}),
|
||||
Archiver::new(self)
|
||||
.serialize()
|
||||
.caused_by(trc::location!())?,
|
||||
);
|
||||
batch.schedule_task(Task::CalendarItipMessage(TaskCalendarItipMessage {
|
||||
account_id: batch.last_account_id().unwrap().into(),
|
||||
document_id: batch.last_document_id().unwrap().into(),
|
||||
messages: self.messages,
|
||||
status: TaskStatus::now(),
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -312,13 +309,13 @@ impl From<ItipMessage<ICalendar>> for ItipMessage<String> {
|
||||
}
|
||||
}
|
||||
|
||||
impl ArchivedItipSummary {
|
||||
impl ItipSummary {
|
||||
pub fn method(&self) -> &str {
|
||||
match self {
|
||||
ArchivedItipSummary::Invite(_) => ICalendarMethod::Request.as_str(),
|
||||
ArchivedItipSummary::Update { method, .. } => method.as_str(),
|
||||
ArchivedItipSummary::Cancel(_) => ICalendarMethod::Cancel.as_str(),
|
||||
ArchivedItipSummary::Rsvp { .. } => ICalendarMethod::Reply.as_str(),
|
||||
ItipSummary::Invite(_) => ICalendarMethod::Request.as_str(),
|
||||
ItipSummary::Update { method, .. } => method.as_str(),
|
||||
ItipSummary::Cancel(_) => ICalendarMethod::Cancel.as_str(),
|
||||
ItipSummary::Rsvp { .. } => ICalendarMethod::Reply.as_str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use calcard::{
|
||||
ICalendarStatus, ICalendarUserTypes, ICalendarValue, Uri,
|
||||
},
|
||||
};
|
||||
use registry::schema::structs::TaskCalendarItipContents;
|
||||
use std::{fmt::Display, hash::Hash};
|
||||
|
||||
pub mod attendee;
|
||||
@@ -144,7 +145,7 @@ pub enum ItipError {
|
||||
AutoAddDisabled,
|
||||
}
|
||||
|
||||
#[derive(Debug, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
#[derive(Debug)]
|
||||
pub struct ItipMessage<T> {
|
||||
pub from: String,
|
||||
pub from_organizer: bool,
|
||||
@@ -153,7 +154,7 @@ pub struct ItipMessage<T> {
|
||||
pub message: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum ItipSummary {
|
||||
Invite(Vec<ItipField>),
|
||||
Update {
|
||||
@@ -168,13 +169,14 @@ pub enum ItipSummary {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ItipField {
|
||||
pub name: ICalendarProperty,
|
||||
pub value: ItipValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(tag = "type", content = "value")]
|
||||
pub enum ItipValue {
|
||||
Text(String),
|
||||
Time(ItipTime),
|
||||
@@ -182,22 +184,21 @@ pub enum ItipValue {
|
||||
Participants(Vec<ItipParticipant>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ItipTime {
|
||||
pub start: i64,
|
||||
pub tz_id: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ItipParticipant {
|
||||
pub email: String,
|
||||
pub name: Option<String>,
|
||||
pub is_organizer: bool,
|
||||
}
|
||||
|
||||
#[derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
|
||||
pub struct ItipMessages {
|
||||
pub messages: Vec<ItipMessage<String>>,
|
||||
pub messages: Vec<TaskCalendarItipContents>,
|
||||
}
|
||||
|
||||
impl Attendee<'_> {
|
||||
|
||||
Reference in New Issue
Block a user