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

@@ -1,12 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE calendars SET principal = ?, id = ?, displayname = ?, description = ?, \"order\" = ?, color = ?, timezone = ?\n WHERE (principal, id) = (?, ?)",
"query": "UPDATE calendars SET principal = ?, id = ?, displayname = ?, description = ?, \"order\" = ?, color = ?, timezone = ?, timezone_id = ?\n WHERE (principal, id) = (?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 9
"Right": 10
},
"nullable": []
},
"hash": "c7a56d737fc8627427d0be202c3c77bb95c1a25b6a3c0c389ef0ad4f468320ee"
"hash": "0d0bd23849e3e9492531fa8ce0eb22832d0c16d690cebbcb7e546cab3e942d64"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "SQLite",
"query": "SELECT principal, id, synctoken, displayname, \"order\", description, color, timezone, deleted_at, subscription_url\n FROM calendars\n WHERE principal = ? AND deleted_at IS NULL",
"query": "SELECT principal, id, synctoken, displayname, \"order\", description, color, timezone, timezone_id, deleted_at, subscription_url\n FROM calendars\n WHERE principal = ? AND deleted_at IS NULL",
"describe": {
"columns": [
{
@@ -44,13 +44,18 @@
"type_info": "Text"
},
{
"name": "deleted_at",
"name": "timezone_id",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "deleted_at",
"ordinal": 9,
"type_info": "Datetime"
},
{
"name": "subscription_url",
"ordinal": 9,
"ordinal": 10,
"type_info": "Text"
}
],
@@ -67,8 +72,9 @@
true,
true,
true,
true,
true
]
},
"hash": "7d27bdb54fbc8e65e5482fa9bc974e57c1fc7abcc5c7ca6bbb4944554381285c"
"hash": "24ece624823b418fa96a867f57d62ed755035e88b0d9363b71aac8aedff1cbb6"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "INSERT INTO calendars (principal, id, displayname, description, \"order\", color, timezone, timezone_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 8
},
"nullable": []
},
"hash": "32969555ebbf5d7220c1c0d2d2c793a69d9bbaa1a1a9ec16611ad1b1d303d5d6"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "SQLite",
"query": "SELECT principal, id, synctoken, displayname, \"order\", description, color, timezone, deleted_at, subscription_url\n FROM calendars\n WHERE principal = ? AND deleted_at IS NOT NULL",
"query": "SELECT principal, id, synctoken, displayname, \"order\", description, color, timezone, timezone_id, deleted_at, subscription_url\n FROM calendars\n WHERE principal = ? AND deleted_at IS NOT NULL",
"describe": {
"columns": [
{
@@ -44,13 +44,18 @@
"type_info": "Text"
},
{
"name": "deleted_at",
"name": "timezone_id",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "deleted_at",
"ordinal": 9,
"type_info": "Datetime"
},
{
"name": "subscription_url",
"ordinal": 9,
"ordinal": 10,
"type_info": "Text"
}
],
@@ -67,8 +72,9 @@
true,
true,
true,
true,
true
]
},
"hash": "97d66b4b76bca677badd9087a6bab978a54d36e4bb12ea77a6d52b9dfa08312c"
"hash": "9770a3a1c85aa92e7787ede67e86aa680e0831613cc9cb87cb19928fc538d35c"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "SQLite",
"query": "SELECT principal, id, synctoken, \"order\", displayname, description, color, timezone, deleted_at, subscription_url\n FROM calendars\n WHERE (principal, id) = (?, ?)",
"query": "SELECT principal, id, synctoken, \"order\", displayname, description, color, timezone, timezone_id, deleted_at, subscription_url\n FROM calendars\n WHERE (principal, id) = (?, ?)",
"describe": {
"columns": [
{
@@ -44,13 +44,18 @@
"type_info": "Text"
},
{
"name": "deleted_at",
"name": "timezone_id",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "deleted_at",
"ordinal": 9,
"type_info": "Datetime"
},
{
"name": "subscription_url",
"ordinal": 9,
"ordinal": 10,
"type_info": "Text"
}
],
@@ -67,8 +72,9 @@
true,
true,
true,
true,
true
]
},
"hash": "38e44b7a271d9be098f00b233100fbce750a4e167ee547abccbefd36a089f399"
"hash": "a74288844bf11fd318c3e688d3a4bc454d8b162d7afbeebfc448211990cd8823"
}

View File

@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO calendars (principal, id, displayname, description, \"order\", color, timezone)\n VALUES (?, ?, ?, ?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 7
},
"nullable": []
},
"hash": "eba774e8d8afa04d33443b42ec3a4af1c2f34515288bade397b87a1e43d789df"
}

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)?;