caldav: Add calendar-timezone-id

This commit is contained in:
Lennart
2025-01-04 16:48:15 +01:00
parent d1350af269
commit 5738f56dfe
13 changed files with 74 additions and 37 deletions

View File

@@ -27,6 +27,7 @@ pub struct SupportedCalendarComponentSetElement {
#[derive(XmlDeserialize, Clone, Debug)]
pub struct MkcolCalendarProp {
// TODO: Add namespaces
resourcetype: Option<Resourcetype>,
displayname: Option<String>,
calendar_description: Option<String>,
@@ -70,6 +71,7 @@ pub async fn route_mkcalendar<C: CalendarStore + ?Sized>(
order: request.order.unwrap_or(0),
displayname: request.displayname,
timezone: request.calendar_timezone,
timezone_id: request.calendar_timezone_id,
color: request.calendar_color,
description: request.calendar_description,
deleted_at: None,

View File

@@ -61,6 +61,9 @@ pub enum CalendarProp {
CalendarDescription(Option<String>),
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
CalendarTimezone(Option<String>),
// https://datatracker.ietf.org/doc/html/rfc7809
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
CalendarTimezoneId(Option<String>),
#[xml(ns = "rustical_dav::namespace::NS_ICAL")]
CalendarOrder(Option<i64>),
#[xml(ns = "rustical_dav::namespace::NS_CALDAV", skip_deserializing)]
@@ -138,6 +141,9 @@ impl Resource for CalendarResource {
CalendarPropName::CalendarTimezone => {
CalendarProp::CalendarTimezone(self.0.timezone.clone())
}
CalendarPropName::CalendarTimezoneId => {
CalendarProp::CalendarTimezoneId(self.0.timezone_id.clone())
}
CalendarPropName::CalendarOrder => CalendarProp::CalendarOrder(Some(self.0.order)),
CalendarPropName::SupportedCalendarComponentSet => {
CalendarProp::SupportedCalendarComponentSet(SupportedCalendarComponentSet::default())
@@ -186,6 +192,11 @@ impl Resource for CalendarResource {
self.0.timezone = timezone;
Ok(())
}
CalendarProp::CalendarTimezoneId(timezone_id) => {
// TODO: Set or remove timezone accordingly
self.0.timezone_id = timezone_id;
Ok(())
}
CalendarProp::CalendarOrder(order) => {
self.0.order = order.unwrap_or_default();
Ok(())
@@ -224,6 +235,10 @@ impl Resource for CalendarResource {
self.0.timezone = None;
Ok(())
}
CalendarPropName::CalendarTimezoneId => {
self.0.timezone_id = None;
Ok(())
}
CalendarPropName::CalendarOrder => {
self.0.order = 0;
Ok(())

View File

@@ -40,7 +40,7 @@ pub fn configure_dav<AP: AuthenticationProvider, C: CalendarStore + ?Sized>(
.insert_header((
HeaderName::from_static("dav"),
HeaderValue::from_static(
"1, 2, 3, access-control, calendar-access, extended-mkcol",
"1, 2, 3, access-control, calendar-access, extended-mkcol, calendar-no-timezone",
),
))
.finish();

View File

@@ -11,6 +11,7 @@ pub struct Calendar {
pub description: Option<String>,
pub color: Option<String>,
pub timezone: Option<String>,
pub timezone_id: Option<String>,
pub deleted_at: Option<NaiveDateTime>,
pub synctoken: i64,
pub subscription_url: Option<String>,

View File

@@ -16,7 +16,6 @@ pub struct EventObject {
impl EventObject {
pub fn get_first_occurence(&self) -> Result<Option<CalDateTime>, Error> {
// This is safe since we enforce the event's existance in the constructor
if let Some(dtstart) = self.event.get_property("DTSTART") {
CalDateTime::parse_prop(dtstart, &self.timezones)
} else {
@@ -25,7 +24,6 @@ impl EventObject {
}
pub fn get_last_occurence(&self) -> Result<Option<CalDateTime>, Error> {
// This is safe since we enforce the event's existence in the constructor
if let Some(_rrule) = self.event.get_property("RRULE") {
// TODO: understand recurrence rules
return Ok(None);

View File

@@ -7,6 +7,7 @@ CREATE TABLE calendars (
"order" INT DEFAULT 0 NOT NULL,
color TEXT,
timezone TEXT,
timezone_id TEXT,
deleted_at DATETIME,
subscription_url TEXT,
PRIMARY KEY (principal, id)

View File

@@ -62,7 +62,7 @@ impl CalendarStore for SqliteStore {
async fn get_calendar(&self, principal: &str, id: &str) -> Result<Calendar, Error> {
let cal = sqlx::query_as!(
Calendar,
r#"SELECT principal, id, synctoken, "order", displayname, description, color, timezone, deleted_at, subscription_url
r#"SELECT principal, id, synctoken, "order", displayname, description, color, timezone, timezone_id, deleted_at, subscription_url
FROM calendars
WHERE (principal, id) = (?, ?)"#,
principal,
@@ -77,7 +77,7 @@ impl CalendarStore for SqliteStore {
async fn get_calendars(&self, principal: &str) -> Result<Vec<Calendar>, Error> {
let cals = sqlx::query_as!(
Calendar,
r#"SELECT principal, id, synctoken, displayname, "order", description, color, timezone, deleted_at, subscription_url
r#"SELECT principal, id, synctoken, displayname, "order", description, color, timezone, timezone_id, deleted_at, subscription_url
FROM calendars
WHERE principal = ? AND deleted_at IS NULL"#,
principal
@@ -91,7 +91,7 @@ impl CalendarStore for SqliteStore {
async fn get_deleted_calendars(&self, principal: &str) -> Result<Vec<Calendar>, Error> {
let cals = sqlx::query_as!(
Calendar,
r#"SELECT principal, id, synctoken, displayname, "order", description, color, timezone, deleted_at, subscription_url
r#"SELECT principal, id, synctoken, displayname, "order", description, color, timezone, timezone_id, deleted_at, subscription_url
FROM calendars
WHERE principal = ? AND deleted_at IS NOT NULL"#,
principal
@@ -104,15 +104,16 @@ impl CalendarStore for SqliteStore {
#[instrument]
async fn insert_calendar(&self, calendar: Calendar) -> Result<(), Error> {
sqlx::query!(
r#"INSERT INTO calendars (principal, id, displayname, description, "order", color, timezone)
VALUES (?, ?, ?, ?, ?, ?, ?)"#,
r#"INSERT INTO calendars (principal, id, displayname, description, "order", color, timezone, timezone_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"#,
calendar.principal,
calendar.id,
calendar.displayname,
calendar.description,
calendar.order,
calendar.color,
calendar.timezone
calendar.timezone,
calendar.timezone_id
)
.execute(&self.db)
.await.map_err(crate::Error::from)?;
@@ -127,7 +128,7 @@ impl CalendarStore for SqliteStore {
calendar: Calendar,
) -> Result<(), Error> {
let result = sqlx::query!(
r#"UPDATE calendars SET principal = ?, id = ?, displayname = ?, description = ?, "order" = ?, color = ?, timezone = ?
r#"UPDATE calendars SET principal = ?, id = ?, displayname = ?, description = ?, "order" = ?, color = ?, timezone = ?, timezone_id = ?
WHERE (principal, id) = (?, ?)"#,
calendar.principal,
calendar.id,
@@ -136,6 +137,7 @@ impl CalendarStore for SqliteStore {
calendar.order,
calendar.color,
calendar.timezone,
calendar.timezone_id,
principal,
id
).execute(&self.db).await.map_err(crate::Error::from)?;