Skip to content

Commit

Permalink
Caldav integration: Handle new until date for recurring events (#2107)
Browse files Browse the repository at this point in the history
  • Loading branch information
bertrandda authored Sep 13, 2024
1 parent 344ad9b commit 48c3786
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 8 deletions.
28 changes: 21 additions & 7 deletions server/lib/calendar/calendar.destroyEvents.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
const { Op } = require('sequelize');
const db = require('../../models');

/**
* @description Delete events from a calendar.
* @param {string} calendarId - Calendar id to empty.
* @param {object} options - Options of the query.
* @example
* gladys.calendar.destroyEvents('0dc03aef-4a23-9c4e-88e3-5437971269e5');
* gladys.calendar.destroyEvents('0dc03aef-4a23-9c4e-88e3-5437971269e5', {url: '/calendar/event.ics'});
*/
async function destroyEvents(calendarId) {
await db.CalendarEvent.destroy({
where: {
calendar_id: calendarId,
},
});
async function destroyEvents(calendarId, options = {}) {
const where = {
calendar_id: calendarId,
};

if (options.url) {
where.url = {
[Op.eq]: options.url,
};
}

if (options.from) {
where.start = {
[Op.gte]: new Date(options.from),
};
}

await db.CalendarEvent.destroy({ where });
}

module.exports = {
Expand Down
14 changes: 14 additions & 0 deletions server/services/caldav/lib/calendar/calendar.syncUserCalendars.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const Promise = require('bluebird');
const get = require('get-value');
const logger = require('../../../../utils/logger');
const { ServiceNotConfiguredError, NotFoundError } = require('../../../../utils/coreErrors');

Expand Down Expand Up @@ -108,6 +109,19 @@ async function syncUserCalendars(userId) {
throw new NotFoundError('CALDAV_FAILED_REQUEST_EVENTS');
}

await Promise.map(
jsonEvents,
async (jsonEvent) => {
if (get(jsonEvent, 'rrule.options.until') && jsonEvent.href) {
await this.gladys.calendar.destroyEvents(calendarToUpdate.id, {
url: jsonEvent.href,
from: get(jsonEvent, 'rrule.options.until'),
});
}
},
{ concurrency: 5 },
);

const formatedEvents = this.formatEvents(jsonEvents, calendarToUpdate);

let insertedOrUpdatedEvent = 0;
Expand Down
33 changes: 33 additions & 0 deletions server/services/caldav/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/services/caldav/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"bluebird": "^3.7.0",
"dav-request": "^1.8.0",
"dayjs": "^1.11.10",
"get-value": "^3.0.1",
"ical": "^0.8.0",
"xmldom": "^0.6.0"
}
Expand Down
24 changes: 23 additions & 1 deletion server/test/lib/calendar/calendar.event.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,37 @@ describe('calendar.destroy', () => {
});

describe('calendar.destroyEvents', () => {
const calendar = new Calendar();
it("should destroy all calendar's event", async () => {
const calendar = new Calendar();
await calendar.destroyEvents('07ec2599-3221-4d6c-ac56-41443973201b');
const allCalendarEvents = await calendar.getEvents(
'0cd30aef-9c4e-4a23-88e3-3547971296e5',
'07ec2599-3221-4d6c-ac56-41443973201b',
);
assert.deepEqual(allCalendarEvents, []);
});

it("should destroy calendar's events by url", async () => {
const calendar = new Calendar();
await calendar.destroyEvents('07ec2599-3221-4d6c-ac56-41443973201b', {
url: '/remote.php/dav/calendars/tony/personal/eee42d70-24f2-4c18-949d-822f3f72594c.ics',
});
const allCalendarEvents = await calendar.getEvents(
'0cd30aef-9c4e-4a23-88e3-3547971296e5',
'07ec2599-3221-4d6c-ac56-41443973201b',
);
expect(allCalendarEvents.length).eq(1);
});

it("should destroy calendar's events starting after date", async () => {
const calendar = new Calendar();
await calendar.destroyEvents('07ec2599-3221-4d6c-ac56-41443973201b', { from: '2019-03-10 07:49:07.556 +00:00' });
const allCalendarEvents = await calendar.getEvents(
'0cd30aef-9c4e-4a23-88e3-3547971296e5',
'07ec2599-3221-4d6c-ac56-41443973201b',
);
expect(allCalendarEvents.length).eq(1);
});
});

describe('calendar.getEvents', () => {
Expand Down
16 changes: 16 additions & 0 deletions server/test/services/caldav/lib/calendar/syncUserCalendars.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('CalDAV sync', () => {
syncUserCalendars,
formatCalendars,
formatEvents,
formatRecurringEvents: sinon.stub().returns([]),
requestCalendars: sinon.stub(),
requestChanges: sinon.stub(),
requestEventsData: sinon.stub(),
Expand All @@ -37,6 +38,7 @@ describe('CalDAV sync', () => {
.stub()
.withArgs('event-to-delete')
.resolves(),
destroyEvents: sinon.stub().resolves(),
},
variable: {
getValue: sinon.stub(),
Expand Down Expand Up @@ -181,6 +183,19 @@ describe('CalDAV sync', () => {
start: new Date('2018-06-08 00:00:00.000 +00:00'),
location: null,
},
{
type: 'VEVENT',
uid: '3a98f1eb-e8e9-4f09-8454-353e92f9ff0d',
summary: 'Evenement 4 to update with rrule',
start: new Date('2018-06-08 00:00:00.000 +00:00'),
location: null,
href: '/home/personal/event-4.ics',
rrule: {
options: {
until: '2019-06-08 00:00:00.000 +00:00',
},
},
},
]);

sync.gladys.calendar.getEvents
Expand Down Expand Up @@ -251,6 +266,7 @@ describe('CalDAV sync', () => {
expect(sync.gladys.calendar.update.callCount).to.equal(1);
expect(sync.gladys.calendar.getEvents.callCount).to.equal(4);
expect(sync.gladys.calendar.destroyEvent.callCount).to.equal(1);
expect(sync.gladys.calendar.destroyEvents.callCount).to.equal(1);
});

it('should failed if no CALDAV_HOST', async () => {
Expand Down

0 comments on commit 48c3786

Please sign in to comment.