[CalendarServer-changes] [883]
CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Thu Dec 21 19:34:35 PST 2006
Revision: 883
http://trac.macosforge.org/projects/calendarserver/changeset/883
Author: cdaboo at apple.com
Date: 2006-12-21 19:34:35 -0800 (Thu, 21 Dec 2006)
Log Message:
-----------
Handle group member/membership for calendar proxies by using an SQL database to maintain the mappings. Do queries on
the DB to determine the list of members in each proxy and group, and to determine whether a regular principal is also
a member of a proxy group. The db lives on the top-level principal collection.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/calendaruserproxy.py
CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/directory/principal.py
CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/extensions.py
CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/resource.py
Modified: CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/calendaruserproxy.py 2006-12-22 00:51:16 UTC (rev 882)
+++ CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/calendaruserproxy.py 2006-12-22 03:34:35 UTC (rev 883)
@@ -15,9 +15,6 @@
#
# DRI: Wilfredo Sanchez, wsanchez at apple.com
##
-from twisted.internet.defer import succeed
-from twistedcaldav.extensions import ReadOnlyResourceMixIn
-from twisted.web2.http import Response
"""
Implements a calendar user proxy principal.
@@ -29,20 +26,41 @@
from urllib import unquote
+from twisted.internet.defer import succeed
from twisted.python import log
from twisted.python.failure import Failure
from twisted.web2 import responsecode
-from twisted.web2.http_headers import MimeType
from twisted.web2.dav import davxml
+from twisted.web2.dav.element.base import dav_namespace
from twisted.web2.dav.util import joinURL
+from twisted.web2.http import Response
+from twisted.web2.http_headers import MimeType
from twistedcaldav.extensions import DAVFile
+from twistedcaldav.extensions import ReadOnlyWritePropertiesResourceMixIn
from twistedcaldav.resource import CalendarPrincipalResource
+from twistedcaldav.sql import AbstractSQLDatabase
from twistedcaldav.static import AutoProvisioningFileMixIn
-class PermissionsMixIn (ReadOnlyResourceMixIn):
+import os
+
+class PermissionsMixIn (ReadOnlyWritePropertiesResourceMixIn):
def defaultAccessControlList(self):
- return authReadACL
+ aces = (
+ # DAV:read access for authenticated users.
+ davxml.ACE(
+ davxml.Principal(davxml.Authenticated()),
+ davxml.Grant(davxml.Privilege(davxml.Read())),
+ ),
+ # Inheritable DAV:all access for the resource's associated principal.
+ davxml.ACE(
+ davxml.Principal(davxml.HRef(self.parent.principalURL())),
+ davxml.Grant(davxml.Privilege(davxml.WriteProperties())),
+ davxml.Protected(),
+ ),
+ )
+
+ return davxml.ACL(*aces)
def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
# Permissions here are fixed, and are not subject to inherritance rules, etc.
@@ -70,6 +88,21 @@
# lookups.
self.provision()
+ def _index(self):
+ """
+ Return the SQL database for this group principal.
+
+ @return: the L{CalendarUserProxyDatabase} for the principal collection.
+ """
+
+ # Get the principal collection we are contained in
+ pcollection = self.parent.parent.parent
+
+ # The db is located in the principal collection root
+ if not hasattr(pcollection, "calendar_user_proxy_db"):
+ setattr(pcollection, "calendar_user_proxy_db", CalendarUserProxyDatabase(pcollection.fp.path))
+ return pcollection.calendar_user_proxy_db
+
def resourceType(self):
if self.type == "calendar-proxy-read":
return davxml.ResourceType.calendarproxyread
@@ -78,6 +111,21 @@
else:
return super(CalendarUserProxyPrincipalResource, self).resourceType()
+ def writeProperty(self, property, request):
+ assert isinstance(property, davxml.WebDAVElement)
+
+ if property.qname() == (dav_namespace, "group-member-set"):
+ return self.setGroupMemberSet(property, request)
+
+ return super(CalendarUserProxyPrincipalResource, self).writeProperty(property, request)
+
+ def setGroupMemberSet(self, new_members, request):
+
+ # Break out the list into a set of URIs.
+ members = [str(h) for h in new_members.children]
+ self._index().setGroupMembers(self._url, members)
+ return succeed(True)
+
##
# HTTP
##
@@ -171,15 +219,123 @@
def principalURL(self):
return self._url
+ def principalCollections(self):
+ return self.parent.principalCollections()
+
def groupMembers(self):
- return ()
+ return self._index().getMembers(self._url)
def groupMemberships(self):
- return ()
+ return self._index().getMemberships(self._url)
- def principalCollections(self):
- return self.parent.principalCollections()
+class CalendarUserProxyDatabase(AbstractSQLDatabase):
+ """
+ A database to maintain calendar user proxy group memberships.
+
+ SCHEMA:
+
+ Group Database:
+
+ ROW: GROUPNAME, MEMBER
+
+ """
+
+ dbType = "CALENDARUSERPROXY"
+ dbFilename = ".db.calendaruserproxy"
+ dbFormatVersion = "1"
+
+ def __init__(self, path):
+ path = os.path.join(path, CalendarUserProxyDatabase.dbFilename)
+ super(CalendarUserProxyDatabase, self).__init__(path, CalendarUserProxyDatabase.dbFormatVersion)
+
+ def setGroupMembers(self, principalURI, members):
+ """
+ Add a group membership record.
+
+ @param principalURI: the principalURI of the group principal to add.
+ @param members: the list of principalURIs that are members of this group.
+ """
+
+ # Remove what is there, then add it back.
+ self._delete_from_db(principalURI)
+ self._add_to_db(principalURI, members)
+ self._db_commit()
+
+ def removeGroup(self, principalURI):
+ """
+ Remove a group membership record.
+
+ @param principalURI: the principalURI of the group principal to add.
+ """
+ self._delete_from_db(principalURI)
+ self._db_commit()
+
+ def getMembers(self, principalURI):
+ """
+ Return the list of group members for the specified principal.
+ """
+ members = set()
+ for row in self._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", principalURI):
+ members.add(row[0])
+ return members
+
+ def getMemberships(self, principalURI):
+ """
+ Return the list of groups the specified principal is a member of.
+ """
+ members = set()
+ for row in self._db_execute("select GROUPNAME from GROUPS where MEMBER = :1", principalURI):
+ members.add(row[0])
+ return members
+
+ def _add_to_db(self, principalURI, members):
+ """
+ Insert the specified entry into the database.
+
+ @param principalURI: the principalURI of the group principal to remove.
+ @param members: the list of principalURIs that are members of this group.
+ """
+ for member in members:
+ self._db_execute(
+ """
+ insert into GROUPS (GROUPNAME, MEMBER)
+ values (:1, :2)
+ """, principalURI, member
+ )
+
+ def _delete_from_db(self, principalURI):
+ """
+ Deletes the specified entry from the database.
+
+ @param principalURI: the principalURI of the group principal to remove.
+ """
+ self._db_execute("delete from GROUPS where GROUPNAME = :1", principalURI)
+
+ def _db_type(self):
+ """
+ @return: the collection type assigned to this index.
+ """
+ return CalendarUserProxyDatabase.dbType
+
+ def _db_init_data_tables(self, q):
+ """
+ Initialise the underlying database tables.
+ @param q: a database cursor to use.
+ """
+
+ #
+ # GROUPS table
+ #
+ q.execute(
+ """
+ create table GROUPS (
+ GROUPNAME text,
+ MEMBER text
+ )
+ """
+ )
+
##
# Utilities
##
Modified: CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/directory/principal.py 2006-12-22 00:51:16 UTC (rev 882)
+++ CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/directory/principal.py 2006-12-22 03:34:35 UTC (rev 883)
@@ -38,6 +38,7 @@
from twisted.web2.dav.util import joinURL
from twistedcaldav.config import config
+from twistedcaldav.calendaruserproxy import CalendarUserProxyDatabase
from twistedcaldav.calendaruserproxy import CalendarUserProxyPrincipalResource
from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVFile
from twistedcaldav.resource import CalendarPrincipalCollectionResource, CalendarPrincipalResource
@@ -361,11 +362,29 @@
return relatives
+ def _calendar_user_proxy_index(self):
+ """
+ Return the SQL database for calendar user proxies.
+
+ @return: the L{CalendarUserProxyDatabase} for the principal collection.
+ """
+
+ # Get the principal collection we are contained in
+ pcollection = self.parent.parent
+
+ # The db is located in the principal collection root
+ if not hasattr(pcollection, "calendar_user_proxy_db"):
+ setattr(pcollection, "calendar_user_proxy_db", CalendarUserProxyDatabase(pcollection.fp.path))
+ return pcollection.calendar_user_proxy_db
+
def groupMembers(self):
return self._getRelatives("members")
def groupMemberships(self):
- return self._getRelatives("groups")
+ groups = self._getRelatives("groups")
+ if config.CalendarUserProxyEnabled:
+ groups.update(self._calendar_user_proxy_index().getMemberships(self._url))
+ return groups
def principalCollections(self):
return self.parent.principalCollections()
Modified: CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/extensions.py 2006-12-22 00:51:16 UTC (rev 882)
+++ CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/extensions.py 2006-12-22 03:34:35 UTC (rev 883)
@@ -286,3 +286,19 @@
def writeProperty(self, property, request):
raise HTTPError(self.readOnlyResponse)
+
+class ReadOnlyWritePropertiesResourceMixIn (object):
+ """
+ Read only that will allow writing of properties resource.
+ """
+ readOnlyResponse = StatusResponse(
+ responsecode.FORBIDDEN,
+ "Resource is read only."
+ )
+
+ def _forbidden(self, request):
+ return self.readOnlyResponse
+
+ http_DELETE = _forbidden
+ http_MOVE = _forbidden
+ http_PUT = _forbidden
Modified: CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/resource.py 2006-12-22 00:51:16 UTC (rev 882)
+++ CalendarServer/branches/users/cdaboo/cuproxy-857/twistedcaldav/resource.py 2006-12-22 03:34:35 UTC (rev 883)
@@ -607,6 +607,12 @@
return maybeDeferred(defer)
+ def groupMembers(self):
+ return ()
+
+ def groupMemberships(self):
+ return ()
+
def calendarHomeURLs(self):
if self.hasDeadProperty((caldav_namespace, "calendar-home-set")):
home_set = self.readDeadProperty((caldav_namespace, "calendar-home-set"))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20061221/2d404bd6/attachment.html
More information about the calendarserver-changes
mailing list