dav
Version:
WebDAV, CalDAV, and CardDAV client for nodejs and the browser
315 lines (248 loc) • 9.7 kB
JavaScript
;
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _co = require('co');
var _co2 = _interopRequireDefault(_co);
var _url = require('url');
var _url2 = _interopRequireDefault(_url);
var _calendars = require('./calendars');
var _contacts = require('./contacts');
var _fuzzy_url_equals = require('./fuzzy_url_equals');
var _fuzzy_url_equals2 = _interopRequireDefault(_fuzzy_url_equals);
var _model = require('./model');
var _namespace = require('./namespace');
var ns = _interopRequireWildcard(_namespace);
var _request = require('./request');
var request = _interopRequireWildcard(_request);
var debug = require('./debug')('dav:accounts');
var defaults = {
accountType: 'caldav',
loadCollections: true,
loadObjects: false
};
/**
* rfc 6764.
*
* @param {dav.Account} account to find root url for.
*/
var serviceDiscovery = _co2['default'].wrap(regeneratorRuntime.mark(function callee$0$0(account, options) {
var endpoint, uri, req, xhr, _location;
return regeneratorRuntime.wrap(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
debug('Attempt service discovery.');
endpoint = _url2['default'].parse(account.server);
endpoint.protocol = endpoint.protocol || 'http'; // TODO(gareth) https?
uri = _url2['default'].format({
protocol: endpoint.protocol,
host: endpoint.host,
pathname: '/.well-known/' + options.accountType
});
req = request.basic({ method: 'GET' });
context$1$0.prev = 5;
context$1$0.next = 8;
return options.xhr.send(req, uri, { sandbox: options.sandbox });
case 8:
xhr = context$1$0.sent;
if (!(xhr.status >= 300 && xhr.status < 400)) {
context$1$0.next = 14;
break;
}
_location = xhr.getResponseHeader('Location');
if (!(typeof _location === 'string' && _location.length)) {
context$1$0.next = 14;
break;
}
debug('Discovery redirected to ' + _location);
return context$1$0.abrupt('return', _url2['default'].format({
protocol: endpoint.protocol,
host: endpoint.host,
pathname: _location
}));
case 14:
context$1$0.next = 19;
break;
case 16:
context$1$0.prev = 16;
context$1$0.t0 = context$1$0['catch'](5);
debug('Discovery failed... failover to the provided url');
case 19:
return context$1$0.abrupt('return', endpoint.href);
case 20:
case 'end':
return context$1$0.stop();
}
}, callee$0$0, this, [[5, 16]]);
}));
/**
* rfc 5397.
*
* @param {dav.Account} account to get principal url for.
*/
var principalUrl = _co2['default'].wrap(regeneratorRuntime.mark(function callee$0$0(account, options) {
var req, res, container;
return regeneratorRuntime.wrap(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
debug('Fetch principal url from context path ' + account.rootUrl + '.');
req = request.propfind({
props: [{ name: 'current-user-principal', namespace: ns.DAV }],
depth: 0,
mergeResponses: true
});
context$1$0.next = 4;
return options.xhr.send(req, account.rootUrl, {
sandbox: options.sandbox
});
case 4:
res = context$1$0.sent;
container = res.props;
debug('Received principal: ' + container.currentUserPrincipal);
return context$1$0.abrupt('return', _url2['default'].resolve(account.rootUrl, container.currentUserPrincipal));
case 8:
case 'end':
return context$1$0.stop();
}
}, callee$0$0, this);
}));
/**
* @param {dav.Account} account to get home url for.
*/
var homeUrl = _co2['default'].wrap(regeneratorRuntime.mark(function callee$0$0(account, options) {
var prop, req, responses, response, container, href;
return regeneratorRuntime.wrap(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
debug('Fetch home url from principal url ' + account.principalUrl + '.');
prop = undefined;
if (options.accountType === 'caldav') {
prop = { name: 'calendar-home-set', namespace: ns.CALDAV };
} else if (options.accountType === 'carddav') {
prop = { name: 'addressbook-home-set', namespace: ns.CARDDAV };
}
req = request.propfind({ props: [prop] });
context$1$0.next = 6;
return options.xhr.send(req, account.principalUrl, {
sandbox: options.sandbox
});
case 6:
responses = context$1$0.sent;
response = responses.find(function (response) {
return (0, _fuzzy_url_equals2['default'])(account.principalUrl, response.href);
});
container = response.props;
href = undefined;
if (options.accountType === 'caldav') {
debug('Received home: ' + container.calendarHomeSet);
href = container.calendarHomeSet;
} else if (options.accountType === 'carddav') {
debug('Received home: ' + container.addressbookHomeSet);
href = container.addressbookHomeSet;
}
return context$1$0.abrupt('return', _url2['default'].resolve(account.rootUrl, href));
case 12:
case 'end':
return context$1$0.stop();
}
}, callee$0$0, this);
}));
/**
* Options:
*
* (String) accountType - one of 'caldav' or 'carddav'. Defaults to 'caldav'.
* (Array.<Object>) filters - list of caldav filters to send with request.
* (Boolean) loadCollections - whether or not to load dav collections.
* (Boolean) loadObjects - whether or not to load dav objects.
* (dav.Sandbox) sandbox - optional request sandbox.
* (String) server - some url for server (needn't be base url).
* (String) timezone - VTIMEZONE calendar object.
* (dav.Transport) xhr - request sender.
*
* @return {Promise} a promise that will resolve with a dav.Account object.
*/
exports.createAccount = _co2['default'].wrap(regeneratorRuntime.mark(function callee$0$0(options) {
var account, key, loadCollections, loadObjects, collections;
return regeneratorRuntime.wrap(function callee$0$0$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
options = Object.assign({}, defaults, options);
if (typeof options.loadObjects !== 'boolean') {
options.loadObjects = options.loadCollections;
}
account = new _model.Account({
server: options.server,
credentials: options.xhr.credentials
});
context$1$0.next = 5;
return serviceDiscovery(account, options);
case 5:
account.rootUrl = context$1$0.sent;
context$1$0.next = 8;
return principalUrl(account, options);
case 8:
account.principalUrl = context$1$0.sent;
context$1$0.next = 11;
return homeUrl(account, options);
case 11:
account.homeUrl = context$1$0.sent;
if (options.loadCollections) {
context$1$0.next = 14;
break;
}
return context$1$0.abrupt('return', account);
case 14:
key = undefined, loadCollections = undefined, loadObjects = undefined;
if (options.accountType === 'caldav') {
key = 'calendars';
loadCollections = _calendars.listCalendars;
loadObjects = _calendars.listCalendarObjects;
} else if (options.accountType === 'carddav') {
key = 'addressBooks';
loadCollections = _contacts.listAddressBooks;
loadObjects = _contacts.listVCards;
}
context$1$0.next = 18;
return loadCollections(account, options);
case 18:
collections = context$1$0.sent;
account[key] = collections;
if (options.loadObjects) {
context$1$0.next = 22;
break;
}
return context$1$0.abrupt('return', account);
case 22:
context$1$0.next = 24;
return collections.map(_co2['default'].wrap(regeneratorRuntime.mark(function callee$1$0(collection) {
return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.prev = 0;
context$2$0.next = 3;
return loadObjects(collection, options);
case 3:
collection.objects = context$2$0.sent;
context$2$0.next = 9;
break;
case 6:
context$2$0.prev = 6;
context$2$0.t0 = context$2$0['catch'](0);
collection.error = context$2$0.t0;
case 9:
case 'end':
return context$2$0.stop();
}
}, callee$1$0, this, [[0, 6]]);
})));
case 24:
account[key] = account[key].filter(function (collection) {
return !collection.error;
});
return context$1$0.abrupt('return', account);
case 26:
case 'end':
return context$1$0.stop();
}
}, callee$0$0, this);
}));
// http redirect.