Permissions Redesign

From Davical
Revision as of 12:19, 22 January 2008 by Karora (talk)
Jump to navigationJump to search

Background

The Permissions system in DAViCal really needs a redesign. This is so for several reasons:

  1. It's backwards. Currently relationships are described in the wrong directional tense, even though they are controlled correctly (for user <-> user relationships at least).
  2. It's arcane. The abuse of a single relationship type for relationships among a group vs. through a group is confusing for the end user.
  3. It's inadequate for expressing RFC3744 (DAV Access Control) which is what calendaring clients can potentially use to manipulate the relationships & permissions from outside of the web interface.

This proposal goes significantly further than the earlier Improved Permissions proposal. In particular this proposal should provide a one to one mapping against the DAV permissions model which should mean that clients developing a UI against that model will work with DAViCal.

High Level Design

Principals

One starting point would be to apply stronger typing to what are currently called 'Users' in DAViCal. In the DAV specification these beasts are called 'Principals' and RFC3744 has a nice piece of eloquence to describe these (section 2):

"A principal is a network resource that represents a distinct human or computational actor that initiates access to network resources. Users and groups are represented as principals in many implementations; other types of principals are also possible."


That's an excellent piece of phrasing and although these are really all the same kind of thing we should separate some elements of them out from the way DAViCal does things. Even just doing it at the user interface level will have some decent gains, since there will be a 'Principals' menu option with sub-menu options for 'Users', 'Groups' and 'Resources'. Each of those would have a list of the relevant records which could be edited.

Working in this way it would immediately become clear that something which was a 'Group' doesn't need all of the detail associated with a 'User', and so we can provide alternative presentations of the data to simplify the maintenance.

The current database structure does not contain a 'principal' table, using the user record to represent this. This approach has served well, but is unlikely to be sufficient for a full implementation. As of version 0.9.2 there is already a programming object interface to represent this data internally, and this should be backed by a real database object as well.

Relationships

A large part of the motivation behind this redesign is to support RFC3744 in a more comprehensive manner than at present. The permissions currently available in DAViCal need extension in some areas to handle the more fine-grained authority described within RFC3744 itself, but also the extensions added in RFC4791 (CalDAV) and in the draft scheduling extensions to caldav.

One thing that needs to be noted is that all permissions are one-way.

Alarms

Another important option to consider is the retrieval or action of 'VALARM' components. While it is arguably a client-side activity to select which calendars should be considered as worth notification, it remains a useful heuristic for those clients where this is not selectable, to be able to not receive the alarms for "calendars which aren't mine". Possibly the 'alarm set' could be controlled through the web interface, as a server-side implementation of the client-side lack.

Database Structures

principal_type

Defining the available types of principals.

  • principal_type_id SERIAL
  • principal_type_desc TEXT

Only needs SELECT access by website.

principal

Providing storage for principal objects.

  • principal_id SERIAL
  • type_id INT NOT NULL REFERENCES principal_type(principal_type_id)
  • user_no NULL ALLOWED REFERENCES usr(user_no)
  • displayname
  • ...

resource_type

Defining the available types of resources (DAV:resourcetype) to which access controls may be applied.

  • resource_type_id SERIAL
  • dav_resource_type TEXT
  • resource_type_desc TEXT

Only needs SELECT access by website. dav_resource_type will be 'principal', 'collection', 'CalDAV:calendar' and so forth.

resource

Basic entity which can be the target of a permissions grant.

  • dav_name A pathname, of sorts.
  • resource_type_id REFERENCES resource_type(resource_type_id)
  • owner_id REFERENCES principal(principal_id)

privilege

Rules describing the set of privileges granted to access a resource.

  • granted_to_id REFERENCES principal(principal_id)
  • resource_path REFERENCES resource(dav_name)
  • granted_by_id REFERENCES principal(principal_id)
  • can_read BOOLEAN
  • can_write BOOLEAN
  • can_write_properties BOOLEAN
  • can_write_content BOOLEAN
  • can_unlock BOOLEAN
  • can_read_acl BOOLEAN
  • can_read_current_user_privilege_set BOOLEAN
  • can_write_acl BOOLEAN
  • can_bind BOOLEAN
  • can_unbind BOOLEAN
  • can_read_free_busy BOOLEAN CalDAV:read-free-busy privilege.

Functional Requirements

The primary operation of permissions is to ascertain whether the logged in user can X the target resource. The X can be any one of the DAV/CalDAV privileges listed above and the logged in user will (always) map to a principal.

That seems simple enough, except that this can happen through a series of intermediate principals meaning that the path from logged in user to target resource could potentially be arbitrarily complex. RFC3744 specifies that <quote>a server may allow a group to be a member of another group</quote> so to simplify things we will limit the number of allowed intermediate steps.