[CalendarServer-changes] [4072] CalendarServer/branches/users/sagen/resource-delegates-4066
source_changes at macosforge.org
source_changes at macosforge.org
Thu Apr 23 16:47:08 PDT 2009
Revision: 4072
http://trac.macosforge.org/projects/calendarserver/changeset/4072
Author: sagen at apple.com
Date: 2009-04-23 16:47:07 -0700 (Thu, 23 Apr 2009)
Log Message:
-----------
Merging branch forward
Modified Paths:
--------------
CalendarServer/branches/users/sagen/resource-delegates-4066/bin/caldav_utility.py
CalendarServer/branches/users/sagen/resource-delegates-4066/calendarserver/tools/util.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/customxml.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/appleopendirectory.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingappleopendirectory.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingdirectory.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingxmlfile.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/calendaruserproxy.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/directory.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/idirectory.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/principal.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/sqldb.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/accounts.xml
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_cachedirectory.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectory.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectoryrecords.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_principal.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_proxyprincipalmembers.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_xmlfile.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlaccountsparser.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlfile.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/memcachepool.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/resource.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/scheduling/processing.py
CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/test/test_memcachepool.py
Property Changed:
----------------
CalendarServer/branches/users/sagen/resource-delegates-4066/
CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-privatecomments.txt
CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-privatecomments.xml
CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-schedulingchanges.txt
CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-schedulingchanges.xml
Property changes on: CalendarServer/branches/users/sagen/resource-delegates-4066
___________________________________________________________________
Added: svn:mergeinfo
+ /CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/bin/caldav_utility.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/bin/caldav_utility.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/bin/caldav_utility.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -18,6 +18,7 @@
from __future__ import with_statement
+
import sys
if "PYTHONPATH" in globals():
@@ -37,53 +38,313 @@
# sys.path.insert(0, "/usr/share/caldavd/lib/python")
-import os
-import itertools
-from code import interact
-
+from calendarserver.provision.root import RootResource
from getopt import getopt, GetoptError
-from os.path import dirname, abspath
-
from twisted.internet import reactor
+from twisted.internet.address import IPv4Address
from twisted.internet.defer import inlineCallbacks, returnValue, succeed
from twisted.python import log
from twisted.python.reflect import namedClass
from twisted.web2.dav import davxml
-# from twisted.web2.http import Request
-
-from twistedcaldav import ical
from twistedcaldav import caldavxml
-from twistedcaldav.resource import isPseudoCalendarCollectionResource
-from twistedcaldav.static import CalDAVFile, CalendarHomeFile, CalendarHomeProvisioningFile
+from twistedcaldav import memcachepool
from twistedcaldav.config import config, defaultConfigFile
+from twistedcaldav.customxml import calendarserver_namespace
from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
+from twistedcaldav.log import setLogLevelForNamespace
+from twistedcaldav.notify import installNotificationClient
+from twistedcaldav.static import CalendarHomeProvisioningFile
+import itertools
+import os
-from calendarserver.provision.root import RootResource
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+def usage(e=None):
+ if e:
+ print e
+ print ""
-from twistedcaldav import memcachepool
-from twistedcaldav.notify import installNotificationClient
-from twisted.internet.address import IPv4Address
+ name = os.path.basename(sys.argv[0])
+ print "usage: %s [options]" % (name,)
+ print ""
+ print "options:"
+ print " -h --help: print this help and exit"
+ print " -f --config <path>: Specify caldavd.plist configuration path"
+ print " --resource <prinicpal-path>: path of the resource to use"
+ print " --read-property: namespace-qualified DAV property to read, e.g. 'DAV:#group-member-set'"
+ print " --list-read-delegates: list delegates with read-only access to the current resource"
+ print " --list-write-delegates: list delegates with read-write access to the current resource"
+ print " --add-read-delegate <prinicpal-path>: add argument as a read-only delegate to the current resource"
+ print " --add-write-delegate <prinicpal-path>: add argument as a read-write delegate to the current resource"
+ print " --remove-delegate <prinicpal-path>: strip argument of delegate status for the current resource"
+ print " --set-auto-schedule [true|false] : determines whether the current resource auto-accepts invitations"
+ print " --get-auto-schedule : returns the current resource's auto-schedule state"
-# This dictionary is a mapping of symbols that other modules might want
-# to use; it's populated by the @exportmethod decorator below.
-exportedSymbols = { }
+ if e:
+ sys.exit(64)
+ else:
+ sys.exit(0)
-def exportmethod(method):
- """ Add the method to exportedSymbols """
- global exportedSymbols
- exportedSymbols[method.func_name] = method
- return method
+class UsageError (StandardError):
+ pass
-def getExports(**kw):
- """ Return a copy of exportedSymbols, with kw included """
- exports = exportedSymbols.copy()
- exports.update(**kw)
- return exports
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+def main():
+ try:
+ (optargs, args) = getopt(
+ sys.argv[1:], "hf:r:s", [
+ "config=",
+ "help",
+ "resource=",
+ "read-property=",
+ "list-read-delegates",
+ "list-write-delegates",
+ "add-read-delegate=",
+ "add-write-delegate=",
+ "remove-delegate=",
+ "set-auto-schedule=",
+ "get-auto-schedule",
+ ],
+ )
+ except GetoptError, e:
+ usage(e)
+ if args:
+ usage("Too many arguments: %s" % (" ".join(args),))
+ logFileName = "/dev/stdout"
+ observer = log.FileLogObserver(open(logFileName, "a"))
+ log.addObserver(observer.emit)
+
+ # First pass through the args:
+
+ configFileName = None
+
+ for opt, arg in optargs:
+ if opt in ("-h", "--help"):
+ usage()
+
+ elif opt in ("-f", "--config"):
+ configFileName = arg
+
+ loadConfig(configFileName)
+ directory, root = setup()
+ root = ResourceWrapper(root)
+
+ reactor.callLater(0, run, directory, root, optargs)
+ reactor.run()
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ at inlineCallbacks
+def run(directory, root, optargs):
+
+ resource = None
+
+ for opt, arg in optargs:
+
+ if opt in ("-r", "--resource",):
+ resource = root.getChild(arg)
+ if resource is not None:
+ print "Found resource %s at %s" % (resource.resource, arg)
+ else:
+ abort("Could not find resource at %s" % (arg,))
+
+ elif opt in ("--read-property",):
+ if resource is None: abort("No current resource.")
+
+ try:
+ namespace, name = arg.split("#")
+ except Exception, e:
+ abort("Can't parse --propertyToRead: %s" % (arg,))
+
+ result = (yield resource.readProperty((namespace, name)))
+ print result.toxml()
+
+ elif opt in ("--list-write-delegates", "--list-read-delegates"):
+ if resource is None: abort("No current resource.")
+
+ permission = "write" if "write" in opt else "read"
+ print "Delegates (%s) for %s:" % (permission, resource.resource)
+ paths = (yield resource.getDelegates(permission))
+ for path in paths:
+ delegate = root.getChild(path)
+ print delegate.resource
+
+ elif opt in ("--add-write-delegate", "--add-read-delegate"):
+ if resource is None: abort("No current resource.")
+
+ delegate = root.getChild(arg)
+ if delegate is None:
+ abort("No delegate found for %s" % (arg,))
+
+ permission = "write" if "write" in opt else "read"
+ result = (yield resource.addDelegate(delegate, permission))
+
+ elif opt == "--remove-delegate":
+ if resource is None: abort("No current resource.")
+
+ delegate = root.getChild(arg)
+ if delegate is None:
+ abort("No delegate found for %s" % (arg,))
+
+ result = (yield resource.removeDelegate(delegate, "read"))
+ result = (yield resource.removeDelegate(delegate, "write"))
+
+ elif opt == "--set-auto-schedule":
+ if resource is None: abort("No current resource.")
+
+ result = (yield resource.setAutoSchedule(arg.lower() in ("true", "1")))
+
+ elif opt == "--get-auto-schedule":
+ if resource is None: abort("No current resource.")
+
+ result = (yield resource.getAutoSchedule())
+ print "Auto-Schedule: %s" % ("True" if result else "False",)
+
+
+ # reactor.callLater(0, reactor.stop)
+ reactor.stop()
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+class ResourceWrapper(object):
+
+ def __init__(self, resource):
+ self.resource = resource
+
+ def readProperty(self, prop):
+ return self.resource.readProperty(prop, FakeRequest())
+
+ def writeProperty(self, prop):
+ return self.resource.writeProperty(prop, FakeRequest())
+
+ def getChild(self, path):
+ resource = self.resource
+ segments = path.strip("/").split("/")
+ for segment in segments:
+ resource = resource.getChild(segment)
+ if resource is None:
+ return None
+ return ResourceWrapper(resource)
+
+ @inlineCallbacks
+ def removeDelegate(self, delegate, permission):
+ subPrincipalName = "calendar-proxy-%s" % (permission,)
+ subPrincipal = self.getChild(subPrincipalName)
+ if subPrincipal is None:
+ abort("No proxy subprincipal found for %s" % (self.resource,))
+
+ namespace, name = davxml.dav_namespace, "group-member-set"
+ prop = (yield subPrincipal.readProperty((namespace, name)))
+ newChildren = []
+ for child in prop.children:
+ if str(child) != delegate.url():
+ newChildren.append(child)
+
+ if len(prop.children) == len(newChildren):
+ # Nothing to do -- the delegate wasn't there
+ returnValue(False)
+
+ newProp = davxml.GroupMemberSet(*newChildren)
+ result = (yield subPrincipal.writeProperty(newProp))
+ returnValue(result)
+
+ @inlineCallbacks
+ def addDelegate(self, delegate, permission):
+
+ opposite = "read" if permission == "write" else "write"
+ result = (yield self.removeDelegate(delegate, opposite))
+
+ subPrincipalName = "calendar-proxy-%s" % (permission,)
+ subPrincipal = self.getChild(subPrincipalName)
+ if subPrincipal is None:
+ abort("No proxy subprincipal found for %s" % (self.resource,))
+
+ namespace, name = davxml.dav_namespace, "group-member-set"
+ prop = (yield subPrincipal.readProperty((namespace, name)))
+ for child in prop.children:
+ if str(child) == delegate.url():
+ # delegate is already in the group
+ break
+ else:
+ # delegate is not already in the group
+ newChildren = list(prop.children)
+ newChildren.append(davxml.HRef(delegate.url()))
+ newProp = davxml.GroupMemberSet(*newChildren)
+ result = (yield subPrincipal.writeProperty(newProp))
+ returnValue(result)
+
+ @inlineCallbacks
+ def getDelegates(self, permission):
+
+ subPrincipalName = "calendar-proxy-%s" % (permission,)
+ subPrincipal = self.getChild(subPrincipalName)
+ if subPrincipal is None:
+ abort("No proxy subprincipal found for %s" % (self.resource,))
+
+ namespace, name = davxml.dav_namespace, "group-member-set"
+ prop = (yield subPrincipal.readProperty((namespace, name)))
+ result = []
+ for child in prop.children:
+ result.append(str(child))
+ returnValue(result)
+
+ def setAutoSchedule(self, autoSchedule):
+ return self.resource.setAutoSchedule(autoSchedule)
+
+ def getAutoSchedule(self):
+ return self.resource.getAutoSchedule()
+
+ def url(self):
+ return self.resource.url()
+
+class FakeRequest(object):
+ pass
+
+def abort(msg, errno=1):
+ print "ERROR:", msg
+ print "Exiting"
+ reactor.stop()
+ sys.exit(errno)
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+def setup():
+
+ setLogLevelForNamespace(None, "warn")
+
+ directory = getDirectory()
+ if config.Memcached["ClientEnabled"]:
+ memcachepool.installPool(
+ IPv4Address(
+ 'TCP',
+ config.Memcached["BindAddress"],
+ config.Memcached["Port"]
+ ),
+ config.Memcached["MaxClients"]
+ )
+ if config.Notifications["Enabled"]:
+ installNotificationClient(
+ config.Notifications["InternalNotificationHost"],
+ config.Notifications["InternalNotificationPort"],
+ )
+ principalCollection = directory.getPrincipalCollection()
+ root = RootResource(
+ config.DocumentRoot,
+ principalCollections=(principalCollection,),
+ )
+ root.putChild("principals", principalCollection)
+ calendarCollection = CalendarHomeProvisioningFile(
+ os.path.join(config.DocumentRoot, "calendars"),
+ directory, "/calendars/",
+ )
+ root.putChild("calendars", calendarCollection)
+
+ return (directory, root)
+
def loadConfig(configFileName):
if configFileName is None:
configFileName = defaultConfigFile
@@ -152,152 +413,10 @@
shortNames = ("dummy",),
fullName = "Dummy McDummerson",
calendarUserAddresses = set(),
- autoSchedule = False,
+ # autoSchedule = False,
)
-def setup():
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- directory = getDirectory()
- if config.Memcached["ClientEnabled"]:
- memcachepool.installPool(
- IPv4Address(
- 'TCP',
- config.Memcached["BindAddress"],
- config.Memcached["Port"]
- ),
- config.Memcached["MaxClients"]
- )
- if config.Notifications["Enabled"]:
- installNotificationClient(
- config.Notifications["InternalNotificationHost"],
- config.Notifications["InternalNotificationPort"],
- )
- principalCollection = directory.getPrincipalCollection()
- root = RootResource(
- config.DocumentRoot,
- principalCollections=(principalCollection,),
- )
- root.putChild("principals", principalCollection)
- calendarCollection = CalendarHomeProvisioningFile(
- os.path.join(config.DocumentRoot, "calendars"),
- directory, "/calendars/",
- )
- root.putChild("calendars", calendarCollection)
-
- return (directory, root)
-
-
-
-class UsageError (StandardError):
- pass
-
-def usage(e=None):
- if e:
- print e
- print ""
-
- name = os.path.basename(sys.argv[0])
- print "usage: %s [options] [input_specifiers]" % (name,)
- print ""
- print "Change calendar user addresses"
- print __doc__
- print "options:"
- print " -h --help: print this help and exit"
- print " -f --config: Specify caldavd.plist configuration path"
- print ""
- print "input specifiers:"
- print " -c --changes: add all calendar homes"
- print " --dry-run: Don't actually change the data"
-
- if e:
- sys.exit(64)
- else:
- sys.exit(0)
-
-def loadChanges(fileName):
- addresses = {}
- with open(fileName) as input:
- count = 1
- for line in input:
- line = line.strip()
- if line and not line.startswith("#"):
- try:
- oldAddr, newAddr = line.split()
- addresses[oldAddr] = newAddr
- except Exception, e:
- print "Could not parse line %d: %s" % (count, line)
- sys.exit(2)
- count += 1
- return addresses
-
-
-
-
-class ResourceWrapper(object):
-
- def __init__(self, resource):
- self.resource = resource
-
- at exportmethod
-def byPath(root, path):
- resource = root
- segments = path.strip("/").split("/")
- for segment in segments:
- resource = resource.getChild(segment)
- return ResourceWrapper(resource)
-
-def main():
- try:
- (optargs, args) = getopt(
- sys.argv[1:], "hf:", [
- "config=",
- "help",
- "dry-run",
- ],
- )
- except GetoptError, e:
- usage(e)
-
- configFileName = None
- logFileName = "/dev/stdout"
- modifyData = True
- changesFile = None
-
- directory = None
- calendarHomePaths = set()
- calendarHomes = set()
-
- def checkExists(resource):
- if not resource.exists():
- sys.stderr.write("No such file: %s\n" % (resource.fp.path,))
- sys.exit(1)
-
- for opt, arg in optargs:
- if opt in ("-h", "--help"):
- usage()
-
- elif opt in ("-f", "--config"):
- configFileName = arg
-
- elif opt in ("--dry-run",):
- modifyData = False
-
- if args:
- usage("Too many arguments: %s" % (" ".join(args),))
-
- observer = log.FileLogObserver(open(logFileName, "a"))
- log.addObserver(observer.emit)
-
- loadConfig(configFileName)
-
- directory, root = setup()
- exportedSymbols['root'] = root
- exportedSymbols['directory'] = directory
-
- banner = "\nWelcome to calendar server\n"
- interact(banner, None, getExports(__name__="__console__", __doc__=None))
-
-
if __name__ == "__main__":
-
main()
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/calendarserver/tools/util.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/calendarserver/tools/util.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/calendarserver/tools/util.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -105,5 +105,5 @@
lastName = "McDummerson",
emailAddresses = (),
calendarUserAddresses = (),
- autoSchedule = False,
+ # autoSchedule = False,
)
Property changes on: CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-privatecomments.txt
___________________________________________________________________
Modified: svn:mergeinfo
- /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-privatecomments-00.txt:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-privatecomments-00.txt:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-privatecomments.txt:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-privatecomments-00.txt:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-privatecomments.txt:3574-3581
+ /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-privatecomments-00.txt:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-privatecomments-00.txt:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-privatecomments.txt:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-privatecomments-00.txt:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-privatecomments.txt:3574-3581
/CalendarServer/branches/users/sagen/resource-delegates-4038/doc/Extensions/caldav-privatecomments.txt:4040-4067
Property changes on: CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-privatecomments.xml
___________________________________________________________________
Modified: svn:mergeinfo
- /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-privatecomments-00.xml:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-privatecomments-00.xml:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-privatecomments.xml:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-privatecomments-00.xml:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-privatecomments.xml:3574-3581
+ /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-privatecomments-00.xml:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-privatecomments-00.xml:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-privatecomments.xml:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-privatecomments-00.xml:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-privatecomments.xml:3574-3581
/CalendarServer/branches/users/sagen/resource-delegates-4038/doc/Extensions/caldav-privatecomments.xml:4040-4067
Property changes on: CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-schedulingchanges.txt
___________________________________________________________________
Modified: svn:mergeinfo
- /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-schedulingchanges-01.txt:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-schedulingchanges-01.txt:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-schedulingchanges.txt:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-schedulingchanges-01.txt:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-schedulingchanges.txt:3574-3581
+ /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-schedulingchanges-01.txt:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-schedulingchanges-01.txt:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-schedulingchanges.txt:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-schedulingchanges-01.txt:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-schedulingchanges.txt:3574-3581
/CalendarServer/branches/users/sagen/resource-delegates-4038/doc/Extensions/caldav-schedulingchanges.txt:4040-4067
Property changes on: CalendarServer/branches/users/sagen/resource-delegates-4066/doc/Extensions/caldav-schedulingchanges.xml
___________________________________________________________________
Modified: svn:mergeinfo
- /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-schedulingchanges-01.xml:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-schedulingchanges-01.xml:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-schedulingchanges.xml:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-schedulingchanges-01.xml:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-schedulingchanges.xml:3574-3581
+ /CalendarServer/branches/users/cdaboo/attendee-comments-2886/doc/Extensions/caldav-schedulingchanges-01.xml:2887-2910
/CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/doc/Extensions/caldav-schedulingchanges-01.xml:2938-3097
/CalendarServer/branches/users/cdaboo/implicit-if-match-3306/doc/Extensions/caldav-schedulingchanges.xml:3307-3349
/CalendarServer/branches/users/cdaboo/implicitauto-2947/doc/Extensions/caldav-schedulingchanges-01.xml:2948-2989
/CalendarServer/branches/users/cdaboo/location-partial-accept-3573/doc/Extensions/caldav-schedulingchanges.xml:3574-3581
/CalendarServer/branches/users/sagen/resource-delegates-4038/doc/Extensions/caldav-schedulingchanges.xml:4040-4067
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/customxml.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/customxml.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -575,9 +575,17 @@
"""
Exposes the type of a record
"""
+ namespace = calendarserver_namespace
name = "record-type"
protected = True
+class AutoSchedule (davxml.WebDAVTextElement):
+ """
+ Whether the principal automatically accepts invitations
+ """
+ namespace = calendarserver_namespace
+ name = "auto-schedule"
+
##
# Extensions to davxml.ResourceType
##
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/appleopendirectory.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/appleopendirectory.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -619,22 +619,6 @@
else:
memberGUIDs = ()
- # Special case for resources and locations
- autoSchedule = False
- proxyGUIDs = ()
- readOnlyProxyGUIDs = ()
- if recordType in (self.recordType_resources, self.recordType_locations):
- resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
- if resourceInfo is not None:
- try:
- autoSchedule, proxy, read_only_proxy = self._parseResourceInfo(resourceInfo, recordGUID, recordType, recordShortName)
- except ValueError:
- continue
- if proxy:
- proxyGUIDs = (proxy,)
- if read_only_proxy:
- readOnlyProxyGUIDs = (read_only_proxy,)
-
record = OpenDirectoryRecord(
service = self,
recordType = recordType,
@@ -647,11 +631,8 @@
lastName = recordLastName,
emailAddresses = recordEmailAddresses,
calendarUserAddresses = calendarUserAddresses,
- autoSchedule = autoSchedule,
enabledForCalendaring = enabledForCalendaring,
memberGUIDs = memberGUIDs,
- proxyGUIDs = proxyGUIDs,
- readOnlyProxyGUIDs = readOnlyProxyGUIDs,
)
def disableGUID(guid, record):
@@ -709,11 +690,6 @@
if recordType == self.recordType_groups:
self._indexGroup(record, record._memberGUIDs, groupsForGUID)
- # Do proxy indexing if needed
- elif recordType in (self.recordType_resources, self.recordType_locations):
- self._indexGroup(record, record._proxyGUIDs, proxiesForGUID)
- self._indexGroup(record, record._readOnlyProxyGUIDs, readOnlyProxiesForGUID)
-
# Index non-duplicate shortNames
def disableName(shortName, record):
self.log_warn("Short name %s disabled due to conflict for record: %s"
@@ -957,8 +933,8 @@
def __init__(
self, service, recordType, guid, nodeName, shortNames, authIDs, fullName,
firstName, lastName, emailAddresses,
- calendarUserAddresses, autoSchedule, enabledForCalendaring,
- memberGUIDs, proxyGUIDs, readOnlyProxyGUIDs,
+ calendarUserAddresses, enabledForCalendaring,
+ memberGUIDs,
):
super(OpenDirectoryRecord, self).__init__(
service = service,
@@ -971,13 +947,10 @@
lastName = lastName,
emailAddresses = emailAddresses,
calendarUserAddresses = calendarUserAddresses,
- autoSchedule = autoSchedule,
enabledForCalendaring = enabledForCalendaring,
)
self.nodeName = nodeName
self._memberGUIDs = tuple(memberGUIDs)
- self._proxyGUIDs = tuple(proxyGUIDs)
- self._readOnlyProxyGUIDs = tuple(readOnlyProxyGUIDs)
def __repr__(self):
if self.service.realmName == self.nodeName:
@@ -1007,48 +980,6 @@
def groups(self):
return self.service.groupsForGUID(self.guid)
- def proxies(self):
- if self.recordType not in (self.service.recordType_resources, self.service.recordType_locations):
- return
-
- for guid in self._proxyGUIDs:
- proxyRecord = self.service.recordWithGUID(guid)
- if proxyRecord is None:
- self.log_error("No record for proxy in (%s)%s with GUID %s" % (
- self.recordType,
- self.shortNames[0],
- guid,
- ))
- else:
- yield proxyRecord
-
- def proxyFor(self):
- result = set()
- result.update(self.service.proxiesForGUID(self.service.recordType_resources, self.guid))
- result.update(self.service.proxiesForGUID(self.service.recordType_locations, self.guid))
- return result
-
- def readOnlyProxies(self):
- if self.recordType not in (self.service.recordType_resources, self.service.recordType_locations):
- return
-
- for guid in self._readOnlyProxyGUIDs:
- proxyRecord = self.service.recordWithGUID(guid)
- if proxyRecord is None:
- self.log_error("No record for proxy in (%s)%s with GUID %s" % (
- self.recordType,
- self.shortNames[0],
- guid,
- ))
- else:
- yield proxyRecord
-
- def readOnlyProxyFor(self):
- result = set()
- result.update(self.service.readOnlyProxiesForGUID(self.service.recordType_resources, self.guid))
- result.update(self.service.readOnlyProxiesForGUID(self.service.recordType_locations, self.guid))
- return result
-
def verifyCredentials(self, credentials):
if isinstance(credentials, UsernamePassword):
# Check cached password
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingappleopendirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingappleopendirectory.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingappleopendirectory.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -477,10 +477,12 @@
elif recordType == DirectoryService.recordType_locations:
listRecordTypes.append(dsattributes.kDSStdRecordTypePlaces)
+ # MOR: possibly can be removed
attrs.append(dsattributes.kDSNAttrResourceInfo)
elif recordType == DirectoryService.recordType_resources:
listRecordTypes.append(dsattributes.kDSStdRecordTypeResources)
+ # MOR: possibly can be removed
attrs.append(dsattributes.kDSNAttrResourceInfo)
else:
@@ -657,22 +659,6 @@
else:
memberGUIDs = ()
- # Special case for resources and locations
- autoSchedule = False
- proxyGUIDs = ()
- readOnlyProxyGUIDs = ()
- if recordType in (self.recordType_resources, self.recordType_locations):
- resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
- if resourceInfo is not None:
- try:
- autoSchedule, proxy, read_only_proxy = self._parseResourceInfo(resourceInfo, recordGUID, recordType, recordShortName)
- except ValueError:
- continue
- if proxy:
- proxyGUIDs = (proxy,)
- if read_only_proxy:
- readOnlyProxyGUIDs = (read_only_proxy,)
-
record = OpenDirectoryRecord(
service = self,
recordType = recordType,
@@ -685,11 +671,8 @@
lastName = recordLastName,
emailAddresses = recordEmailAddresses,
calendarUserAddresses = calendarUserAddresses,
- autoSchedule = autoSchedule,
enabledForCalendaring = enabledForCalendaring,
memberGUIDs = memberGUIDs,
- proxyGUIDs = proxyGUIDs,
- readOnlyProxyGUIDs = readOnlyProxyGUIDs,
)
self.recordCacheForType(recordType).addRecord(record)
@@ -701,8 +684,9 @@
def __init__(
self, service, recordType, guid, nodeName, shortNames, authIDs,
fullName, firstName, lastName, emailAddresses,
- calendarUserAddresses, autoSchedule, enabledForCalendaring,
- memberGUIDs, proxyGUIDs, readOnlyProxyGUIDs,
+ calendarUserAddresses,
+ enabledForCalendaring,
+ memberGUIDs,
):
super(OpenDirectoryRecord, self).__init__(
service = service,
@@ -715,13 +699,10 @@
lastName = lastName,
emailAddresses = emailAddresses,
calendarUserAddresses = calendarUserAddresses,
- autoSchedule = autoSchedule,
enabledForCalendaring = enabledForCalendaring,
)
self.nodeName = nodeName
self._memberGUIDs = tuple(memberGUIDs)
- self._proxyGUIDs = tuple(proxyGUIDs)
- self._readOnlyProxyGUIDs = tuple(readOnlyProxyGUIDs)
self._groupMembershipGUIDs = None
@@ -759,48 +740,6 @@
if record:
yield record
- def proxies(self):
- if self.recordType not in (self.service.recordType_resources, self.service.recordType_locations):
- return
-
- for guid in self._proxyGUIDs:
- proxyRecord = self.service.recordWithGUID(guid)
- if proxyRecord is None:
- self.log_error("No record for proxy in (%s)%s with GUID %s" % (
- self.recordType,
- self.shortNames[0],
- guid,
- ))
- else:
- yield proxyRecord
-
- def proxyFor(self):
- result = set()
- result.update(self.service.proxiesForGUID(self.service.recordType_resources, self.guid))
- result.update(self.service.proxiesForGUID(self.service.recordType_locations, self.guid))
- return result
-
- def readOnlyProxies(self):
- if self.recordType not in (self.service.recordType_resources, self.service.recordType_locations):
- return
-
- for guid in self._readOnlyProxyGUIDs:
- proxyRecord = self.service.recordWithGUID(guid)
- if proxyRecord is None:
- self.log_error("No record for proxy in (%s)%s with GUID %s" % (
- self.recordType,
- self.shortNames[0],
- guid,
- ))
- else:
- yield proxyRecord
-
- def readOnlyProxyFor(self):
- result = set()
- result.update(self.service.readOnlyProxiesForGUID(self.service.recordType_resources, self.guid))
- result.update(self.service.readOnlyProxiesForGUID(self.service.recordType_locations, self.guid))
- return result
-
def verifyCredentials(self, credentials):
if isinstance(credentials, UsernamePassword):
# Check cached password
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingdirectory.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingdirectory.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -319,7 +319,7 @@
def __init__(
self, service, recordType, guid, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- calendarUserAddresses=set(), autoSchedule=False,
+ calendarUserAddresses=set(),
enabledForCalendaring=None, uid=None,
):
super(CachingDirectoryRecord, self).__init__(
@@ -333,7 +333,6 @@
lastName = lastName,
emailAddresses = emailAddresses,
calendarUserAddresses = calendarUserAddresses,
- autoSchedule = autoSchedule,
enabledForCalendaring = enabledForCalendaring,
uid = uid,
)
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingxmlfile.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingxmlfile.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/cachingxmlfile.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -183,17 +183,12 @@
lastName = xmlPrincipal.lastName,
emailAddresses = xmlPrincipal.emailAddresses,
calendarUserAddresses = xmlPrincipal.calendarUserAddresses,
- autoSchedule = xmlPrincipal.autoSchedule,
enabledForCalendaring = xmlPrincipal.enabledForCalendaring,
)
self.password = xmlPrincipal.password
self._members = xmlPrincipal.members
self._groups = xmlPrincipal.groups
- self._proxies = xmlPrincipal.proxies
- self._proxyFor = xmlPrincipal.proxyFor
- self._readOnlyProxies = xmlPrincipal.readOnlyProxies
- self._readOnlyProxyFor = xmlPrincipal.readOnlyProxyFor
def members(self):
for recordType, shortName in self._members:
@@ -203,22 +198,6 @@
for shortName in self._groups:
yield self.service.recordWithShortName(DirectoryService.recordType_groups, shortName)
- def proxies(self):
- for recordType, shortName in self._proxies:
- yield self.service.recordWithShortName(recordType, shortName)
-
- def proxyFor(self, read_write=True):
- for recordType, shortName in self._proxyFor:
- yield self.service.recordWithShortName(recordType, shortName)
-
- def readOnlyProxies(self):
- for recordType, shortName in self._readOnlyProxies:
- yield self.service.recordWithShortName(recordType, shortName)
-
- def readOnlyProxyFor(self, read_write=True):
- for recordType, shortName in self._readOnlyProxyFor:
- yield self.service.recordWithShortName(recordType, shortName)
-
def verifyCredentials(self, credentials):
if isinstance(credentials, UsernamePassword):
return credentials.password == self.password
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/calendaruserproxy.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/calendaruserproxy.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -161,15 +161,7 @@
assert isinstance(property, davxml.WebDAVElement)
if property.qname() == (dav_namespace, "group-member-set"):
- if self.hasEditableMembership():
- return self.setGroupMemberSet(property, request)
- else:
- raise HTTPError(
- StatusResponse(
- responsecode.FORBIDDEN,
- "Proxies cannot be changed."
- )
- )
+ return self.setGroupMemberSet(property, request)
return super(CalendarUserProxyPrincipalResource, self).writeProperty(property, request)
@@ -269,8 +261,7 @@
"""Principal UID: %s\n""" % (self.principalUID(),),
"""Principal URL: %s\n""" % (format_link(self.principalURL()),),
"""\nAlternate URIs:\n""" , format_list(format_link(u) for u in self.alternateURIs()),
- """\nGroup members (%s):\n""" % ({False:"Locked", True:"Editable"}[self.hasEditableMembership()])
- , format_principals(closure["members"]),
+ """\nGroup members:\n""" , format_principals(closure["members"]),
"""\nGroup memberships:\n""" , format_principals(closure["memberships"]),
"""</pre></blockquote></div>""",
closure["output"]
@@ -321,7 +312,8 @@
for member in members:
if member.principalUID() not in uids:
relatives.add(member)
- yield self._expandMemberUIDs(member.principalUID(), relatives, uids, infinity=infinity)
+ if infinity:
+ yield self._expandMemberUIDs(member.principalUID(), relatives, uids, infinity=infinity)
elif isinstance(principal, DirectoryPrincipalResource):
if infinity:
members = yield principal.expandedGroupMembers()
@@ -333,35 +325,28 @@
@inlineCallbacks
def _directGroupMembers(self):
- if self.hasEditableMembership():
- # Get member UIDs from database and map to principal resources
- members = yield self._index().getMembers(self.uid)
- found = []
- missing = []
- for uid in members:
- p = self.pcollection.principalForUID(uid)
- if p:
- found.append(p)
- # Make sure any outstanding deletion timer entries for
- # existing principals are removed
- yield self._index()._memcacher.clearDeletionTimer(uid)
- else:
- missing.append(uid)
+ # Get member UIDs from database and map to principal resources
+ members = yield self._index().getMembers(self.uid)
+ found = []
+ missing = []
+ for uid in members:
+ p = self.pcollection.principalForUID(uid)
+ if p:
+ found.append(p)
+ # Make sure any outstanding deletion timer entries for
+ # existing principals are removed
+ yield self._index()._memcacher.clearDeletionTimer(uid)
+ else:
+ missing.append(uid)
- # Clean-up ones that are missing
- for uid in missing:
- cacheTimeout = config.DirectoryService.params.get("cacheTimeout", 30) * 60 # in seconds
+ # Clean-up ones that are missing
+ for uid in missing:
+ cacheTimeout = config.DirectoryService.params.get("cacheTimeout", 30) * 60 # in seconds
- yield self._index().removePrincipal(uid,
- delay=cacheTimeout*2)
+ yield self._index().removePrincipal(uid,
+ delay=cacheTimeout*2)
- returnValue(found)
- else:
- # Fixed proxies
- if self.proxyType == "calendar-proxy-write":
- returnValue(self.parent.proxies())
- else:
- returnValue(self.parent.readOnlyProxies())
+ returnValue(found)
def groupMembers(self):
return self._expandMemberUIDs()
@@ -375,9 +360,6 @@
memberships = yield self._index().getMemberships(self.uid)
returnValue([p for p in [self.pcollection.principalForUID(uid) for uid in memberships] if p])
- def hasEditableMembership(self):
- return self.parent.hasEditableProxyMembership()
-
class CalendarUserProxyDatabase(AbstractSQLDatabase, LoggingMixIn):
"""
A database to maintain calendar user proxy group memberships.
@@ -481,11 +463,8 @@
current_members = ()
current_members = set(current_members)
- # Remove what is there, then add it back.
- self._delete_from_db(principalUID)
- self._add_to_db(principalUID, members)
- self._db_commit()
-
+ self.setGroupMembersInDatabase(principalUID, members)
+
# Update cache
update_members = set(members)
@@ -495,6 +474,18 @@
_ignore = yield self._memcacher.deleteMembership(member)
_ignore = yield self._memcacher.deleteMember(principalUID)
+ def setGroupMembersInDatabase(self, principalUID, members):
+ """
+ A blocking call to add a group membership record in the database.
+
+ @param principalUID: the UID of the group principal to add.
+ @param members: a list UIDs of principals that are members of this group.
+ """
+ # Remove what is there, then add it back.
+ self._delete_from_db(principalUID)
+ self._add_to_db(principalUID, members)
+ self._db_commit()
+
@inlineCallbacks
def removeGroup(self, principalUID):
"""
@@ -550,7 +541,7 @@
for suffix in ("calendar-proxy-read", "calendar-proxy-write",):
groupUID = "%s#%s" % (principalUID, suffix,)
self._delete_from_db(groupUID)
-
+
# Update cache
members = yield self.getMembers(groupUID)
if members:
@@ -561,7 +552,7 @@
memberships = (yield self.getMemberships(principalUID))
for groupUID in memberships:
yield self._memcacher.deleteMember(groupUID)
-
+
self._delete_from_db_member(principalUID)
yield self._memcacher.deleteMembership(principalUID)
self._db_commit()
@@ -571,7 +562,7 @@
def getMembers(self, principalUID):
"""
Return the list of group member UIDs for the specified principal.
-
+
@return: a deferred returning a C{set} of members.
"""
@@ -695,6 +686,8 @@
"""
)
+
+
##
# Utilities
##
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/directory.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/directory.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -269,7 +269,8 @@
def __init__(
self, service, recordType, guid, shortNames=(), authIDs=set(), fullName=None,
firstName=None, lastName=None, emailAddresses=set(),
- calendarUserAddresses=set(), autoSchedule=False, enabledForCalendaring=None,
+ calendarUserAddresses=set(),
+ enabledForCalendaring=None,
uid=None,
):
assert service.realmName is not None
@@ -309,7 +310,6 @@
self.emailAddresses = emailAddresses
self.enabledForCalendaring = enabledForCalendaring
self.calendarUserAddresses = calendarUserAddresses
- self.autoSchedule = autoSchedule
def __cmp__(self, other):
if not isinstance(other, DirectoryRecord):
@@ -335,20 +335,8 @@
def groups(self):
return ()
- def proxies(self):
- return ()
-
- def proxyFor(self):
- return ()
-
- def readOnlyProxies(self):
- return ()
-
- def readOnlyProxyFor(self):
- return ()
-
def hasEditableProxyMembership(self):
- return self.recordType in (DirectoryService.recordType_users, DirectoryService.recordType_groups)
+ return True
def verifyCredentials(self, credentials):
return False
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/idirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/idirectory.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/idirectory.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -101,7 +101,6 @@
lastName = Attribute("The last name of this record.")
emailAddress = Attribute("The email address of this record.")
calendarUserAddresses = Attribute("A set of calendar user addresses for this record.")
- autoSchedule = Attribute("Principal identified by this record should automatically accept/deny meetings.")
enabledForCalendaring = Attribute("Determines whether this record should be provisioned with a calendar home.")
def members():
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/principal.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/principal.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -582,11 +582,10 @@
members = (yield self.groupMembers())
memberships = (yield self.groupMemberships())
-
+
proxyFor = (yield self.proxyFor(True))
-
readOnlyProxyFor = (yield self.proxyFor(False))
-
+
returnValue("".join((
"""<div class="directory-listing">"""
"""<h1>Principal Details</h1>"""
@@ -662,6 +661,32 @@
def url(self):
return self.principalURL()
+ @inlineCallbacks
+ def proxyFor(self, read_write, resolve_memberships=True):
+ proxyFors = set()
+
+ if resolve_memberships:
+ memberships = self._getRelatives("groups", infinity=True)
+ for membership in memberships:
+ results = (yield membership.proxyFor(read_write, False))
+ proxyFors.update(results)
+
+ if config.EnableProxyPrincipals:
+ # Get proxy group UIDs and map to principal resources
+ proxies = []
+ memberships = (yield self._calendar_user_proxy_index().getMemberships(self.principalUID()))
+ for uid in memberships:
+ subprincipal = self.parent.principalForUID(uid)
+ if subprincipal:
+ if subprincipal.isProxyType(read_write):
+ proxies.append(subprincipal.parent)
+ else:
+ yield self._calendar_user_proxy_index().removeGroup(uid)
+
+ proxyFors.update(proxies)
+
+ returnValue(proxyFors)
+
def _getRelatives(self, method, record=None, relatives=None, records=None, proxy=None, infinity=False):
if record is None:
record = self.record
@@ -703,8 +728,9 @@
if config.EnableProxyPrincipals:
# Get any directory specified proxies
- groups.update(self._getRelatives("proxyFor", proxy='read-write', infinity=infinity))
- groups.update(self._getRelatives("readOnlyProxyFor", proxy='read-only', infinity=infinity))
+ # MOR:
+ # groups.update(self._getRelatives("proxyFor", proxy='read-write', infinity=infinity))
+ # groups.update(self._getRelatives("readOnlyProxyFor", proxy='read-only', infinity=infinity))
# Get proxy group UIDs and map to principal resources
proxies = []
@@ -723,40 +749,6 @@
def expandedGroupMemberships(self):
return self.groupMemberships(infinity=True)
-
- @inlineCallbacks
- def proxyFor(self, read_write, resolve_memberships=True):
- proxyFors = set()
-
- if resolve_memberships:
- memberships = self._getRelatives("groups", infinity=True)
- for membership in memberships:
- results = (yield membership.proxyFor(read_write, False))
- proxyFors.update(results)
-
- if config.EnableProxyPrincipals:
- # Get any directory specified proxies
- if read_write:
- directoryProxies = self._getRelatives("proxyFor", proxy='read-write', infinity=True)
- else:
- directoryProxies = self._getRelatives("readOnlyProxyFor", proxy='read-only', infinity=True)
- proxyFors.update([subprincipal.parent for subprincipal in directoryProxies])
-
- # Get proxy group UIDs and map to principal resources
- proxies = []
- memberships = (yield self._calendar_user_proxy_index().getMemberships(self.principalUID()))
- for uid in memberships:
- subprincipal = self.parent.principalForUID(uid)
- if subprincipal:
- if subprincipal.isProxyType(read_write):
- proxies.append(subprincipal.parent)
- else:
- yield self._calendar_user_proxy_index().removeGroup(uid)
-
- proxyFors.update(proxies)
-
- returnValue(proxyFors)
-
def principalCollections(self):
return self.parent.principalCollections()
@@ -837,9 +829,6 @@
return addresses
- def autoSchedule(self):
- return self.record.autoSchedule
-
def enabledAsOrganizer(self):
if self.record.recordType == DirectoryService.recordType_users:
return True
@@ -852,15 +841,6 @@
else:
return False
- def proxies(self):
- return self._getRelatives("proxies", infinity=True)
-
- def readOnlyProxies(self):
- return self._getRelatives("readOnlyProxies", infinity=True)
-
- def hasEditableProxyMembership(self):
- return self.record.hasEditableProxyMembership()
-
def scheduleInbox(self, request):
home = self.calendarHome()
if home is None:
@@ -907,6 +887,7 @@
else:
return None
+
##
# Static
##
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/sqldb.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/sqldb.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/sqldb.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -101,10 +101,7 @@
# Get calendar user addresses
calendarUserAddresses = self.calendarUserAddresses(shortName)
- # TODO: need this for Resources and Locations
- autoSchedule = False
-
- yield shortName, guid, password, name, members, groups, calendarUserAddresses, autoSchedule
+ yield shortName, guid, password, name, members, groups, calendarUserAddresses
def getRecord(self, recordType, shortName):
# Get individual account record
@@ -129,11 +126,8 @@
# Get calendar user addresses
calendarUserAddresses = self.calendarUserAddresses(shortName)
- # TODO: need this for Resources and Locations
- autoSchedule = False
+ return shortName, guid, password, name, members, groups, calendarUserAddresses
- return shortName, guid, password, name, members, groups, calendarUserAddresses, autoSchedule
-
def members(self, shortName):
members = set()
for member in self._db_execute(
@@ -318,7 +312,6 @@
members = result[4],
groups = result[5],
calendarUserAddresses = result[6],
- autoSchedule = result[7],
)
def recordWithShortName(self, recordType, shortName):
@@ -334,7 +327,6 @@
members = result[4],
groups = result[5],
calendarUserAddresses = result[6],
- autoSchedule = result[7],
)
return None
@@ -343,7 +335,7 @@
"""
XML based implementation implementation of L{IDirectoryRecord}.
"""
- def __init__(self, service, recordType, shortName, guid, password, name, members, groups, calendarUserAddresses, autoSchedule):
+ def __init__(self, service, recordType, shortName, guid, password, name, members, groups, calendarUserAddresses):
super(SQLDirectoryRecord, self).__init__(
service = service,
recordType = recordType,
@@ -351,7 +343,6 @@
shortNames = (shortName,),
fullName = name,
calendarUserAddresses = calendarUserAddresses,
- autoSchedule = autoSchedule,
)
self.password = password
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/accounts.xml
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/accounts.xml 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/accounts.xml 2009-04-23 23:47:07 UTC (rev 4072)
@@ -67,6 +67,7 @@
</user>
<user repeat="2">
<uid>user%02d</uid>
+ <guid>user%02d</guid>
<password>%02duser</password>
<name>User %02d</name>
</user>
@@ -81,6 +82,7 @@
</group>
<group>
<uid>admin</uid>
+ <guid>admin</guid>
<password>admin</password>
<name>Administrators</name>
<members>
@@ -89,6 +91,7 @@
</group>
<group>
<uid>grunts</uid>
+ <guid>grunts</guid>
<password>grunts</password>
<name>We do all the work</name>
<members>
@@ -99,6 +102,7 @@
</group>
<group>
<uid>right_coast</uid>
+ <guid>right_coast</guid>
<password>right_coast</password>
<name>East Coast</name>
<members>
@@ -107,6 +111,7 @@
</group>
<group>
<uid>left_coast</uid>
+ <guid>left_coast</guid>
<password>left_coast</password>
<name>West Coast</name>
<members>
@@ -117,6 +122,7 @@
</group>
<group>
<uid>both_coasts</uid>
+ <guid>both_coasts</guid>
<password>both_coasts</password>
<name>Both Coasts</name>
<members>
@@ -126,6 +132,7 @@
</group>
<group>
<uid>recursive1_coasts</uid>
+ <guid>recursive1_coasts</guid>
<password>recursive1_coasts</password>
<name>Recursive1 Coasts</name>
<members>
@@ -135,6 +142,7 @@
</group>
<group>
<uid>recursive2_coasts</uid>
+ <guid>recursive2_coasts</guid>
<password>recursive2_coasts</password>
<name>Recursive2 Coasts</name>
<members>
@@ -144,6 +152,7 @@
</group>
<group>
<uid>non_calendar_group</uid>
+ <guid>non_calendar_group</guid>
<password>non_calendar_group</password>
<name>Non-calendar group</name>
<members>
@@ -154,6 +163,7 @@
</group>
<location>
<uid>mercury</uid>
+ <guid>mercury</guid>
<password>mercury</password>
<name>Mecury Seven</name>
<email-address>mercury at example.com</email-address>
@@ -164,6 +174,7 @@
</location>
<location>
<uid>gemini</uid>
+ <guid>gemini</guid>
<password>gemini</password>
<name>Gemini Twelve</name>
<email-address>gemini at example.com</email-address>
@@ -175,6 +186,7 @@
</location>
<location>
<uid>apollo</uid>
+ <guid>apollo</guid>
<password>apollo</password>
<name>Apollo Eleven</name>
<email-address>apollo at example.com</email-address>
@@ -185,6 +197,7 @@
</location>
<location>
<uid>orion</uid>
+ <guid>orion</guid>
<password>orion</password>
<name>Orion</name>
<email-address>orion at example.com</email-address>
@@ -195,6 +208,7 @@
</location>
<resource>
<uid>transporter</uid>
+ <guid>transporter</guid>
<password>transporter</password>
<name>Mass Transporter</name>
<email-address>transporter at example.com</email-address>
@@ -202,6 +216,7 @@
</resource>
<resource>
<uid>ftlcpu</uid>
+ <guid>ftlcpu</guid>
<password>ftlcpu</password>
<name>Faster-Than-Light Microprocessor</name>
<email-address>ftlcpu at example.com</email-address>
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_cachedirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_cachedirectory.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_cachedirectory.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -61,7 +61,6 @@
lastName = "",
emailAddresses = record.get("email"),
calendarUserAddresses = record.get("email"),
- autoSchedule = False,
enabledForCalendaring = True,
)
self.recordCacheForType(recordType).addRecord(cacheRecord)
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectory.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectory.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -72,11 +72,8 @@
lastName = "User",
emailAddresses = set(("someuser at example.com",)),
calendarUserAddresses = set(("mailtoguid at example.com",)),
- autoSchedule = False,
enabledForCalendaring = True,
memberGUIDs = [],
- proxyGUIDs = (),
- readOnlyProxyGUIDs = (),
)
digestFields = {}
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectoryrecords.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectoryrecords.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_opendirectoryrecords.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -692,58 +692,8 @@
self.verifyQuery(self.service.recordWithEmailAddress, "location05 at example.com")
self.verifyNoQuery(self.service.recordWithEmailAddress, "location05 at example.com")
- def test_resourceinfo(self):
- good_plist = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <dict>
- <key>AutoAcceptsInvitation</key>
- <true/>
- <key>Label</key>
- <string>Location</string>
- <key>CalendaringDelegate</key>
- <string></string>
- <key>ReadOnlyCalendaringDelegate</key>
- <string></string>
- </dict>
-</dict>
-</plist>
-"""
- bad_plist = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <string>bogus</string>
-</dict>
-</plist>
-"""
- invalid_xml = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <string>R&D</string>
-</dict>
-</plist>
-"""
-
- self.loadRecords({
- DirectoryService.recordType_locations: [
- fakeODRecord("Location 01", resourceInfo=good_plist),
- fakeODRecord("Location 02", resourceInfo=bad_plist),
- fakeODRecord("Location 03", resourceInfo=invalid_xml),
- ],
- })
-
- self.verifyRecords(DirectoryService.recordType_locations, ("location01",))
- self.verifyDisabledRecords(DirectoryService.recordType_locations, (), ())
-
-
def fakeODRecord(fullName, shortName=None, guid=None, email=None, members=None, resourceInfo=None):
if shortName is None:
shortName = shortNameForFullName(fullName)
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_principal.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_principal.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -39,11 +39,6 @@
import twistedcaldav.test.util
-directoryServices = (
- BasicDirectoryService(digestRealm, basicUserFile, groupFile),
- DigestDirectoryService(digestRealm, digestUserFile, groupFile),
- XMLDirectoryService(xmlFile),
-)
class ProvisionedPrincipals (twistedcaldav.test.util.TestCase):
"""
@@ -52,9 +47,15 @@
def setUp(self):
super(ProvisionedPrincipals, self).setUp()
+ self.directoryServices = (
+ BasicDirectoryService(digestRealm, basicUserFile, groupFile),
+ DigestDirectoryService(digestRealm, digestUserFile, groupFile),
+ XMLDirectoryService(xmlFile),
+ )
+
# Set up a principals hierarchy for each service we're testing with
self.principalRootResources = {}
- for directory in directoryServices:
+ for directory in self.directoryServices:
name = directory.__class__.__name__
url = "/" + name + "/"
@@ -78,7 +79,7 @@
DirectoryPrincipalResource.principalURL(),
"""
- for directory in directoryServices:
+ for directory in self.directoryServices:
#print "\n -> %s" % (directory.__class__.__name__,)
provisioningResource = self.principalRootResources[directory.__class__.__name__]
@@ -140,7 +141,7 @@
"""
DirectoryPrincipalProvisioningResource.principalForUser()
"""
- for directory in directoryServices:
+ for directory in self.directoryServices:
provisioningResource = self.principalRootResources[directory.__class__.__name__]
for user in directory.listRecords(DirectoryService.recordType_users):
@@ -152,7 +153,7 @@
"""
DirectoryPrincipalProvisioningResource.principalForAuthID()
"""
- for directory in directoryServices:
+ for directory in self.directoryServices:
provisioningResource = self.principalRootResources[directory.__class__.__name__]
for user in directory.listRecords(DirectoryService.recordType_users):
@@ -204,20 +205,6 @@
self.failIf(provisioningResource.principalForCalendarUserAddress("/principals/users/nocalendar/") is not None)
self.failIf(provisioningResource.principalForCalendarUserAddress("/principals/__uids__/543D28BA-F74F-4D5F-9243-B3E3A61171E5/") is not None)
- def test_autoSchedule(self):
- """
- DirectoryPrincipalProvisioningResource.principalForCalendarUserAddress()
- """
- for provisioningResource, recordType, recordResource, record in self._allRecords():
- principal = provisioningResource.principalForRecord(record)
- self.failIf(principal is None)
- if record.enabledForCalendaring:
- self.assertEquals(record.autoSchedule, principal.autoSchedule())
- if record.shortNames[0] == "gemini":
- self.assertTrue(principal.autoSchedule())
- else:
- self.assertFalse(principal.autoSchedule())
-
def test_enabledForCalendaring(self):
"""
DirectoryPrincipalProvisioningResource.principalForCalendarUserAddress()
@@ -302,24 +289,6 @@
memberships = yield recordResource.groupMemberships()
self.failUnless(set(record.groups()).issubset(set(r.record for r in memberships if hasattr(r, "record"))))
- def test_proxies(self):
- """
- DirectoryPrincipalResource.proxies()
- """
- for provisioningResource, recordType, recordResource, record in self._allRecords():
- if record.enabledForCalendaring:
- self.failUnless(set(record.proxies()).issubset(set(r.record for r in recordResource.proxies())))
- self.assertEqual(record.hasEditableProxyMembership(), recordResource.hasEditableProxyMembership())
-
- def test_read_only_proxies(self):
- """
- DirectoryPrincipalResource.proxies()
- """
- for provisioningResource, recordType, recordResource, record in self._allRecords():
- if record.enabledForCalendaring:
- self.failUnless(set(record.readOnlyProxies()).issubset(set(r.record for r in recordResource.readOnlyProxies())))
- self.assertEqual(record.hasEditableProxyMembership(), recordResource.hasEditableProxyMembership())
-
def test_principalUID(self):
"""
DirectoryPrincipalResource.principalUID()
@@ -356,7 +325,7 @@
# Need to create a calendar home provisioner for each service.
calendarRootResources = {}
- for directory in directoryServices:
+ for directory in self.directoryServices:
url = "/homes_" + directory.__class__.__name__ + "/"
path = os.path.join(self.docroot, url[1:])
@@ -412,7 +381,7 @@
"""
Default access controls for principal provisioning resources.
"""
- for directory in directoryServices:
+ for directory in self.directoryServices:
#print "\n -> %s" % (directory.__class__.__name__,)
provisioningResource = self.principalRootResources[directory.__class__.__name__]
@@ -472,7 +441,7 @@
C{record} is the directory service record
for each record in each directory in C{directoryServices}.
"""
- for directory in directoryServices:
+ for directory in self.directoryServices:
provisioningResource = self.principalRootResources[directory.__class__.__name__]
for recordType in directory.recordTypes():
for record in directory.listRecords(recordType):
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_proxyprincipalmembers.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_proxyprincipalmembers.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_proxyprincipalmembers.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -28,7 +28,6 @@
import twistedcaldav.test.util
from twistedcaldav.config import config
-directoryService = XMLDirectoryService(xmlFile)
class ProxyPrincipals (twistedcaldav.test.util.TestCase):
"""
@@ -37,19 +36,21 @@
def setUp(self):
super(ProxyPrincipals, self).setUp()
+ self.directoryService = XMLDirectoryService(xmlFile)
+
# Set up a principals hierarchy for each service we're testing with
self.principalRootResources = {}
- name = directoryService.__class__.__name__
+ name = self.directoryService.__class__.__name__
url = "/" + name + "/"
- provisioningResource = DirectoryPrincipalProvisioningResource(url, directoryService)
+ provisioningResource = DirectoryPrincipalProvisioningResource(url, self.directoryService)
self.site.resource.putChild(name, provisioningResource)
- self.principalRootResources[directoryService.__class__.__name__] = provisioningResource
+ self.principalRootResources[self.directoryService.__class__.__name__] = provisioningResource
def _getPrincipalByShortName(self, type, name):
- provisioningResource = self.principalRootResources[directoryService.__class__.__name__]
+ provisioningResource = self.principalRootResources[self.directoryService.__class__.__name__]
return provisioningResource.principalForShortName(type, name)
def _groupMembersTest(self, recordType, recordName, subPrincipalName, expectedMembers):
@@ -252,7 +253,7 @@
return self.members
- user = self._getPrincipalByShortName(directoryService.recordType_users,
+ user = self._getPrincipalByShortName(self.directoryService.recordType_users,
"cdaboo")
proxyGroup = user.getChild("calendar-proxy-write")
@@ -281,7 +282,7 @@
def changed(self):
self.changedCount += 1
- user = self._getPrincipalByShortName(directoryService.recordType_users, "cdaboo")
+ user = self._getPrincipalByShortName(self.directoryService.recordType_users, "cdaboo")
proxyGroup = user.getChild("calendar-proxy-write")
@@ -376,7 +377,7 @@
db._memcacher.theTime = theTime
- for doMembershipFirst in (True, False,):
+ for doMembershipFirst in (True, False):
for proxyType in ("calendar-proxy-read", "calendar-proxy-write"):
principal = self._getPrincipalByShortName(DirectoryService.recordType_users, "wsanchez")
@@ -419,7 +420,7 @@
self.assertEquals(len(members), 2)
# Remove the dreid user from the directory service
- del directoryService._accounts()[DirectoryService.recordType_users]["dreid"]
+ del self.directoryService._accounts()[DirectoryService.recordType_users]["dreid"]
@inlineCallbacks
def _membershipTest():
@@ -451,8 +452,8 @@
self.assertEquals(len(members), 2)
# Restore removed user
- parser = XMLAccountsParser(directoryService.xmlFile)
- directoryService._parsedAccounts = parser.items
+ parser = XMLAccountsParser(self.directoryService.xmlFile)
+ self.directoryService._parsedAccounts = parser.items
# Trigger the proxy DB clean up, which will actually
# remove the deletion timer because the principal has been
@@ -464,7 +465,7 @@
self.assertEquals(result, None)
# Remove the dreid user from the directory service
- del directoryService._accounts()[DirectoryService.recordType_users]["dreid"]
+ del self.directoryService._accounts()[DirectoryService.recordType_users]["dreid"]
# Trigger the proxy DB clean up, which won't actually
# remove anything because we haven't exceeded the timeout
@@ -493,8 +494,8 @@
yield _membershipTest()
# Restore removed user
- parser = XMLAccountsParser(directoryService.xmlFile)
- directoryService._parsedAccounts = parser.items
+ parser = XMLAccountsParser(self.directoryService.xmlFile)
+ self.directoryService._parsedAccounts = parser.items
self._clearProxy(principal, proxyType)
self._clearProxy(fakePrincipal, proxyType)
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_xmlfile.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/test/test_xmlfile.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -17,10 +17,14 @@
import os
from twisted.python.filepath import FilePath
+from twisted.internet.defer import inlineCallbacks
+from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
from twistedcaldav.directory.directory import DirectoryService
import twistedcaldav.directory.test.util
from twistedcaldav.directory.xmlfile import XMLDirectoryService
+from twistedcaldav.resource import ResourceInfoDatabase
+from twistedcaldav.config import config
xmlFile = FilePath(os.path.join(os.path.dirname(__file__), "accounts.xml"))
@@ -104,6 +108,7 @@
<accounts realm="Test Realm">
<user>
<uid>admin</uid>
+ <guid>admin</guid>
<password>nimda</password>
<name>Super User</name>
</user>
@@ -121,6 +126,7 @@
set(expectedRecords)
)
+ @inlineCallbacks
def test_okAutoSchedule(self):
service = self.service()
@@ -130,6 +136,7 @@
<accounts realm="Test Realm">
<location>
<uid>my office</uid>
+ <guid>myoffice</guid>
<password>nimda</password>
<name>Super User</name>
<auto-schedule/>
@@ -147,30 +154,10 @@
set(r.shortNames[0] for r in service.listRecords(recordType)),
set(expectedRecords)
)
- self.assertTrue(service.recordWithShortName(DirectoryService.recordType_locations, "my office").autoSchedule)
+ resourceInfoDatabase = ResourceInfoDatabase(config.DataRoot)
+ self.assertTrue((yield resourceInfoDatabase.getAutoSchedule(service.recordWithShortName(DirectoryService.recordType_locations, "my office").guid)))
- def test_badAutoSchedule(self):
- service = self.service()
- self.xmlFile().open("w").write(
-"""<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE accounts SYSTEM "accounts.dtd">
-<accounts realm="Test Realm">
- <user>
- <uid>my office</uid>
- <password>nimda</password>
- <name>Super User</name>
- <auto-schedule/>
- </user>
-</accounts>
-"""
- )
-
- def _findRecords():
- set(r.shortNames[0] for r in service.listRecords(DirectoryService.recordType_users))
-
- self.assertRaises(ValueError, _findRecords)
-
def test_okDisableCalendar(self):
service = self.service()
@@ -207,6 +194,7 @@
self.assertFalse(service.recordWithShortName(DirectoryService.recordType_groups, "enabled").enabledForCalendaring)
self.assertFalse(service.recordWithShortName(DirectoryService.recordType_groups, "disabled").enabledForCalendaring)
+ @inlineCallbacks
def test_okProxies(self):
service = self.service()
@@ -216,11 +204,13 @@
<accounts realm="Test Realm">
<user>
<uid>test</uid>
+ <guid>test</guid>
<password>nimda</password>
<name>Test</name>
</user>
<location>
<uid>my office</uid>
+ <guid>myoffice</guid>
<password>nimda</password>
<name>Super User</name>
<auto-schedule/>
@@ -241,29 +231,9 @@
set(r.shortNames[0] for r in service.listRecords(recordType)),
set(expectedRecords)
)
- self.assertEqual(set([("users", "test",)],), service.recordWithShortName(DirectoryService.recordType_locations, "my office")._proxies)
- self.assertEqual(set([("locations", "my office",)],), service.recordWithShortName(DirectoryService.recordType_users, "test")._proxyFor)
+ calendarUserProxyDatabase = CalendarUserProxyDatabase(config.DataRoot)
+ members = (yield calendarUserProxyDatabase.getMembers("myoffice#calendar-proxy-write"))
+ self.assertTrue("test" in members)
+ members = (yield calendarUserProxyDatabase.getMemberships("test"))
+ self.assertTrue("myoffice#calendar-proxy-write" in members)
- def test_badProxies(self):
- service = self.service()
-
- self.xmlFile().open("w").write(
-"""<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE accounts SYSTEM "accounts.dtd">
-<accounts realm="Test Realm">
- <user>
- <uid>my office</uid>
- <password>nimda</password>
- <name>Super User</name>
- <proxies>
- <member>12345-GUID-67890</member>
- </proxies>
- </user>
-</accounts>
-"""
- )
-
- def _findRecords():
- set(r.shortNames[0] for r in service.listRecords(DirectoryService.recordType_users))
-
- self.assertRaises(ValueError, _findRecords)
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlaccountsparser.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlaccountsparser.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -28,8 +28,11 @@
from twisted.python.filepath import FilePath
+from twistedcaldav.config import config
from twistedcaldav.directory.directory import DirectoryService
from twistedcaldav.log import Logger
+from twistedcaldav.resource import ResourceInfoDatabase
+from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
log = Logger()
@@ -73,6 +76,7 @@
return "<%s %r>" % (self.__class__.__name__, self.xmlFile)
def __init__(self, xmlFile):
+
if type(xmlFile) is str:
xmlFile = FilePath(xmlFile)
@@ -94,7 +98,43 @@
self.log("Ignoring file %r because it is not a repository builder file" % (self.xmlFile,))
return
self._parseXML(accounts_node)
-
+ self._updateExternalDatabases()
+
+ def _updateExternalDatabases(self):
+ resourceInfoDatabase = ResourceInfoDatabase(config.DataRoot)
+
+ calendarUserProxyDatabase = CalendarUserProxyDatabase(config.DataRoot)
+
+ for records in self.items.itervalues():
+ for principal in records.itervalues():
+
+ resourceInfoDatabase.setAutoScheduleInDatabase(principal.guid,
+ principal.autoSchedule)
+
+ if principal.proxies:
+ proxies = []
+ for recordType, uid in principal.proxies:
+ record = self.items[recordType].get(uid)
+ if record is not None:
+ proxies.append(record.guid)
+
+ calendarUserProxyDatabase.setGroupMembersInDatabase(
+ "%s#calendar-proxy-write" % (principal.guid,),
+ proxies
+ )
+
+ if principal.readOnlyProxies:
+ readOnlyProxies = []
+ for recordType, uid in principal.readOnlyProxies:
+ record = self.items[recordType].get(uid)
+ if record is not None:
+ readOnlyProxies.append(record.guid)
+
+ calendarUserProxyDatabase.setGroupMembersInDatabase(
+ "%s#calendar-proxy-read" % (principal.guid,),
+ readOnlyProxies
+ )
+
def _parseXML(self, node):
"""
Parse the XML root node from the accounts configuration document.
@@ -280,9 +320,6 @@
if child.firstChild is not None:
self.calendarUserAddresses.add(child.firstChild.data.encode("utf-8"))
elif child_name == ELEMENT_AUTOSCHEDULE:
- # Only Resources & Locations
- if self.recordType not in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
- raise ValueError("<auto-schedule> element only allowed for Resources and Locations: %s" % (child_name,))
self.autoSchedule = True
elif child_name == ELEMENT_DISABLECALENDAR:
# FIXME: Not sure I see why this restriction is needed. --wsanchez
@@ -291,14 +328,8 @@
# raise ValueError("<disable-calendar> element only allowed for Users: %s" % (child_name,))
self.enabledForCalendaring = False
elif child_name == ELEMENT_PROXIES:
- # Only Resources & Locations
- if self.recordType not in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
- raise ValueError("<proxies> element only allowed for Resources and Locations: %s" % (child_name,))
self._parseMembers(child, self.proxies)
elif child_name == ELEMENT_READ_ONLY_PROXIES:
- # Only Resources & Locations
- if self.recordType not in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
- raise ValueError("<read-only-proxies> element only allowed for Resources and Locations: %s" % (child_name,))
self._parseMembers(child, self.readOnlyProxies)
else:
raise RuntimeError("Unknown account attribute: %s" % (child_name,))
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlfile.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/directory/xmlfile.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -104,6 +104,7 @@
self._fileInfo = fileInfo
return self._parsedAccounts
+
class XMLDirectoryRecord(DirectoryRecord):
"""
XML based implementation implementation of L{IDirectoryRecord}.
@@ -119,17 +120,12 @@
lastName = xmlPrincipal.lastName,
emailAddresses = xmlPrincipal.emailAddresses,
calendarUserAddresses = xmlPrincipal.calendarUserAddresses,
- autoSchedule = xmlPrincipal.autoSchedule,
enabledForCalendaring = xmlPrincipal.enabledForCalendaring,
)
self.password = xmlPrincipal.password
self._members = xmlPrincipal.members
self._groups = xmlPrincipal.groups
- self._proxies = xmlPrincipal.proxies
- self._proxyFor = xmlPrincipal.proxyFor
- self._readOnlyProxies = xmlPrincipal.readOnlyProxies
- self._readOnlyProxyFor = xmlPrincipal.readOnlyProxyFor
def members(self):
for recordType, shortName in self._members:
@@ -139,22 +135,6 @@
for shortName in self._groups:
yield self.service.recordWithShortName(DirectoryService.recordType_groups, shortName)
- def proxies(self):
- for recordType, shortName in self._proxies:
- yield self.service.recordWithShortName(recordType, shortName)
-
- def proxyFor(self, read_write=True):
- for recordType, shortName in self._proxyFor:
- yield self.service.recordWithShortName(recordType, shortName)
-
- def readOnlyProxies(self):
- for recordType, shortName in self._readOnlyProxies:
- yield self.service.recordWithShortName(recordType, shortName)
-
- def readOnlyProxyFor(self, read_write=True):
- for recordType, shortName in self._readOnlyProxyFor:
- yield self.service.recordWithShortName(recordType, shortName)
-
def verifyCredentials(self, credentials):
if isinstance(credentials, UsernamePassword):
return credentials.password == self.password
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/memcachepool.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/memcachepool.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/memcachepool.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -67,6 +67,11 @@
"""
Notify the connectionPool that we've lost our connection.
"""
+
+ if self.connectionPool.shutdown_requested:
+ # The reactor is stopping; don't reconnect
+ return
+
self.log_error("MemCache connection lost: %s" % (reason,))
if self._protocolInstance is not None:
self.connectionPool.clientBusy(self._protocolInstance)
@@ -90,7 +95,6 @@
connector,
reason)
-
def buildProtocol(self, addr):
"""
Attach the C{self.connectionPool} to the protocol so it can tell it,
@@ -138,15 +142,31 @@
if reactor is None:
from twisted.internet import reactor
-
self._reactor = reactor
+ self.shutdown_deferred = None
+ self.shutdown_requested = False
+ reactor.addSystemEventTrigger('before', 'shutdown', self._shutdownCallback)
+
self._busyClients = set([])
self._freeClients = set([])
self._pendingConnects = 0
self._commands = []
+ def _isIdle(self):
+ return (
+ len(self._busyClients) == 0 and
+ len(self._commands) == 0 and
+ self._pendingConnects == 0
+ )
+ def _shutdownCallback(self):
+ self.shutdown_requested = True
+ if self._isIdle():
+ return None
+ self.shutdown_deferred = Deferred()
+ return self.shutdown_deferred
+
def _newClientConnection(self):
"""
Create a new client connection.
@@ -165,6 +185,7 @@
return client
factory = self.clientFactory()
+ factory.noisy = False
factory.connectionPool = self
@@ -222,6 +243,7 @@
@return: A L{Deferred} that fires with the result of the given command.
"""
+
if len(self._freeClients) > 0:
client = self._freeClients.pop()
@@ -274,6 +296,7 @@
@param client: An instance of C{self.clientFactory}
"""
+
if client in self._freeClients:
self._freeClients.remove(client)
@@ -294,6 +317,9 @@
self._freeClients.add(client)
+ if self.shutdown_deferred and self._isIdle():
+ self.shutdown_deferred.callback(None)
+
if len(self._commands) > 0:
d, command, args, kwargs = self._commands.pop(0)
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/resource.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/resource.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -27,6 +27,7 @@
"isPseudoCalendarCollectionResource",
]
+import os
import urllib
from zope.interface import implements
@@ -36,13 +37,12 @@
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.web2 import responsecode
from twisted.web2.dav import davxml
+from twisted.web2.dav.davxml import dav_namespace
+from twisted.web2.dav.http import ErrorResponse
from twisted.web2.dav.idav import IDAVPrincipalCollectionResource
from twisted.web2.dav.resource import AccessDeniedError, DAVPrincipalCollectionResource
-from twisted.web2.dav.davxml import dav_namespace
-from twisted.web2.dav.http import ErrorResponse
from twisted.web2.dav.resource import TwistedACLInheritable
-from twisted.web2.dav.util import joinURL, parentForURL, unimplemented,\
- normalizeURL
+from twisted.web2.dav.util import joinURL, parentForURL, unimplemented, normalizeURL
from twisted.web2.http import HTTPError, RedirectResponse, StatusResponse, Response
from twisted.web2.http_headers import MimeType
from twisted.web2.iweb import IResponse
@@ -51,16 +51,18 @@
import twistedcaldav
from twistedcaldav import caldavxml, customxml
+from twistedcaldav.caldavxml import caldav_namespace
from twistedcaldav.config import config
from twistedcaldav.customxml import TwistedCalendarAccessProperty
+from twistedcaldav.customxml import calendarserver_namespace
from twistedcaldav.extensions import DAVResource, DAVPrincipalResource
from twistedcaldav.ical import Component
+from twistedcaldav.ical import Component as iComponent
+from twistedcaldav.ical import allowedComponents
from twistedcaldav.icaldav import ICalDAVResource, ICalendarPrincipalResource
-from twistedcaldav.caldavxml import caldav_namespace
-from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.ical import allowedComponents
-from twistedcaldav.ical import Component as iComponent
from twistedcaldav.log import LoggingMixIn
+from twistedcaldav.memcacher import Memcacher
+from twistedcaldav.sql import AbstractSQLDatabase, db_prefix
from urlparse import urlsplit
@@ -828,6 +830,7 @@
(caldav_namespace, "calendar-user-type" ),
(calendarserver_namespace, "calendar-proxy-read-for" ),
(calendarserver_namespace, "calendar-proxy-write-for" ),
+ (calendarserver_namespace, "auto-schedule" ),
)
@classmethod
@@ -898,9 +901,23 @@
*[davxml.HRef(principal.principalURL()) for principal in results]
))
+ elif name == "auto-schedule":
+ autoSchedule = (yield self.getAutoSchedule())
+ returnValue(customxml.AutoSchedule("true" if autoSchedule else "false"))
+
result = (yield super(CalendarPrincipalResource, self).readProperty(property, request))
returnValue(result)
+ def writeProperty(self, property, request):
+ assert isinstance(property, davxml.WebDAVElement), (
+ "%r is not a WebDAVElement instance" % (property,)
+ )
+
+ if property.qname() == (caldav_namespace, "auto-schedule"):
+ self.setAutoSchedule(autoSchedule) # MOR: parse the value
+
+ return super(CalendarPrincipalResource, self).writeProperty(property, request)
+
def calendarHomeURLs(self):
if self.hasDeadProperty((caldav_namespace, "calendar-home-set")):
home_set = self.readDeadProperty((caldav_namespace, "calendar-home-set"))
@@ -989,6 +1006,39 @@
"""
return None
+ def setAutoSchedule(self, autoSchedule):
+ self._resource_info_index().setAutoSchedule(self.record.guid, autoSchedule)
+
+ def getAutoSchedule(self):
+ return self._resource_info_index().getAutoSchedule(self.record.guid)
+
+ def _resource_info_index(self):
+ """
+ Return the resource info SQL database for this calendar principal.
+
+ @return: the L{ResourceInfoDatabase} for the calendar principal.
+ """
+
+ # The db is located in the data root
+ self.pcollection = self.parent.parent # MOR: doesn't feel right
+ if not hasattr(self.pcollection, "resource_info_db"):
+ setattr(self.pcollection, "resource_info_db", ResourceInfoDatabase(config.DataRoot))
+ return self.pcollection.resource_info_db
+
+ def _calendar_user_proxy_index(self):
+ """
+ Return the calendar user proxy SQL database for this calendar principal.
+
+ @return: the L{CalendarUserProxyDatabase} for the calendar principal.
+ """
+
+ # The db is located in the data root
+ self.pcollection = self.parent.parent # MOR: doesn't feel right
+ if not hasattr(self.pcollection, "calendar_user_proxy_db"):
+ setattr(self.pcollection, "calendar_user_proxy_db", CalendarUserProxyDatabase(config.DataRoot))
+ return self.pcollection.calendar_user_proxy_db
+
+
##
# Utilities
##
@@ -1008,3 +1058,146 @@
return False
else:
return resource.isPseudoCalendarCollection()
+
+
+class ResourceInfoDatabase(AbstractSQLDatabase, LoggingMixIn):
+ """
+ A database to maintain resource (and location) information
+
+ SCHEMA:
+
+ Group Database:
+
+ ROW: GUID, AUTOSCHEDULE
+
+ """
+
+ dbType = "RESOURCEINFO"
+ dbFilename = "resourceinfo.sqlite"
+ dbOldFilename = db_prefix + "resourceinfo"
+ dbFormatVersion = "1"
+
+ class ResourceInfoDBMemcacher(Memcacher):
+
+ def setAutoSchedule(self, guid, autoSchedule):
+ return self.set("resourceinfo:%s" % (str(guid),), "1" if autoSchedule else "0")
+
+ @inlineCallbacks
+ def getAutoSchedule(self, guid):
+ result = (yield self.get("resourceinfo:%s" % (str(guid),)))
+ if result is not None:
+ autoSchedule = result == "1"
+ else:
+ autoSchedule = None
+ returnValue(autoSchedule)
+
+ def __init__(self, path):
+ path = os.path.join(path, ResourceInfoDatabase.dbFilename)
+ super(ResourceInfoDatabase, self).__init__(path, True)
+
+ self._memcacher = ResourceInfoDatabase.ResourceInfoDBMemcacher("resourceInfoDB")
+
+ @inlineCallbacks
+ def setAutoSchedule(self, guid, autoSchedule):
+ """
+ Set a resource/location's auto-Schedule boolean.
+
+ @param guid: the UID of the group principal to add.
+ @param autoSchedule: boolean
+ """
+ self.setAutoScheduleInDatabase(guid, autoSchedule)
+
+ # Update cache
+ _ignore = (yield self._memcacher.setAutoSchedule(guid, autoSchedule))
+
+ def setAutoScheduleInDatabase(self, guid, autoSchedule):
+ """
+ A blocking call to set a resource/location's auto-Schedule boolean
+ value in the database.
+
+ @param guid: the UID of the group principal to add.
+ @param autoSchedule: boolean
+ """
+ # Remove what is there, then add it back.
+ self._delete_from_db(guid)
+ self._add_to_db(guid, autoSchedule)
+ self._db_commit()
+
+ @inlineCallbacks
+ def getAutoSchedule(self, guid):
+ """
+ Return the auto-Schedule state for the resource/location specified by guid
+ """
+
+ # Pull from cache
+ autoSchedule = (yield self._memcacher.getAutoSchedule(guid))
+ if autoSchedule is None:
+ # Not in memcache, check local db
+ autoSchedule = self._db_value_for_sql("select AUTOSCHEDULE from RESOURCEINFO where GUID = :1", guid)
+ if autoSchedule is not None:
+ autoSchedule = autoSchedule == 1
+ result = (yield self._memcacher.setAutoSchedule(guid, autoSchedule))
+ else:
+ # Not in local db
+ # MOR: no value -- what to do, default to False?
+ autoSchedule = False
+
+ returnValue(autoSchedule)
+
+ def _add_to_db(self, guid, autoSchedule):
+ """
+ Insert the specified entry into the database.
+
+ @param guid: the guid of the resource/location
+ @param autoSchedule: a boolean
+ """
+ self._db_execute(
+ """
+ insert into RESOURCEINFO (GUID, AUTOSCHEDULE)
+ values (:1, :2)
+ """, guid, 1 if autoSchedule else 0
+ )
+
+ def _delete_from_db(self, guid):
+ """
+ Deletes the specified entry from the database.
+
+ @param guid: the guid of the resource/location to delete
+ """
+ self._db_execute("delete from RESOURCEINFO where GUID = :1", guid)
+
+ def _db_version(self):
+ """
+ @return: the schema version assigned to this index.
+ """
+ return ResourceInfoDatabase.dbFormatVersion
+
+ def _db_type(self):
+ """
+ @return: the collection type assigned to this index.
+ """
+ return ResourceInfoDatabase.dbType
+
+ def _db_init_data_tables(self, q):
+ """
+ Initialise the underlying database tables.
+ @param q: a database cursor to use.
+ """
+
+ #
+ # RESOURCEINFO table
+ #
+ q.execute(
+ """
+ create table RESOURCEINFO (
+ GUID text,
+ AUTOSCHEDULE integer
+ )
+ """
+ )
+ q.execute(
+ """
+ create index RESOURCEGUIDS on RESOURCEINFO (GUID)
+ """
+ )
+
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/scheduling/processing.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/scheduling/processing.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -269,7 +269,7 @@
raise ImplicitProcessorException(iTIPRequestStatus.NO_USER_SUPPORT)
log.debug("ImplicitProcessing - originator '%s' to recipient '%s' ignoring METHOD:REQUEST, UID: '%s' - new processed" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
- autoprocessed = self.recipient.principal.autoSchedule()
+ autoprocessed = (yield self.recipient.principal.getAutoSchedule())
new_calendar = iTipProcessing.processNewRequest(self.message, self.recipient.cuaddr, autoprocessing=autoprocessed)
name = md5(str(new_calendar) + str(time.time()) + default.fp.path).hexdigest() + ".ics"
@@ -292,7 +292,7 @@
result = (True, autoprocessed, changes,)
else:
# Processing update to existing event
- autoprocessed = self.recipient.principal.autoSchedule()
+ autoprocessed = (yield self.recipient.principal.getAutoSchedule())
new_calendar, props_changed, rids = iTipProcessing.processRequest(self.message, self.recipient_calendar, self.recipient.cuaddr, autoprocessing=autoprocessed)
if new_calendar:
@@ -351,7 +351,7 @@
else:
# Need to check for auto-respond attendees. These need to suppress the inbox message
# if the cancel is processed.
- autoprocessed = self.recipient.principal.autoSchedule()
+ autoprocessed = (yield self.recipient.principal.getAutoSchedule())
# Check to see if this is a cancel of the entire event
processed_message, delete_original, rids = iTipProcessing.processCancel(self.message, self.recipient_calendar, autoprocessing=autoprocessed)
Modified: CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/test/test_memcachepool.py
===================================================================
--- CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/test/test_memcachepool.py 2009-04-23 19:53:23 UTC (rev 4071)
+++ CalendarServer/branches/users/sagen/resource-delegates-4066/twistedcaldav/test/test_memcachepool.py 2009-04-23 23:47:07 UTC (rev 4072)
@@ -40,8 +40,11 @@
"""
def __init__(self):
self.calls = []
+ self.shutdown_deferred = None
+ self.shutdown_requested = False
+
def clientFree(self, client):
"""
Record a C{'free'} call for C{client}.
@@ -100,7 +103,10 @@
return StubConnector()
+ def addSystemEventTrigger(*args, **kwds):
+ pass
+
class PooledMemCacheProtocolTests(TestCase):
"""
Tests for the L{PooledMemCacheProtocol}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090423/de4e9430/attachment-0001.html>
More information about the calendarserver-changes
mailing list