[CalendarServer-changes] [348]
CalendarServer/trunk/twistedcaldav/directory.py
source_changes at macosforge.org
source_changes at macosforge.org
Wed Nov 1 17:45:49 PST 2006
Revision: 348
http://trac.macosforge.org/projects/calendarserver/changeset/348
Author: wsanchez at apple.com
Date: 2006-11-01 17:45:49 -0800 (Wed, 01 Nov 2006)
Log Message:
-----------
Add IDirectoryService, IDirectoryRecord interfaces.
Add DirectoryRecord, OpenDirectoryService, OpenDirectoryRecord implementations.
Make all properties of DirectoryPrincipalFile read-only; data comes from the directory; we never edit.
Use calendarUserAddresses() to implement calendar-user-address-set property.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/directory.py
Modified: CalendarServer/trunk/twistedcaldav/directory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory.py 2006-11-01 18:45:56 UTC (rev 347)
+++ CalendarServer/trunk/twistedcaldav/directory.py 2006-11-02 01:45:49 UTC (rev 348)
@@ -28,7 +28,7 @@
"DirectoryPrincipalProvisioningResource",
]
-from zope.interface import implements
+from zope.interface import implements, Attribute, Interface
from twisted.cred import checkers, credentials, error
from twisted.cred.credentials import UsernamePassword
@@ -58,6 +58,122 @@
import os
import unicodedata
+class IDirectoryService(Interface):
+ """
+ Directory Service
+ """
+ def recordTypes():
+ """
+ @return: a sequence of strings denoting the record types that are kept
+ in the directory. For example: C{["users", "groups", "resources"]}.
+ """
+
+ def listRecords(type):
+ """
+ @param type: the type of records to retrieve.
+ @return: an iterable of records of the given type.
+ """
+
+class IDirectoryRecord(Interface):
+ """
+ Directory Record
+ """
+ directory = Attribute("The L{IDirectoryService} this record exists in.")
+ recordType = Attribute("The type of this record.")
+ guid = Attribute("The GUID of this record.")
+ shortName = Attribute("The name of this record.")
+ fullName = Attribute("The full name of this record.")
+ calendarUserAddresses = Attribute("A sequence of calendar user addresses of this record.")
+
+ def authenticate(credentials):
+ """
+ Verify that the given credentials can authenticate the principal
+ represented by this record.
+ @param credentials: the credentials to authenticate with.
+ @return: C{True} if the given credentials match this record,
+ C{False} otherwise.
+ """
+
+class DirectoryRecord(object):
+ implements(IDirectoryRecord)
+
+ def __init__(self, directory, recordType, guid, shortName, fullName=None, calendarUserAddresses=()):
+ self.directory = directory
+ self.recordType = recordType
+ self.guid = guid
+ self.shortName = shortName
+ self.fullName = fullName
+ self.calendarUserAddresses = calendarUserAddresses
+
+ def authenticate(credentials):
+ return False
+
+class OpenDirectoryService(object):
+ """
+ Open Directory implementation of L{IDirectoryService}.
+ """
+ implements(IDirectoryService)
+
+ def __init__(self, node="/Search"):
+ directory = opendirectory.odInit(node)
+ if directory is None:
+ raise ValueError("Failed to open Open Directory Node: %s" % (node,))
+
+ self._directory = directory
+
+ def recordTypes(self):
+ return ("users", "groups", "resources")
+
+ def listRecords(self, recordType):
+ def makeRecord(shortName, guid, lastModified, principalURI):
+ if not guid:
+ return None
+
+ ##
+ # FIXME: Also verify that principalURI is on this server
+ # Which probably means that the host information needs to be on
+ # the site object, and that we need the site object passed to
+ # __init__() here.
+ ##
+
+ return OpenDirectoryRecord(
+ directory = self,
+ recordType = recordType,
+ guid = guid,
+ shortName = shortName,
+ fullName = None,
+ calendarUserAddresses = (),
+ )
+
+ if recordType == "users":
+ for data in opendirectory.listUsers(self._directory):
+ yield makeRecord(*data)
+ return
+
+ if recordType == "groups":
+ for data in opendirectory.listGroups(self._directory):
+ yield makeRecord(*data)
+ return
+
+ if recordType == "resources":
+ for data in opendirectory.listResources(self._directory):
+ yield makeRecord(*data)
+ return
+
+ raise AssertionError("Unknown Open Directory record type: %s" % (recordType,))
+
+class OpenDirectoryRecord(DirectoryRecord):
+ """
+ Open Directory implementation of L{IDirectoryRecord}.
+ """
+ def authenticate(self, credentials):
+ if isinstance(credentials, credentials.UsernamePassword):
+ return opendirectory.authenticateUser(self.directory, self.shortName, credentials.password)
+
+ return False
+
+######################
+
class DirectoryCredentialsChecker (TwistedPropertyChecker):
def requestAvatarId(self, credentials):
@@ -173,10 +289,6 @@
return self.getPropertyValue(customxml.TwistedGUIDProperty)
def readProperty(self, property, request):
- """
- Override inherited behavior to make calendar-user-address-set property 'protected'/'live'
- """
-
if type(property) is tuple:
qname = property
else:
@@ -184,35 +296,21 @@
namespace, name = qname
- # Only return the calendar prinicpal URI when calendar-user-address-set is requested.
if namespace == caldavxml.caldav_namespace:
if name == "calendar-user-address-set":
- return succeed(caldavxml.CalendarUserAddressSet(davxml.HRef().fromString(self.getPropertyValue(customxml.TwistedCalendarPrincipalURI))))
+ return succeed(caldavxml.CalendarUserAddressSet(
+ *[davxml.HRef().fromString(uri) for uri in self.calendarUserAddresses()]
+ ))
return super(DirectoryPrincipalFile, self).readProperty(qname, request)
def writeProperty(self, property, request):
- """
- Override inherited behavior to make calendar-user-address-set property 'protected'/'live'
- """
+ # This resource is read-only.
+ raise HTTPError(StatusResponse(
+ responsecode.FORBIDDEN,
+ "Protected property %s may not be set." % (property.sname(),)
+ ))
- if type(property) is tuple:
- qname = property
- else:
- qname = property.qname()
-
- namespace, name = qname
-
- # Don't allow changes to the calendar-user-address set as the value comes from the directory.
- if namespace == caldavxml.caldav_namespace:
- if name == "calendar-user-address-set":
- raise HTTPError(StatusResponse(
- responsecode.FORBIDDEN,
- "Protected property %s may not be set." % (property.sname(),)
- ))
-
- return super(DirectoryPrincipalFile, self).readProperty(qname, request)
-
def calendarUserAddresses(self):
# Must have a valid calendar principal uri
if self.hasDeadProperty(customxml.TwistedCalendarPrincipalURI):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20061101/bad96adf/attachment.html
More information about the calendarserver-changes
mailing list