DAVACL & CalDAV Support #32

Closed
wants to merge 135 commits into
from

Conversation

Projects
None yet
7 participants

I've implemented enough of DAVACL to make it work, and most of the CalDAV spec. There are still some missing features, but I feel there is significant value in the code as it sits now.

On a potentially controversial note; I replaced the xml library with libxmljs. I could not get XPath queries with namespaces working correctly with o3-xml. I also feel that we should be using something like libxmljs for generating XML responses, being that it's generally more robust than building xml using string catenation.

james-emerton added some commits Dec 12, 2011

@james-emerton james-emerton jsDAV_Directory now inherits correctly from jsDAV_Node ec2738c
@james-emerton james-emerton jsDAV_iProperties is now compatible with jsDAV_Base.implement() 8bed0bf
@james-emerton james-emerton Now returning missing properties as 404 c3b4108
@james-emerton james-emerton Fix callback reference 52225c1
@james-emerton james-emerton Committing changes in my CalDAV sandbox f039ad4
@james-emerton james-emerton Guard against currentNode === undefined 12a270d
@james-emerton james-emerton Ignore vim swapfiles 72b12d3
@james-emerton james-emerton Fixed a couple of authentication bugs 39103ca
@james-emerton james-emerton Parsing form data is now deterministic and will not timeout the reque…
…st if the request content type is incorrect or does not contain file data
42a7226
@james-emerton james-emerton Fix some SimpleDirectory and ObjectTree issues 99fea3d
@james-emerton james-emerton Initial DAVACL components 1bc802c
@james-emerton james-emerton iProperties.getProperties() is not async 1057ad9
@james-emerton james-emerton Made jsDAV_Auth_Plugin.getCurrentUser non-async
In order to implement jsDAV_Property_CurrentUserPrincipal the current
user is required. Unfortunately the property system is not designed to
be async, and it is easier to change the function of getCurrentUser()
0a3350b
@james-emerton james-emerton Implemented {DAV:}current-user-principal ef5dce4
@james-emerton james-emerton Fixes jsDAV_PrincipalCollection.getChild() 69ef238
@james-emerton james-emerton Implemented {DAV:}principal-URL b51f487
@james-emerton james-emerton Refactored jsDAV_Hander.getPropertiesForPath()
afterGetProperty() was being called inconsistently, and it only needs
to be called once per node instead of per automatic property. Moved it
into the end() section of the inner loop.
c114912
@james-emerton james-emerton Implemented {DAV:}resourcetype for principals fe240c9
@james-emerton james-emerton Refactored getPropertiesForNode() out of getPropertiesForPath()
Breaking up a large method to make it easier for my tiny brain
9a8afc1
@james-emerton james-emerton Added support for beforeGetProperties event 140ee65
@james-emerton james-emerton Created DAVACL plugin and reimplemented current-user-principal using …
…beforeGetProperties
04a9a0f
@james-emerton james-emerton Don't clobber properties from beforeGetProperties handlers f0abfca
@james-emerton james-emerton Handle custom namespaces correctly
resNsList was not getting a copy of handler.xmlNamespaces which caused
elements to serialize in a custom namespace but without an xmlns
attribute
6447f51
@james-emerton james-emerton Added missing require, removed debug cruft d3d73f2
@james-emerton james-emerton Added jsDAV_Property_HrefList bfc97d0
@james-emerton james-emerton Added CalDAV plugin
This is a preliminary version of the CalDAV plugin, with support for a
couple basic CalDAV properties.
4151065
@james-emerton james-emerton Merge branch 'master' of git://github.com/mikedeboer/jsDAV
Conflicts:
	lib/DAV/handler.js
