Skip to content

Improve ACL Management for Shared Calendars #372

Open

Description

@adri-M

Improve ACL Management for Shared Calendars

Context

Currently, Agendav handles calendar sharing by:

  • Adding an existing user via the interface (with read or read-write permissions).
  • Recording an entry in the database (shares table) 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 shares table.
  • 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:

  1. Dynamically fetch the list of users with access to a calendar (or collection) using a PROPFIND request with <D:acl>.
  2. Synchronize this information with Agendav’s database (shares table), or simply remove shared table?!
  3. 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>
EOF

Response (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, ttiti has read and read-free-busy permissions 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>
EOF

Note: 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-m has read permission 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 PROPFIND request 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 shares table (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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions