Skip to content

Commit

Permalink
feat: add ctx as an arg throughout all data functions, dropped node-i…
Browse files Browse the repository at this point in the history
…cal support in favor of manual ical.js parsing (node-ical and ical-generator have too many bugs; we started to use ical.js directly instead; see @forwardemail codebase)
  • Loading branch information
titanism committed Feb 26, 2024
1 parent 0785bd1 commit 3d15d99
Show file tree
Hide file tree
Showing 14 changed files with 35 additions and 39 deletions.
3 changes: 0 additions & 3 deletions common/parse-body.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const ical = require('node-ical');
const raw = require('raw-body');
const { DOMParser } = require('@xmldom/xmldom');

Expand All @@ -10,7 +9,5 @@ module.exports = async function (ctx) {

if (ctx.request.type.includes('xml')) {
ctx.request.xml = new DOMParser().parseFromString(ctx.request.body);
} else if (ctx.request.type === 'text/calendar') {
ctx.request.ical = await ical.async.parseICS(ctx.request.body);
}
};
8 changes: 4 additions & 4 deletions common/tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ module.exports = function (options) {
},
getetag: {
doc: 'https://tools.ietf.org/html/rfc4791#section-5.3.4',
async resp({ resource, event }) {
async resp({ resource, ctx, event }) {
if (resource === 'event') {
return {
[buildTag(dav, 'getetag')]: options.data.getETag(event)
[buildTag(dav, 'getetag')]: options.data.getETag(ctx, event)
};
}
}
Expand Down Expand Up @@ -199,8 +199,8 @@ module.exports = function (options) {
[cal]: {
'calendar-data': {
doc: 'https://tools.ietf.org/html/rfc4791#section-9.6',
async resp({ event, calendar }) {
const ics = await options.data.buildICS(event, calendar);
async resp({ event, ctx, calendar }) {
const ics = await options.data.buildICS(ctx, event, calendar);
return {
[buildTag(cal, 'calendar-data')]: ics
};
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ module.exports = function (options) {
return false;
}

ctx.state.user = await options.authenticate({
ctx.state.user = await options.authenticate(ctx, {
username: creds.name,
password: creds.pass,
principalId: ctx.state.params.principalId
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"dependencies": {
"@xmldom/xmldom": "^0.8.10",
"basic-auth": "^2.0.1",
"boolean": "3.2.0",
"lodash": "^4.17.21",
"moment": "^2.30.1",
"node-ical": "^0.17.1",
"path-to-regexp": "^6.2.1",
"raw-body": "^2.5.2",
"winston": "^3.11.0",
Expand Down
2 changes: 1 addition & 1 deletion routes/calendar/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = function (options) {

if (calendarId) {
// Check calendar exists & user has access
const calendar = await options.data.getCalendar({
const calendar = await options.data.getCalendar(ctx, {
principalId: ctx.state.params.principalId,
calendarId,
user: ctx.state.user
Expand Down
6 changes: 3 additions & 3 deletions routes/calendar/calendar/calendar-multiget.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module.exports = function (options) {

const hrefParts = href.split('/');
const eventId = hrefParts.at(-1).slice(0, -4);
const event = await options.data.getEvent({
const event = await options.data.getEvent(ctx, {
eventId,
principalId: ctx.state.params.principalId,
calendarId: ctx.state.params.calendarId,
Expand All @@ -31,10 +31,10 @@ module.exports = function (options) {
return response(href, status[404]);
}

const ics = await options.data.buildICS(event, calendar);
const ics = await options.data.buildICS(ctx, event, calendar);
return response(href, status[200], [
{
'D:getetag': options.data.getETag(event)
'D:getetag': options.data.getETag(ctx, event)
},
{
'CAL:calendar-data': ics
Expand Down
8 changes: 4 additions & 4 deletions routes/calendar/calendar/calendar-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ module.exports = function (options) {
});

if (!filters?.[0]) {
const events = await options.data.getEventsForCalendar({
const events = await options.data.getEventsForCalendar(ctx, {
principalId: ctx.state.params.principalId,
calendarId: options.data.getCalendarId(calendar),
calendarId: options.data.getCalendarId(ctx, calendar),
user: ctx.state.user,
fullData
});
Expand Down Expand Up @@ -67,9 +67,9 @@ module.exports = function (options) {
if (endAttr && endAttr.nodeValue && moment(endAttr.nodeValue).isValid())
end = moment(endAttr.nodeValue).toDate();

const events = await options.data.getEventsByDate({
const events = await options.data.getEventsByDate(ctx, {
principalId: ctx.state.params.principalId,
calendarId: options.data.getCalendarId(calendar),
calendarId: options.data.getCalendarId(ctx, calendar),
start,
end,
user: ctx.state.user,
Expand Down
4 changes: 2 additions & 2 deletions routes/calendar/calendar/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = function (options) {
return;
}

const existing = await options.data.getEvent({
const existing = await options.data.getEvent(ctx, {
eventId: ctx.state.params.eventId,
principalId: ctx.state.params.principalId,
calendarId: ctx.state.params.calendarId,
Expand All @@ -26,7 +26,7 @@ module.exports = function (options) {
});
log.debug(`existing event${existing ? '' : ' not'} found`);

await options.data.deleteEvent({
await options.data.deleteEvent(ctx, {
eventId: ctx.state.params.eventId,
principalId: ctx.state.params.principalId,
calendarId: ctx.state.params.calendarId,
Expand Down
4 changes: 2 additions & 2 deletions routes/calendar/calendar/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = function (options) {
const log = winston({ ...options, label: 'calendar/get' });

const exec = async function (ctx, calendar) {
const event = await options.data.getEvent({
const event = await options.data.getEvent(ctx, {
eventId: ctx.state.params.eventId,
principalId: ctx.state.params.principalId,
calendarId: ctx.state.params.calendarId,
Expand All @@ -18,7 +18,7 @@ module.exports = function (options) {
return;
}

return options.data.buildICS(event, calendar);
return options.data.buildICS(ctx, event, calendar);
};

return {
Expand Down
6 changes: 3 additions & 3 deletions routes/calendar/calendar/propfind.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module.exports = function (options) {

const calendarUrl = path.join(
ctx.state.calendarHomeUrl,
options.data.getCalendarId(calendar),
options.data.getCalendarId(ctx, calendar),
'/'
);
const props = _.compact(res);
Expand All @@ -53,9 +53,9 @@ module.exports = function (options) {
const fullData = _.some(children, (child) => {
return child.localName === 'calendar-data';
});
const events = await options.data.getEventsForCalendar({
const events = await options.data.getEventsForCalendar(ctx, {
principalId: ctx.state.params.principalId,
calendarId: options.data.getCalendarId(calendar),
calendarId: options.data.getCalendarId(ctx, calendar),
user: ctx.state.user,
fullData
});
Expand Down
19 changes: 9 additions & 10 deletions routes/calendar/calendar/put.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const _ = require('lodash');
const { notFound, preconditionFail } = require('../../../common/x-build');
const { setMissingMethod } = require('../../../common/response');
const winston = require('../../../common/winston');
Expand All @@ -19,14 +18,16 @@ module.exports = function (options) {
return;
}

const incoming = _.find(ctx.request.ical, { type: 'VEVENT' });
if (!incoming) {
if (
ctx.request.type !== 'text/calendar' ||
typeof ctx.request.body !== 'string'
) {
log.warn('incoming VEVENT not present');
ctx.body = notFound(ctx.url); // Make more meaningful
return;
}

const existing = await options.data.getEvent({
const existing = await options.data.getEvent(ctx, {
eventId: ctx.state.params.eventId,
principalId: ctx.state.params.principalId,
calendarId: ctx.state.params.calendarId,
Expand All @@ -43,30 +44,28 @@ module.exports = function (options) {
return;
}

const updateObject = await options.data.updateEvent({
const updateObject = await options.data.updateEvent(ctx, {
eventId: ctx.state.params.eventId,
principalId: ctx.state.params.principalId,
calendarId: ctx.state.params.calendarId,
event: incoming,
user: ctx.state.user
});
log.debug('event updated');

/* https://tools.ietf.org/html/rfc4791#section-5.3.2 */
ctx.status = 201;
ctx.set('ETag', options.data.getETag(updateObject));
ctx.set('ETag', options.data.getETag(ctx, updateObject));
} else {
const newObject = await options.data.createEvent({
const newObject = await options.data.createEvent(ctx, {
eventId: ctx.state.params.eventId,
principalId: ctx.state.params.principalId,
calendarId: ctx.state.params.calendarId,
event: incoming,
user: ctx.state.user
});
log.debug('new event created');
/* https://tools.ietf.org/html/rfc4791#section-5.3.2 */
ctx.status = 201;
ctx.set('ETag', options.data.getETag(newObject));
ctx.set('ETag', options.data.getETag(ctx, newObject));
}
};

Expand Down
4 changes: 2 additions & 2 deletions routes/calendar/calendar/sync-collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ module.exports = function (options) {
const fullData = _.some(children, (child) => {
return child.localName === 'calendar-data';
});
const events = await options.data.getEventsForCalendar({
const events = await options.data.getEventsForCalendar(ctx, {
principalId: ctx.state.params.principalId,
calendarId: options.data.getCalendarId(calendar),
calendarId: options.data.getCalendarId(ctx, calendar),
user: ctx.state.user,
fullData
});
Expand Down
2 changes: 1 addition & 1 deletion routes/calendar/user/propfind.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module.exports = function (options) {
response(ctx.url, props.length > 0 ? status[200] : status[404], props)
];

const calendars = await options.data.getCalendarsForPrincipal({
const calendars = await options.data.getCalendarsForPrincipal(ctx, {
principalId: ctx.state.params.principalId,
user: ctx.state.user
});
Expand Down
4 changes: 2 additions & 2 deletions routes/principal/mkcalendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ module.exports = function (options) {
// </d:set>
// </c:mkcalendar>

const calendarObject = await options.data.createCalendar(calendar);
const calendarObject = await options.data.createCalendar(ctx, calendar);
ctx.status = 201;
ctx.set('ETag', options.data.getETag(calendarObject));
ctx.set('ETag', options.data.getETag(ctx, calendarObject));
};
};

0 comments on commit 3d15d99

Please sign in to comment.