d383fe7
@james-emerton james-emerton Updated calendar server "example" 5550b9e
@james-emerton james-emerton Added support for {DAV:}principal-collection-set and {DAV:}displayname 80fba45
@james-emerton james-emerton Pass errors from REPORT handlers back to client b1b3358
@james-emerton james-emerton Fixes jsDAV_Handler.getHTTPDepth 81955b5
@james-emerton james-emerton Added {DAV:}principal-search-property-set report be9c6b2
@james-emerton james-emerton Added a big chunk of DAVACL functionality 9ffbac9
@james-emerton james-emerton Added some CalDAV components f7040f3
@james-emerton james-emerton Updated calendarserver test/example 96506ba
@james-emerton james-emerton Added missing file cb3d154
@james-emerton james-emerton Compose node path using parent+name
An internal property was being used for the node path
13bab58
@james-emerton james-emerton Add parameters to iCollection interface 9bc8f60
@james-emerton james-emerton Implemented some CalDAV specific ACL parts 7d28776
@james-emerton james-emerton Fix some ACL porting errors cc46498
@james-emerton james-emerton Now enforcing ACLs (fixed checkPrivileges()) dd5ada7
@james-emerton james-emerton Added generateXmlTag() to handler, now serializing privileges with ot…
…her namespaces correctly
0953bde
@james-emerton james-emerton Fixes typo 574be22
@james-emerton james-emerton Added attribute support to generateXmlTag() b2ccc3d
@james-emerton james-emerton Add method parameters to iFile 94c02c9
@james-emerton james-emerton Implemented a bit more CalDAV 7faaecd
@james-emerton james-emerton Move principal property type constants out of prototype 75ab862
@james-emerton james-emerton Don't declare a special namespace when the document hasn't declared it b155c64
@james-emerton james-emerton Add {DAV:}group-membership property a4d76b7
@james-emerton james-emerton Fix xmlns error in generateXmlTag() e4dcaeb
@james-emerton james-emerton Fix exception result 7ad7031
@james-emerton james-emerton Fix up {DAV:}supported-report-set property a6e831f
@james-emerton james-emerton Use Util.fromClarkNotation() to parse property namespaces 50b0ddb
@james-emerton james-emerton Implemented {DAV:}expand-property report 86e0c6a
@james-emerton james-emerton Minor tweaks 5281c38
@james-emerton james-emerton Add support for calendar-proxy-read-for and calendar-proxy-write for 34947ed
@james-emerton james-emerton jsDAV_ServerPlugin.getSupportedReportSet is now async d5d0f23
@james-emerton james-emerton Made resourcetype property smarter, added calendar type bd8706d
@james-emerton james-emerton Fixed PROPPATCH method, made async 1adf92b
@james-emerton james-emerton Removed node-o3-xml in favour of libxmljs
node-o3-xml suffers from poor documentation, lack of support for xml
document generation, poor XPath namespace support and a bug which
causes it to segfault when a DOM object toString() method is called.
f1c3053
@james-emerton james-emerton Fixes some minor issues created by the libxmljs port 931d984
@james-emerton james-emerton Added jsDAV_Handler.sendResponse()
This defaults the Content-Type to "application/xml; charset=utf-8" and
sets Content-Length to avoid using chunked encoding needlessly.
cbfb2b7
@james-emerton james-emerton Added the calendar-multiget report 20122a2
@james-emerton james-emerton Updated example/test
Added basic persistence and a more complete implementation of the
backend interface
b5cd73c
@james-emerton james-emerton Tidied up jsDAV_Handler.checkPreconditions(), fixed etag related bugs 1a36184
@james-emerton james-emerton Fix up use of "special" this
Least favourite thing about JS ever...
7f92d7b
@james-emerton james-emerton Added proper lastmodified support f4d93df
@james-emerton james-emerton Marked protected properties 23b06c3
@james-emerton james-emerton jsDAV_iNode is no longer derived from jsDAV_Base, added default imple…
…mentations
df4115e
@james-emerton james-emerton Added getName() to jsDAV_CalDAV_UserCalendars fe6df6b
@james-emerton james-emerton Remove stub implementations in favour of base class methods 6111e3c
@james-emerton james-emerton Tidy up xml namespaces 2e7d232
@james-emerton james-emerton Catching exceptions from event handlers 01a2de8
@james-emerton james-emerton Setup pseudo-inheritance between interfaces 67ba8f1
@james-emerton james-emerton Improve error handling 4278fa7
@james-emerton james-emerton More fixes for error handling, simplified EventEmitter 3644c8b
@james-emerton james-emerton Fixed parameters to iCollection.createFile() ac5fc8c
@james-emerton james-emerton Send the error message back with an auth failure, fix callback in bas…
…ic auth handler
4b53b93
@james-emerton james-emerton Add ctag support to calendar example
If iCal (tested v5.0.1) doesn't get a ctag value for a calendar the
user will see strange behaviour when the calendar refreshes
642b22c
@james-emerton james-emerton Cache ETag values for calendar objects 608852c
@james-emerton james-emerton Added a little hack to allow the iPhone default principal path to work 84ace74
@james-emerton james-emerton Removed Function.prototype.bind override
The behaviour of the bind override here is not quite equivalent to the
V8 native method.
efcee36
@james-emerton james-emerton Moved calendar_data.json in examples dir, added to .gitignore 75daa3a
@james-emerton james-emerton Merged upstream changes 973f237
@james-emerton james-emerton Fix a tiny syntax error 854fb17
@james-emerton james-emerton Updated README 50a5340
@james-emerton james-emerton Fixup required module paths 00dd65c
@james-emerton james-emerton Tidied debug logging, added request headers to output 72fc623
@james-emerton james-emerton Fix psychotic 'this' 7ddefea
@james-emerton james-emerton More reliably clear listener timeouts 6819371
@james-emerton james-emerton Added default implementations for jsDAV_iFile a07d8e1
@james-emerton james-emerton Started adding some tests 5f6bb15
@james-emerton james-emerton Fix up If-Modified-Since, removed redundant code 23601f0
@james-emerton james-emerton Don't send two responses 4ab9563
@james-emerton james-emerton Fix up If-Unmodified-Since 9ae1b84
@james-emerton james-emerton Remove cached etag when calendar object is modified e430c16
@james-emerton james-emerton Test multiple precondition headers 1d9de4e
@james-emerton james-emerton Don't add trailing slashes to non-collections 4277601
@james-emerton james-emerton Expose jsdav.require() for loading jsDAV components f52fc31
@james-emerton james-emerton Pass error message back to client and not to the auth handler when au…
…th fails
9716c93
@james-emerton james-emerton Bump libxmljs version 90790a8
@james-emerton james-emerton Fix require module case ec27975
@james-emerton james-emerton Don't synthesize the /principals/users collection 756a39e
@james-emerton james-emerton Added preliminary support for calendar-query report f8ee60e
@james-emerton james-emerton Log errors >= 500 even if debugMode is off 8664aba
@james-emerton james-emerton Don't swallow errors returned by ICollection.createFile() c673751
@james-emerton james-emerton Remove debugging cruft 1cce283
@james-emerton james-emerton 0.2.0 286d58e
@james-emerton james-emerton Added supported-calendar-component-set property object 8abc667
@james-emerton james-emerton Added calendar validation using beforeCreateFile and beforeWriteContent 78b300f
@james-emerton james-emerton Added some tests against CalDAV d80fe90
@james-emerton james-emerton Now requiring newer version of icalendar module f18da05
@james-emerton james-emerton version 0.2.1 8eb8841
@james-emerton james-emerton Fix a silly autocomplete-typo 45f5a20
@james-emerton james-emerton Bug fixes ea11ad1
@james-emerton james-emerton 0.2.2 0d9f6a3
@james-emerton james-emerton Fix for renamed method b84574b
@james-emerton james-emerton Error handling 1d8c4a9
@james-emerton james-emerton 0.2.3 0a6a93e
Owner

