-
Notifications
You must be signed in to change notification settings - Fork 159
CardDAV Integration
If you are looking at jsDAV to add CalDAV or CarDAV functionality to your existing application, you'll need to roll your own Backend classes. This guide explains how and where to do this.
The following example illustrates how you can setup a CalDAV server. This is also how you'd want to build up your own server.
// Database driver to use. 'redis' is the default, but feel free to use anything
// else supported by jsDAV
var DB_DRIVER = "redis";
var jsDAV = require("./../lib/jsdav");
var jsDAV_Auth_Backend = require("./../lib/DAV/plugins/auth/" + DB_DRIVER);
var jsDAVACL_PrincipalBackend = require("./../lib/DAVACL/backends/" + DB_DRIVER);
var jsCardDAV_Backend = require("./../lib/CardDAV/backends/" + DB_DRIVER);
// node classes:
var jsDAVACL_PrincipalCollection = require("./../lib/DAVACL/principalCollection");
var jsCardDAV_AddressBookRoot = require("./../lib/CardDAV/addressBookRoot");
// plugins:
var jsDAV_Auth_Plugin = require("./../lib/DAV/plugins/auth");
var jsDAV_Browser_Plugin = require("./../lib/DAV/plugins/browser");
var jsCardDAV_Plugin = require("./../lib/CardDAV/plugin");
var jsDAVACL_Plugin = require("./../lib/DAVACL/plugin");
var Db = require("./../lib/shared/backends/" + DB_DRIVER);
var DB_INIT = require("./data/addressbook/" + DB_DRIVER);
// Arguments to be passed to the function that establishes a connection with the db
var DB_ARGS = [];
// Database connection
var db = Db.getConnection.apply(Db, DB_ARGS);
// Make sure this setting is turned on and reflect the root url for your WebDAV server.
// This can be for example the root / or a complete path to your server script
var baseUri = "/";
// set it up for demo use:
DB_INIT.init(db, function(err) {
if (err)
throw(err);
// Backends
var authBackend = jsDAV_Auth_Backend.new(db);
var principalBackend = jsDAVACL_PrincipalBackend.new(db);
var carddavBackend = jsCardDAV_Backend.new(db);
// Setting up the directory tree
var nodes = [
jsDAVACL_PrincipalCollection.new(principalBackend),
jsCardDAV_AddressBookRoot.new(principalBackend, carddavBackend)
];
jsDAV.createServer({
node: nodes,
baseUri: baseUri,
authBackend: authBackend,
realm: "jsDAV",
plugins: [jsDAV_Auth_Plugin, jsDAV_Browser_Plugin, jsCardDAV_Plugin, jsDAVACL_Plugin]
}, 8000);
});
To setup the Redis database (or mongo, if you prefer), follow the instructions on the CardDAV page.
Setting up a CardDAV server is extremely similar. For examples you can also head over to the CardDAV page or check the examples/ directory in the standard jsDAV distribution.
If you want to integrate CardDAV into your existing infrastructure, you can do so by creating your own Authentication, Principal and Calendar backends. Depending on your needs you may want to replace all of them, or just the ones that make sense for your application.
Your Authentication class needs to implement the jsDAV_Auth_iBackend
interface.
If you want to use basic or digest authentication (the only widely supported
authentication methods) you can also extend jsDAV_Auth_Backend_AbstractDigest
or jsDAV_Auth_Backend_AbstractBasic
. jsDAV_Auth_Backend_Redis
is a decent
example for digest authentication.
Lastly, the principal backend must implement jsDAVACL_PrincipalBackend_iBackend
.
Principals are in the context of WebDAV either users or groups (or both).
For CardDAV, you may also want to extend jsCardDAV_Backend_AbstractBackend
, check
jsCardDAV_Backend_Redis
for an example.
Users are called 'principals' in WebDAV terminology. Principals are associated to
a url. If your username is homer
, the url could be /principals/homer
or
/principals/[email protected]
CalDAV and CardDAV clients may use this url to gather more information about the user. You must return this url from the Auth backend, and it will be used in the Addressbook backend to return all the calendars from a specific user.
Calendars are stored under for example:
/calendars/[email protected]/
A user has multiple calendars. An example of a calendar could for example be:
/calendars/[email protected]/work
Calendar objects (events, todo's, journals) are stored as resources under this url:
/calendars/[email protected]/work/meeting.ics
Similarly, by default addressbooks will be stored under
/addressbooks/[email protected]
Specific addressbooks under there:
/addressbooks/[email protected]/book1
and vcards under there:
/addressbooks/[email protected]/book1/marge.vcf
There's a bunch of id's you will need to keep track off.
When CalDAV clients create new calendar objects, they will store them using a url.
This url can look like for example /calendars/[email protected]/1b520550-d7ca-11df-937b-0800200c9a66/22bad740-d7ca-11df-937b-0800200c9a66.ics
The last part of this url is the calendar object. You must make sure that when a CalDAV client stores a new object under a url, the client must be able to access the object using that url.
This could mean you need to make a new database field for this url. Even though most clients use the uuid.ics format, you can't rely on the url to e an uuid. Any string could be sent, and upper/lowercase can vary. Therefore it's not a true uuid field.
The jsCalDAV_Backend_AbstractBackend
class also uses a generic 'id' field. This
id is never sent to the client. It can hold any content, but it's specifically
added to allow you to store for example a database id.
Calendar objects are 'iCalendar' formatted files. They can hold events, todo's or journals (although the latter is extremely uncommon). Generally they only hold one event each, but in the case of a recurring event with exceptions, they can hold multiple.
Now, there's a good chance you want to map Calendar objects to an existing datamodel. If you do have to do this, you can do this with the VObject library, which is included with jsDAV.
The VObject library provides a parser and interface to iCalendar objects very
similar to what the jsdom
module does for xml.
Although it must be said that the iCalendar standard can be difficult, especially when dealing with timezone and recurrence. If you need to parse out data from the events and todo's to store them in separate fields, I would still recommend keeping the actual full object around in a BLOB. This will ensure that you can easily parse out the data you need, while ensuring all the users' data is kept intact.
VCards' structure are very similarly structured as iCalendars. You can also use the VObject library to work with them.
You still need a basic understanding how vcards are structured. The VObject library just helps with parsing, traversing and manipulating them.
Based on the original document at http://code.google.com/p/sabredav/wiki/