Repository navigation
Improve ACL Management for Shared Calendars #372
Description
Improve ACL Management for Shared Calendars
Context
Currently, Agendav handles calendar sharing by:
- Adding an existing user via the interface (with
readorread-writepermissions). - Recording an entry in the database (
sharestable) to track shares made through Agendav. - Sending a DAV request (RFC 3744) to apply permissions on the CalDAV server (e.g., Davical).
Example SQL entry:
(1,'/caldav.php/ttest/','/caldav.php/ttest/calendar/','/caldav.php/ttiti/','[]',0);Problem
If a share is created outside of Agendav (e.g., via Apple Calendar, a Davical web interface, or another CalDAV client):
- No entry is created in Agendav’s
sharestable. - Consequences:
- The shared user does not appear in Agendav’s sharing list.
- It is impossible to modify or remove their permissions via Agendav.
- No visibility on who actually has access to the calendar.
Impact: This is an issue in environments where users rely on multiple CalDAV clients (e.g., Agendav + Apple Calendar + Davical interface).
Proposed Solution
Leverage the ACL discovery mechanism defined in RFC 3744 (WebDAV ACL) to:
- Dynamically fetch the list of users with access to a calendar (or collection) using a
PROPFINDrequest with<D:acl>. - Synchronize this information with Agendav’s database (
sharestable), or simply remove shared table?! - Allow users to modify/remove permissions even if the initial share was not created through Agendav.
Benefit: Centralized permission management in Agendav, regardless of the sharing origin. As far as I am aware, Agendav will be the only open-source web interface that manages access rights and discovery – for both users and groups – via RFC 3744, and does so for all servers that comply with this standard.
Example CalDAV Requests
1. Fetch ACLs for a Calendar
Request to my davical using basic user auth:
curl -u "ttest:PASSWORD" \
-X PROPFIND \
-H "Depth: 0" \
-H "Content-Type: application/xml; charset=utf-8" \
--data-binary @- \
https://calendar.mydomain.fr/caldav.php/ttest/calendar/ <<'EOF'
<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
<D:prop>
<D:acl/>
</D:prop>
</D:propfind>
EOFResponse (excerpt):
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
<response>
<href>/caldav.php/ttest/calendar/</href>
<propstat>
<prop>
<acl>
<ace>
<principal>
<href>/caldav.php/ttiti/</href>
</principal>
<grant>
<privilege>
<read/>
</privilege>
<privilege>
<C:read-free-busy/>
</privilege>
</grant>
</ace>
<ace>
</acl>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>→ Here,
ttitihasreadandread-free-busypermissions on/ttest/calendar/.
2. Fetch ACLs for a Principal (Optional)
Request to my davical using basic user auth:
curl -u "ttest:PASSWORD" \
-X PROPFIND \
-H "Depth: 0" \
-H "Content-Type: application/xml; charset=utf-8" \
--data-binary @- \
https://calendar.mydomain.fr/caldav.php/ttest/ <<'EOF'
<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
<D:prop>
<D:acl/>
</D:prop>
</D:propfind>
EOFNote: Permissions on the principal are cascaded to collections if the Default Privileges option is enabled in Davical. See #368
Example response (excerpt):
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
<response>
<href>/caldav.php/ttest/</href>
<propstat>
<prop>
<acl>
<ace>
<principal>
<href>/caldav.php/adri-m/</href>
</principal>
<grant>
<privilege>
<read/>
</privilege>
<privilege>
<read-current-user-privilege-set/>
</privilege>
</grant>
</ace>
</acl>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>→
adri-mhasreadpermission on the principal/ttest/(and thus on its collections, such as/ttest/calendar/if the ‘default rights’ box is ticked in davical server).
Technical Recommendations
- Do not process principal ACLs: Focus on individual collections (calendars), as is already done today.
- Use user permissions: The
PROPFINDrequest can be executed with the calendar owner’s credentials (no admin rights required). - Periodic synchronization? Consider this to avoid desynchronization (e.g., shares added via another client between Agendav sessions). Maybe refresh at "share" click on the web interface?
Current Workaround
"For years, I’ve used a Perl script to scan all shares and manually add them to Agendav’s database. It works, but it’s a hack! Native integration would be much cleaner."
Expected Outcomes
- Implement ACL fetching via
PROPFIND(RFC 3744). - Synchronize ACLs with Agendav’s
sharestable (or simply remove this table?!). - Allow permission modification/removal regardless of the sharing origin.
- (Optional) Add a manual refresh option for ACLs in the interface.
Tested Environment:
- CalDAV Server: Davical 1.1.12
- Client: Agendav 3.3.1
- Protocol: WebDAV ACL (RFC 3744)
I am, of course, available to help with this improvement and carry out the necessary tests.
PS: Text enhanced by AI for clarity and translation
Activity