mikedeboer commented Feb 8, 2012

Wow! that's massive!!! thanks a ton for the contribution! I still need to thoroughly review your code, if you don't mind...

I also noticed that the pull request can not be automatically merged anymore - probably due to a large amount of changes I made recently. Could you extend you effort and try to merge master back into your branch?

Thanks a ton and I will try to find time to review as soon as possible.

I did merge your branch back into my repo a few weeks ago, but I fear I didn't do it correctly. I ended up with all of your changesets collapsing into a single changeset in my repo, which I suspect is creating the problem.

I'll try and fix that, and pull the latest changes in as well.

On 2012-02-08, at 9:53 AM, Mike de Boer wrote:

Wow! that's massive!!! thanks a ton for the contribution! I still need to thoroughly review your code, if you don't mind...

I also noticed that the pull request can not be automatically merged anymore - probably due to a large amount of changes I made recently. Could you extend you effort and try to merge master back into your branch?

Thanks a ton and I will try to find time to review as soon as possible.


Reply to this email directly or view it on GitHub:
#32 (comment)

LeytonC commented Feb 13, 2012

Hi Guys, i am needing to implement a *DAV server (the most urgent of these is a calDAV server, hence my post here - seems the best place to ask this question, mind you i never use github, so this might be an epic fail - sorry in advance)

