caldav-adapter 8.0.4 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/common/tags.js CHANGED
@@ -57,11 +57,17 @@ module.exports = function (options) {
57
57
  };
58
58
  }
59
59
 
60
- if (resource === 'calendar') {
60
+ if (resource === 'calendar')
61
61
  return {
62
62
  [buildTag(dav, 'displayname')]: calendar.name
63
63
  };
64
- }
64
+
65
+ if (resource === 'calendarProppatch')
66
+ return response(ctx.url, status[200], [
67
+ {
68
+ [buildTag(dav, 'displayname')]: calendar.name
69
+ }
70
+ ]);
65
71
  }
66
72
  },
67
73
  getcontenttype: {
@@ -230,37 +236,33 @@ module.exports = function (options) {
230
236
  'calendar-description': {
231
237
  doc: 'https://tools.ietf.org/html/rfc4791#section-5.2.1',
232
238
  async resp({ resource, ctx, calendar }) {
233
- if (resource === 'calendar') {
239
+ if (resource === 'calendar')
234
240
  return {
235
- [buildTag(ical, 'calendar-description')]: calendar.description
241
+ [buildTag(cal, 'calendar-description')]: calendar.description
236
242
  };
237
- }
238
243
 
239
- if (resource === 'calendarProppatch') {
240
- return response(ctx.url, status[403], [
244
+ if (resource === 'calendarProppatch')
245
+ return response(ctx.url, status[200], [
241
246
  {
242
- [buildTag(cal, 'calendar-description')]: ''
247
+ [buildTag(cal, 'calendar-description')]: calendar.description
243
248
  }
244
249
  ]);
245
- }
246
250
  }
247
251
  },
248
252
  'calendar-timezone': {
249
253
  doc: 'https://tools.ietf.org/html/rfc4791#section-5.2.2',
250
254
  async resp({ resource, ctx, calendar }) {
251
- if (resource === 'calendar') {
255
+ if (resource === 'calendar')
252
256
  return {
253
- [buildTag(ical, 'calendar-timezone')]: calendar.timezone
257
+ [buildTag(cal, 'calendar-timezone')]: calendar.timezone
254
258
  };
255
- }
256
259
 
257
- if (resource === 'calendarProppatch') {
258
- return response(ctx.url, status[403], [
260
+ if (resource === 'calendarProppatch')
261
+ return response(ctx.url, status[200], [
259
262
  {
260
- [buildTag(cal, 'calendar-timezone')]: ''
263
+ [buildTag(cal, 'calendar-timezone')]: calendar.timezone
261
264
  }
262
265
  ]);
263
- }
264
266
  }
265
267
  },
266
268
  'calendar-user-address-set': {
@@ -351,7 +353,19 @@ module.exports = function (options) {
351
353
  },
352
354
  'checksum-versions': {},
353
355
  'dropbox-home-URL': {},
354
- 'email-address-set': {},
356
+ 'email-address-set': {
357
+ async resp({ resource, ctx }) {
358
+ if (
359
+ resource === 'calendar' &&
360
+ (ctx?.state?.user?.email || ctx?.state?.user?.username)
361
+ ) {
362
+ return {
363
+ [buildTag(cs, 'email-address-set')]:
364
+ ctx?.state?.user?.email || ctx?.state?.user?.username
365
+ };
366
+ }
367
+ }
368
+ },
355
369
  getctag: {
356
370
  // DEPRECATED
357
371
  doc: 'https://github.com/apple/ccs-calendarserver/blob/master/doc/Extensions/caldav-ctag.txt',
@@ -370,37 +384,37 @@ module.exports = function (options) {
370
384
  [ical]: {
371
385
  'calendar-color': {
372
386
  async resp({ resource, ctx, calendar }) {
373
- if (resource === 'calendar') {
387
+ if (resource === 'calendar')
374
388
  return {
375
389
  [buildTag(ical, 'calendar-color')]: calendar.color
376
390
  };
377
- }
378
391
 
379
- if (resource === 'calendarProppatch') {
380
- return response(ctx.url, status[403], [
392
+ if (resource === 'calendarProppatch')
393
+ return response(ctx.url, status[200], [
381
394
  {
382
- [buildTag(ical, 'calendar-color')]: ''
395
+ [buildTag(ical, 'calendar-color')]: calendar.color
383
396
  }
384
397
  ]);
385
- }
386
398
  }
387
399
  },
388
400
  'calendar-order': {
389
- async resp({ resource, ctx }) {
390
- if (
391
- resource === 'calCollectionProppatch' ||
392
- resource === 'calendarProppatch'
393
- ) {
394
- return response(ctx.url, status[403], [
401
+ async resp({ resource, ctx, calendar }) {
402
+ if (resource === 'calendar')
403
+ return {
404
+ [buildTag(ical, 'calendar-order')]: calendar.order
405
+ };
406
+
407
+ if (resource === 'calendarProppatch')
408
+ return response(ctx.url, status[200], [
395
409
  {
396
- [buildTag(ical, 'calendar-order')]: ''
410
+ [buildTag(ical, 'calendar-order')]: calendar.order
397
411
  }
398
412
  ]);
399
- }
400
413
  }
401
414
  }
402
415
  }
403
416
  };
417
+
404
418
  const getResponse = async ({ resource, child, ctx, calendar, event }) => {
405
419
  if (!child.namespaceURI) {
406
420
  return null;
package/index.js CHANGED
@@ -134,11 +134,8 @@ module.exports = function (options) {
134
134
  if (
135
135
  ctx.url.toLowerCase() === '/.well-known/caldav' &&
136
136
  !options.disableWellKnown
137
- ) {
138
- // Return ctx.redirect(rootRoute);
139
- ctx.status = 404;
140
- return;
141
- }
137
+ )
138
+ return ctx.redirect(rootRoute); // TODO: should be 302?
142
139
 
143
140
  if (!rootRegexp.test(ctx.url)) {
144
141
  await next();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "caldav-adapter",
3
3
  "description": "CalDAV server for Node.js and Koa. Modernized and maintained for Forward Email.",
4
- "version": "8.0.4",
4
+ "version": "8.1.0",
5
5
  "author": "Sanders DeNardi and Forward Email LLC",
6
6
  "contributors": [
7
7
  "Sanders DeNardi <sedenardi@gmail.com> (http://www.sandersdenardi.com/)",
@@ -18,12 +18,73 @@ module.exports = function (options) {
18
18
  ctx.request.xml
19
19
  );
20
20
 
21
+ const updates = {};
22
+ for (const child of children) {
23
+ if (!child.localName || !child.textContent) continue;
24
+ switch (child.localName) {
25
+ case 'displayname': {
26
+ updates.name = child.textContent;
27
+
28
+ break;
29
+ }
30
+
31
+ case 'calendar-description': {
32
+ updates.description = child.textContent;
33
+
34
+ break;
35
+ }
36
+
37
+ case 'calendar-timezone': {
38
+ updates.timezone = child.textContent;
39
+
40
+ break;
41
+ }
42
+
43
+ case 'calendar-color': {
44
+ updates.color = child.textContent;
45
+
46
+ break;
47
+ }
48
+
49
+ case 'calendar-order': {
50
+ updates.order = Number.parseInt(child.textContent, 10);
51
+
52
+ break;
53
+ }
54
+
55
+ // TODO: finish me
56
+
57
+ // No default
58
+ }
59
+ }
60
+
61
+ //
62
+ // if updates was empty then we should log so we can alert admins
63
+ // as to what other properties clients are attempting to update
64
+ // (this code is an anti-pattern but temporary so we can improve)
65
+ //
66
+ if (_.isEmpty(updates)) {
67
+ const err = new TypeError('CalDAV PROPPATCH missing fields');
68
+ err.isCodeBug = true; // Specific to Forward Email (can be removed later)
69
+ err.str = ctx.request.body; // Sensitive and should be removed later
70
+ err.xml = ctx.request.xml;
71
+ console.error(err);
72
+ if (ctx.logger) ctx.logger.error(err);
73
+ }
74
+
75
+ const updatedCalendar = await options.data.updateCalendar(ctx, {
76
+ principalId: ctx.state.params.principalId,
77
+ calendarId: ctx.state.params.calendarId,
78
+ user: ctx.state.user,
79
+ updates
80
+ });
81
+
21
82
  const actions = _.map(children, async (child) => {
22
83
  return tags.getResponse({
23
84
  resource: 'calendarProppatch',
24
85
  child,
25
86
  ctx,
26
- calendar
87
+ calendar: updatedCalendar
27
88
  });
28
89
  });
29
90
  const res = await Promise.all(actions);
@@ -13,6 +13,12 @@ module.exports = function (options) {
13
13
  return;
14
14
  }
15
15
 
16
+ // TODO: support XML update (?)
17
+ // const { children } = xml.getWithChildren(
18
+ // '/D:propertyupdate/D:set/D:prop',
19
+ // ctx.request.xml
20
+ // );
21
+
16
22
  if (
17
23
  ctx.request.type !== 'text/calendar' ||
18
24
  typeof ctx.request.body !== 'string'
@@ -11,7 +11,7 @@ const routerUserPropfind = require('./user/propfind');
11
11
  const routerCalPropfind = require('./calendar/propfind');
12
12
  const routerCalReport = require('./calendar/report');
13
13
  const routerCalGet = require('./calendar/get');
14
- // const routerCalProppatch = require('./calendar/proppatch');
14
+ const routerCalProppatch = require('./calendar/proppatch');
15
15
  const routerCalPut = require('./calendar/put');
16
16
  const routerCalDelete = require('./calendar/delete');
17
17
 
@@ -25,7 +25,7 @@ module.exports = function (options) {
25
25
  propfind: routerCalPropfind(options),
26
26
  report: routerCalReport(options),
27
27
  get: routerCalGet(options),
28
- // proppatch: routerCalProppatch(options),
28
+ proppatch: routerCalProppatch(options),
29
29
  put: routerCalPut(options),
30
30
  delete: routerCalDelete(options),
31
31
  mkcalendar: routeMkCalendar(options)
@@ -31,6 +31,18 @@ module.exports = function (options) {
31
31
 
32
32
  break;
33
33
  }
34
+
35
+ case 'calendar-color': {
36
+ calendar.color = child.textContent;
37
+
38
+ break;
39
+ }
40
+
41
+ case 'calendar-order': {
42
+ calendar.order = Number.parseInt(child.textContent, 10);
43
+
44
+ break;
45
+ }
34
46
  // No default
35
47
  }
36
48
  }