How long approximately will it be until this code is available to use / try out? Basically we have our own group calendar software (PHP and mySQL) but we want to be able to enable calDAV based access to it from mobile devices. We are already using node for a basic chat server / push messaging system, and i would prefer to have a node server handling DAV requests to stop them killing Apache and PHP. I have had a look SabreDAV but it looks like a lot of hassle my side to make it work with our system. I am hoping jsDAV would be a better solution, and give me better resource utilisation.

Thank you for any help / comments in advance, and again i apologise for posting this here if there is a better place i just didn't find.

Leyton.

Hi Leyton,

You can try the code out today, even though it's not merged back to Mike's branch yet. Just clone github.com/tritech/jsDAV. You will find an example of a CalDAV server in examples/calendarserver.js

James

LeytonC commented Feb 13, 2012

Thank you for your help - i have the code, and i have it running, but i am out of time for today - i will take a look tomorrow.

Again thank you so much for your help. Speak to you soon.

LeytonC commented Feb 15, 2012

Hi James, thanks for your reply - i have cloned the code, npm'd what i needed to get it working - i hope you dont mind but i have a couple of questions to ask. I am not sure if its me (which it probably is) or code problems.

  1. In the example code, i have tried to change the name of the calendar - using iCal and i get the following error in iCal

The server responded with
“500”
to operation CalDAVSetPropertyQueueableOperation.

i am running calendarserver.js in a terminal window (node ver is 0.6.6 - osx) and that returns

uri: calendars/admin/calendar
Save cal data
{DAV:}displayname: My new calendar
[error] Invalid result from updateProperties
[error] Error
[error] at new (/Users/leytonc/calDAV/jsDAV/lib/DAV/exceptions.js:21:19)
[error] at Object.oncomplete (/Users/leytonc/calDAV/jsDAV/lib/DAV/handler.js:1836:42)

i modified the node.updateProperties routine to output some extra information that i thought might be useful - the original code line it was failing on was 1827, basically the updateResult parameter wasnt true, false or an object.

  1. I have the example server running on iCal and the iPhone - but when i try it in Lightning it wont work and generates a load of messages, it seems to be stuck in a loop somewhere. If you want i can try it again and get you a list of the messages it generates. I havent done yet in case you are aware of a problem and i would be waiting your time with an even larger email.

  2. With the sample calendar server app, i can see how to add extra users for authentication, this is very simple - but what i want to be able to have is a single calendar per users - rather than a list of everyones calendars to a logged in user. I just cannot see what i have to do to make it work like that. The getting and saving calendars is no problem, its just the ability to limit a logged in user to their own calendar is escaping me at the moment.

I thank you for help in advance - if you need anything else please contact me.

Leyton.

On 13 Feb 2012, at 16:53, James Emerton wrote:

Hi Leyton,

You can try the code out today, even though it's not merged back to Mike's branch yet. Just clone github.com/tritech/jsDAV. You will find an example of a CalDAV server in examples/calendarserver.js

James


Reply to this email directly or view it on GitHub:
#32 (comment)


Leyton Cleveley
Chief Software Engineer
Team Service (UK) Ltd.
Software to Empower Your Team

Home Page: www.teamservice.co.uk
Direct Tel: (0121) 288 0366
Mobile:(07525) 417121

Address: 171 Birmingham Road, Stratford-Upon-Avon, Warwickshire, England, United Kingdom, CV37 0AP

This email is private and confidential and is intended solely for the addressee. Access by or disclosure to anyone other than the intended recipient for any reason other than the purpose for which the message is intended, is unauthorized. If you are not the intended recipient, you are hereby notified that any dissemination, distribution, copying, reproduction, modification or publication of this communication is strictly prohibited. Please delete the message from your computer and notify the sender immediately. You should not retain the message or disclose its contents to anyone.

Internet communications are not secure and therefore Team Service (UK) Ltd., does not accept legal responsibility for the contents of this message. Any views or opinions presented are solely those of the author and do not necessarily represent those of Team Service (UK) Ltd., unless otherwise specifically stated. Team Service (UK), Limited is a company registered in England and Wales with company number 03448608

  1. In the example code I am simply passing the original callback through to writeFile(), which is not supplying a second parameter. This was probably something I didn't try in my testing. Add another callback that calls the original callback passed to updateCalendar() with (null, true) as the arguments.

  2. I am seeing a problem connecting from Lightning right now. Unfortunately, I'm busy with another project and can't look into it. I had it working with Lightning before, so this is likely a relatively small fix.

  3. I have not implemented any enforcement of ACLs in the DAVACL package; only enough of it to make CalDAV work in a highly permissive mode. You can use the code from SabreDAV as a reference and port over the DAVACL plugin's beforeMethod() handler. See https://github.com/evert/SabreDAV/blob/master/lib/Sabre/DAVACL/Plugin.php#L665

LeytonC commented Feb 16, 2012

Thank you for your prompt reply, i will take a look at the plugin when i get chance.

i am sure i will have some more questions later. Again thanks for you help

Leyton.

On 15 Feb 2012, at 19:02, James Emerton wrote:

  1. In the example code I am simply passing the original callback through to writeFile(), which is not supplying a second parameter. This was probably something I didn't try in my testing. Add another callback that calls the original callback passed to updateCalendar() with (null, true) as the arguments.

  2. I am seeing a problem connecting from Lightning right now. Unfortunately, I'm busy with another project and can't look into it. I had it working with Lightning before, so this is likely a relatively small fix.

  3. I have not implemented any enforcement of ACLs in the DAVACL package; only enough of it to make CalDAV work in a highly permissive mode. You can use the code from SabreDAV as a reference and port over the DAVACL plugin's beforeMethod() handler. See https://github.com/evert/SabreDAV/blob/master/lib/Sabre/DAVACL/Plugin.php#L665


Reply to this email directly or view it on GitHub:
#32 (comment)


Leyton Cleveley
Chief Software Engineer
Team Service (UK) Ltd.
Software to Empower Your Team

Home Page: www.teamservice.co.uk
Direct Tel: (0121) 288 0366
Mobile:(07525) 417121

Address: 171 Birmingham Road, Stratford-Upon-Avon, Warwickshire, England, United Kingdom, CV37 0AP

This email is private and confidential and is intended solely for the addressee. Access by or disclosure to anyone other than the intended recipient for any reason other than the purpose for which the message is intended, is unauthorized. If you are not the intended recipient, you are hereby notified that any dissemination, distribution, copying, reproduction, modification or publication of this communication is strictly prohibited. Please delete the message from your computer and notify the sender immediately. You should not retain the message or disclose its contents to anyone.

Internet communications are not secure and therefore Team Service (UK) Ltd., does not accept legal responsibility for the contents of this message. Any views or opinions presented are solely those of the author and do not necessarily represent those of Team Service (UK) Ltd., unless otherwise specifically stated. Team Service (UK), Limited is a company registered in England and Wales with company number 03448608

Warning: this.currentUser is not safe as this class is only instantiated once in the server and reused for every request. So in the middle of one async request, this variable may change! Just FYI.

Owner

james-emerton replied Mar 30, 2012

Plugin objects are instantiated by the handler for each request. They're owned by the handler object (also instantiated per request) and collected after each request has ended. See the jsDAV_Handler() constructor, handler.js:44.

Yes, the handler and the plugins are inited for each request. But the authBackend isn't: https://github.com/rocketpack/jsDAV/blob/master/lib/DAV/plugins/auth.js#L23

Owner

james-emerton replied Apr 2, 2012

Oh dear. It appears you're absolutely correct, but this is also an issue for the code before my changes. On a server with any amount of load this is going to return values that are all sorts of wrong and have the potential to be a huge security hole!

I think the correct thing to do is remove getCurrentUser() from the auth backend interface and pass the user to the authenticate() callback so that it can be stored in the per-connection instance of the auth plugin.

Thanks for bringing this to my attention.

Hi James, is there any specific reason why you made this change? The reason I'm asking is that, I'm currently playing this project, but found that method overriding is not working anymore, specifically, "getName()" of iNode. Run "test_server.js" and in the browser you'll find out that "getName()" alsways return "undefined" which is from the interface "iNode.js", not from subclasses, like jsDAV_FS_File. Please advise. Thanks, foster

Owner

james-emerton replied Jul 24, 2012

jsDAV_Base is implementation, whereas jsDAV_iNode defines the iNode interface. I actually made this change to be consistent with how interfaces and implementation classes are defined throughout the project. I'm pretty sure I was actually having a problem, but I don't recall what that was.

I did some research into your problem, and it seems this is because jsDAV_FS_File expects jsDAV_FS_Node to implement getName() (which it does.) Unfortunately, that implementation is overwritten by the default implementation when jsDAV_FS_File calls implement() for jsDAV_iFile (which inherits from jsDAV_iNode) and overwrites properties that have been defined by jsDAV_FS_Node.

Owner

james-emerton replied Jul 24, 2012

I've fixed the interfaces in 65b0e41

This is amazing! You are so great. Thanks.

BTW, what's the roadmap for this CalDAV feature? Are you actively working on it? Thanks,

Owner

james-emerton replied Jul 24, 2012

The CalDAV parts have been deployed in something of a "side project" for our company. Unfortunately, the project does not have my full attention, and jsDAV has even less. The roadmap is currently "eventually", but I will happily receive patches against the work. I also see there has been a lot of activity upstream, and I will reintegrate those changes in the near future.

This (admittedly very large) pull request has languished here for some time. I've just had a look at integrating some upstream changes, but there are a large number of merge conflicts and I suspect some duplicated efforts.

Would it be helpful if I were to create a new branch specifically for fixes to jsDAV itself, without any of the DAVACL or CalDAV parts? I can go back over these changesets and cherry-pick the ones that still apply.

arikon commented Sep 11, 2012

Do you plan to merge CalDAV support?

Owner

mikedeboer commented Sep 12, 2012

@ephelon and @arikon I am planning to merge CalDAV support as soon as possible! I am planning to put it into its own branch first, so that I can thoroughly prepare it and James, it might be wise to talk on Skype about some details...

My skype account name is the same as my GH username :)

The reason why I haven't worked on this sooner is because I was VERY busy with stuff at Cloud9 IDE. But now I'm able to put in a chunk of my spare time into the project again!

mikedeboer referenced this pull request Oct 24, 2012

Closed

CardDAV example #59

Owner

mikedeboer commented Feb 22, 2013

jsDAV has changed A LOT in two years. Current release is v0.3.0, which includes FULL DAVACL and CardDAV support. Granted, CalDAV is not there yet, but it will be more work to port @ephelon code over to the refactored object inheritance system than to port it directly from SabreDAV.

If you find this decision to be in error, please reopen the issue.

mikedeboer closed this Feb 22, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment