[CalendarServer-changes] [4502] CalendarServer/branches/users/cdaboo/partition-4464

source_changes at macosforge.org source_changes at macosforge.org
Fri Aug 21 11:10:31 PDT 2009


Revision: 4502
          http://trac.macosforge.org/projects/calendarserver/changeset/4502
Author:   cdaboo at apple.com
Date:     2009-08-21 11:10:27 -0700 (Fri, 21 Aug 2009)
Log Message:
-----------
Make full use of augment data in directory records.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/caldav.py
    CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/test/test_caldav.py
    CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/principals.py
    CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/util.py
    CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/webadmin/resource.py
    CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml
    CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd
    CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml
    CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-apple.plist
    CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-test.plist
    CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd.plist
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/augment.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sudo.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments.xml
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_aggregate.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_augment.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_cachedirectory.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_calendar.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_guidchange.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectory.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/resource.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/implicit.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/processing.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_upgrade.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/upgrade.py

Added Paths:
-----------
    CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments-test.xml
    CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments.dtd
    CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies-test.xml
    CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies.dtd
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/calendaruserproxyloader.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments-test.xml
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/proxies.xml
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaugmentsparser.py

Removed Paths:
-------------
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sqldb.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/basic
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/digest
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/groups
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_apache.py
    CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_sqldb.py

Modified: CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/caldav.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/caldav.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -39,6 +39,7 @@
 from twisted.python.usage import Options, UsageError
 from twisted.python.reflect import namedClass
 from twisted.plugin import IPlugin
+from twisted.internet import reactor
 from twisted.internet.reactor import callLater
 from twisted.internet.process import ProcessExitedAlready
 from twisted.internet.protocol import Protocol, Factory
@@ -74,6 +75,8 @@
 from twistedcaldav.config import config
 from twistedcaldav.config import ConfigurationError
 from twistedcaldav.resource import CalDAVResource, AuthenticationWrapper
+from twistedcaldav.directory import augment
+from twistedcaldav.directory.calendaruserproxyloader import XMLCalendarUserProxyLoader
 from twistedcaldav.directory.digest import QopDigestCredentialFactory
 from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
 from twistedcaldav.directory.aggregate import AggregateDirectoryService
@@ -493,6 +496,29 @@
                 SudoDirectoryService.recordType_sudoers)
 
         #
+        # Setup the Augment Service
+        #
+        augmentClass = namedClass(config.AugmentService.type)
+
+        self.log_info("Configuring augment service of type: %s" % (augmentClass,))
+
+        try:
+            augment.AugmentService = augmentClass(**config.AugmentService.params)
+        except IOError, e:
+            self.log_error("Could not start augment service")
+            raise
+
+        #
+        # Make sure proxies get initialized
+        #
+        if config.ProxyLoadFromFile:
+            def _doProxyUpdate():
+                loader = XMLCalendarUserProxyLoader(config.ProxyLoadFromFile)
+                return loader.updateProxyDB()
+            
+            reactor.addSystemEventTrigger("before", "startup", _doProxyUpdate)
+
+        #
         # Configure Memcached Client Pool
         #
         if config.Memcached.ClientEnabled:

Modified: CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/test/test_caldav.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/test/test_caldav.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tap/test/test_caldav.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2007 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2009 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -180,6 +180,7 @@
         self.config = ConfigDict(DEFAULT_CONFIG)
 
         accountsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/accounts.xml")
+        augmentsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/augments.xml")
         pemFile = os.path.join(sourceRoot, "twistedcaldav/test/data/server.pem")
 
         self.config["DirectoryService"] = {
@@ -187,6 +188,11 @@
             "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService"
         }
 
+        self.config["AugmentService"] = {
+            "params": {"xmlFiles": [augmentsFile]},
+            "type": "twistedcaldav.directory.augment.AugmentXMLDB"
+        }
+
         self.config.DocumentRoot   = self.mktemp()
         self.config.DataRoot       = self.mktemp()
         self.config.ProcessType    = "Slave"

Modified: CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/principals.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/principals.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -431,11 +431,11 @@
             { True: "true", False: "false" }[autoSchedule],
             principal,
         )
-        (yield principal.setAutoSchedule(autoSchedule))
+        principal.setAutoSchedule(autoSchedule)
 
 @inlineCallbacks
 def action_getAutoSchedule(principal):
-    autoSchedule = (yield principal.getAutoSchedule())
+    autoSchedule = principal.getAutoSchedule()
     print "Autoschedule for %s is %s" % (
         principal,
         { True: "true", False: "false" }[autoSchedule],

Modified: CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/util.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/util.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/tools/util.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -29,6 +29,7 @@
 
 import socket
 from twistedcaldav.config import config, ConfigurationError
+from twistedcaldav.directory import augment
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
 from twistedcaldav.stdconfig import DEFAULT_CONFIG_FILE
 
@@ -93,6 +94,9 @@
     while not directory.isAvailable():
         sleep(5)
 
+    augmentClass = namedClass(config.AugmentService.type)
+    augment.AugmentService = augmentClass(**config.AugmentService.params)
+
     return directory
 
 class DummyDirectoryService (DirectoryService):

Modified: CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/webadmin/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/webadmin/resource.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/calendarserver/webadmin/resource.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -154,7 +154,7 @@
             # Update the auto-schedule value if specified.
             if autoSchedule is not None and (autoSchedule == "true" or autoSchedule == "false"):
                 if principal.record.recordType != "users" and principal.record.recordType != "groups":
-                    result = (yield principal.setAutoSchedule(autoSchedule == "true"))
+                    result = principal.setAutoSchedule(autoSchedule == "true")
 
             # Update the proxies if specified.
             for proxyId in removeProxies:
@@ -277,7 +277,7 @@
         ###
         autoScheduleHtml = ""
         if resource.record.recordType != "users" and resource.record.recordType != "groups":
-            autoSchedule = (yield resource.getAutoSchedule())
+            autoSchedule = resource.getAutoSchedule()
             autoScheduleHtml = """
 <div style=\"margin-top:15px; border-bottom:1px #444444 dotted\"></div>
 <form id=\"frm_autoSchedule\" name=\"autoScheduleForm\" action=\"/admin/\" style=\"margin-top:15px\">

Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -44,8 +44,6 @@
     <first-name>User</first-name>
     <last-name>%02d</last-name>
     <email-address>user%02d at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:user%02d at example.com</cuaddr>
   </user>
   <user repeat="10">
     <uid>public%02d</uid>
@@ -54,30 +52,18 @@
     <name>Public %02d</name>
     <first-name>Public</first-name>
     <last-name>%02d</last-name>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:public%02d at example.com</cuaddr>
   </user>
   <location repeat="10">
     <uid>location%02d</uid>
     <guid>location%02d</guid>
     <password>location%02d</password>
     <name>Room %02d</name>
-    <enable-calendar>true</enable-calendar>
-    <auto-schedule/>
   </location>
   <resource repeat="10">
     <uid>resource%02d</uid>
     <guid>resource%02d</guid>
     <password>resource%02d</password>
     <name>Resource %02d</name>
-    <enable-calendar>true</enable-calendar>
-    <auto-schedule/>
-    <proxies>
-      <member type="users">user01</member>
-    </proxies>
-    <read-only-proxies>
-      <member type="users">user03</member>
-    </read-only-proxies>
   </resource>
   <group>
     <uid>group01</uid>
@@ -123,7 +109,6 @@
     <uid>disabledgroup</uid>
     <guid>disabledgroup</guid>
     <password>disabledgroup</password>
-    <enable>false</enable>
     <name>Disabled Group</name>
     <members>
       <member type="users">user01</member>

Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd	2009-08-21 18:10:27 UTC (rev 4502)
@@ -17,16 +17,16 @@
 <!ELEMENT accounts (user*, group*, resource*, location*) >
   <!ATTLIST accounts realm CDATA "">
 
-  <!ELEMENT user (uid*, guid, password?, enable?, hosted-at?, name?, first-name?, last-name?, email-address*, enable-calendar?, cuaddr*)>
+  <!ELEMENT user (uid*, guid, password?, name?, first-name?, last-name?, email-address*,)>
     <!ATTLIST user repeat CDATA "1">
 
-  <!ELEMENT group (uid*, guid, password?, enable?, hosted-at?, name?, members, enable-calendar?, cuaddr*)>
+  <!ELEMENT group (uid*, guid, password?, name?, members, enable-calendar?,)>
     <!ATTLIST group repeat CDATA "1">
 
-  <!ELEMENT resource (uid*, guid, password?, enable?, hosted-at?, name?, enable-calendar?, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
+  <!ELEMENT resource (uid*, guid, password?, name?,)>
     <!ATTLIST resource repeat CDATA "1">
 
-  <!ELEMENT location (uid*, guid, password?, enable?, hosted-at?, name?, enable-calendar?, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
+  <!ELEMENT location (uid*, guid, password?, name?,)>
     <!ATTLIST location repeat CDATA "1">
 
   <!ELEMENT member (#PCDATA)>
@@ -35,16 +35,9 @@
   <!ELEMENT uid               (#PCDATA)>
   <!ELEMENT guid              (#PCDATA)>
   <!ELEMENT password          (#PCDATA)>
-  <!ELEMENT enable            (#PCDATA)>
-  <!ELEMENT hosted-at         (#PCDATA)>
   <!ELEMENT name              (#PCDATA)>
   <!ELEMENT first-name        (#PCDATA)>
   <!ELEMENT last-name         (#PCDATA)>
   <!ELEMENT email-address     (#PCDATA)>
   <!ELEMENT members           (member*)>
-  <!ELEMENT enable-calendar   (#PCDATA)>
-  <!ELEMENT cuaddr            (#PCDATA)>
-  <!ELEMENT auto-schedule     (#PCDATA)>
-  <!ELEMENT proxies           (member*)>
-  <!ELEMENT read-only-proxies (member*)>
 >

Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -28,8 +28,6 @@
     <uid>test</uid>
     <password>test</password>
     <name>Test User</name>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:testuser at example.com</cuaddr>
   </user>
   <group>
     <uid>users</uid>
@@ -43,11 +41,6 @@
     <uid>mercury</uid>
     <password>mercury</password>
     <name>Mecury Conference Room, Building 1, 2nd Floor</name>
-    <enable-calendar>true</enable-calendar>
-    <auto-schedule>true</auto-schedule>
-    <proxies>
-      <member type="users">test</member>
-    </proxies>
   </location>
 </accounts>
 

Added: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments-test.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments-test.xml	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments-test.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<!DOCTYPE augments SYSTEM "augments.dtd">
+
+<augments>
+  <record>
+    <guid>admin</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
+    <guid>apprentice</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record repeat="99">
+    <guid>user%02d</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <cuaddr>mailto:user%02d at example.com</cuaddr>
+  </record>
+  <record repeat="10">
+    <guid>public%02d</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <cuaddr>mailto:public%02d at example.com</cuaddr>
+  </record>
+  <record repeat="10">
+    <guid>location%02d</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <auto-schedule>true</auto-schedule>
+  </record>
+  <record repeat="10">
+    <guid>resource%02d</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <auto-schedule>true</auto-schedule>
+  </record>
+  <record repeat="4">
+    <guid>group%02d</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>disabledgroup</guid>
+    <enable>false</enable>
+  </record>
+</augments>

Added: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments.dtd
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments.dtd	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/augments.dtd	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,28 @@
+<!--
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<!ELEMENT augments (record*) >
+
+  <!ELEMENT record (guid, enable, hosted-at?, enable-calendar?, auto-schedule?, cuaddr*)>
+    <!ATTLIST record repeat CDATA "1">
+
+  <!ELEMENT guid              (#PCDATA)>
+  <!ELEMENT enable            (#PCDATA)>
+  <!ELEMENT hosted-at         (#PCDATA)>
+  <!ELEMENT enable-calendar   (#PCDATA)>
+  <!ELEMENT auto-schedule     (#PCDATA)>
+  <!ELEMENT cuaddr            (#PCDATA)>
+>

Added: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies-test.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies-test.xml	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies-test.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<!DOCTYPE proxies SYSTEM "proxies.dtd">
+
+<proxies>
+  <record repeat="10">
+    <guid>resource%02d</guid>
+    <proxies>
+      <member>user01</member>
+    </proxies>
+    <read-only-proxies>
+      <member>user03</member>
+    </read-only-proxies>
+  </record>
+</proxies>

Added: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies.dtd
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies.dtd	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/proxies.dtd	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,26 @@
+<!--
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<!ELEMENT proxies (record*) >
+
+  <!ELEMENT record (guid, proxies?, read-only-proxies?)>
+    <!ATTLIST record repeat CDATA "1">
+
+  <!ELEMENT guid              (#PCDATA)>
+  <!ELEMENT proxies           (member*)>
+  <!ELEMENT read-only-proxies (member*)>
+  <!ELEMENT member            (#PCDATA)>
+>

Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-apple.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-apple.plist	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-apple.plist	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2009 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -160,6 +160,45 @@
 
 
     <!--
+        Augment service
+
+        Augments for the directory service records to add calendar specific attributes.
+
+        A variety of augment services are available for use.
+        When using a partitioned server, a service that can be accessed from each host will be needed.
+      -->
+
+    <!-- XML File Augment Service -->
+    <key>AugmentService</key>
+    <dict>
+      <key>type</key>
+      <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
+      
+      <key>params</key>
+      <dict>
+        <key>xmlFiles</key>
+        <array>
+	      <string>/etc/caldavd/augments.xml</string>
+        </array>
+      </dict>
+    </dict>
+    
+    <!-- Sqlite Augment Service -->
+    <!--
+    <key>AugmentService</key>
+    <dict>
+      <key>type</key>
+      <string>twistedcaldav.directory.augment.AugmentSqliteDB</string>
+      
+      <key>params</key>
+      <dict>
+        <key>dbpath</key>
+        <string>/etc/caldavd/augments.sqlite</string>
+      </dict>
+    </dict>
+     -->
+
+    <!--
         Special principals
 
         These principals are granted special access and/or perform

Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-test.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-test.plist	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd-test.plist	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2009 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -145,10 +145,6 @@
       <dict>
         <key>node</key>
         <string>/Search</string>
-        <key>restrictEnabledRecords</key>
-        <false/>
-        <key>restrictToGroup</key>
-        <string></string>
         <key>cacheTimeout</key>
         <integer>30</integer>
       </dict>
@@ -212,6 +208,48 @@
 
 
     <!--
+        Augment service
+
+        Augments for the directory service records to add calendar specific attributes.
+
+        A variety of augment services are available for use.
+        When using a partitioned server, a service that can be accessed from each host will be needed.
+      -->
+
+    <!-- XML File Augment Service -->
+    <key>AugmentService</key>
+    <dict>
+      <key>type</key>
+      <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
+      
+      <key>params</key>
+      <dict>
+        <key>xmlFiles</key>
+        <array>
+	      <string>conf/auth/augments-test.xml</string>
+        </array>
+      </dict>
+    </dict>
+    
+    <!-- Sqlite Augment Service -->
+    <!--
+    <key>AugmentService</key>
+    <dict>
+      <key>type</key>
+      <string>twistedcaldav.directory.augment.AugmentSqliteDB</string>
+      
+      <key>params</key>
+      <dict>
+        <key>dbpath</key>
+        <string>/etc/caldavd/augments.sqlite</string>
+      </dict>
+    </dict>
+     -->
+
+	<key>ProxyLoadFromFile</key>
+    <string>conf/auth/proxies-test.xml</string>
+
+    <!--
         Special principals
 
         These principals are granted special access and/or perform

Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd.plist	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/caldavd.plist	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+    Copyright (c) 2006-2009 Apple Inc. All rights reserved.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -148,10 +148,6 @@
       <dict>
         <key>node</key>
         <string>/Search</string>
-        <key>restrictEnabledRecords</key>
-        <false/>
-        <key>restrictToGroup</key>
-        <string></string>
         <key>cacheTimeout</key>
         <integer>30</integer>
       </dict>
@@ -159,6 +155,45 @@
      -->
 
     <!--
+        Augment service
+
+        Augments for the directory service records to add calendar specific attributes.
+
+        A variety of augment services are available for use.
+        When using a partitioned server, a service that can be accessed from each host will be needed.
+      -->
+
+    <!-- XML File Augment Service -->
+    <key>AugmentService</key>
+    <dict>
+      <key>type</key>
+      <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
+      
+      <key>params</key>
+      <dict>
+        <key>xmlFiles</key>
+        <array>
+	      <string>/etc/caldavd/augments.xml</string>
+        </array>
+      </dict>
+    </dict>
+    
+    <!-- Sqlite Augment Service -->
+    <!--
+    <key>AugmentService</key>
+    <dict>
+      <key>type</key>
+      <string>twistedcaldav.directory.augment.AugmentSqliteDB</string>
+      
+      <key>params</key>
+      <dict>
+        <key>dbpath</key>
+        <string>/etc/caldavd/augments.sqlite</string>
+      </dict>
+    </dict>
+     -->
+
+    <!--
         Special principals
 
         These principals are granted special access and/or perform

Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,221 +0,0 @@
-##
-# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-Apache UserFile/GroupFile compatible directory service implementation.
-"""
-
-__all__ = [
-    "BasicDirectoryService",
-    "DigestDirectoryService",
-]
-
-from crypt import crypt
-
-from twisted.python.filepath import FilePath
-from twisted.cred.credentials import UsernamePassword
-
-from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
-from twistedcaldav.directory.directory import UnknownRecordTypeError, DirectoryConfigurationError
-
-class AbstractDirectoryService(DirectoryService):
-    """
-    Abstract Apache-compatible implementation of L{IDirectoryService}.
-    """
-    def __repr__(self):
-        return "<%s %r: %r %r>" % (self.__class__.__name__, self.realmName, self.userFile, self.groupFile)
-
-    def __init__(self, params):
-        defaults = {
-            'realmName' : '',
-            'userFile' : None,
-            'groupFile' : None,
-        }
-        ignored = None
-        params = self.getParams(params, defaults, ignored)
-
-        super(AbstractDirectoryService, self).__init__()
-
-        userFile = params["userFile"]
-        if not userFile:
-            raise DirectoryConfigurationError("Invalid Apache user file name: %r" % (userFile,))
-
-        if userFile and type(userFile) is str:
-            userFile = FilePath(userFile)
-
-        groupFile = params["groupFile"]
-        if groupFile and type(groupFile) is str:
-            groupFile = FilePath(groupFile)
-
-        self.realmName = params["realmName"]
-        self.userFile = userFile
-        self.groupFile = groupFile
-
-    def recordTypes(self):
-        recordTypes = (DirectoryService.recordType_users,)
-        if self.groupFile is not None:
-            recordTypes += (DirectoryService.recordType_groups,)
-        return recordTypes
-
-    def listRecords(self, recordType):
-        for entryShortName, entryData in self.entriesForRecordType(recordType):
-            if recordType == DirectoryService.recordType_users:
-                yield self.userRecordClass(
-                    service       = self,
-                    recordType    = recordType,
-                    shortName     = entryShortName,
-                    cryptPassword = entryData,
-                )
-
-            elif recordType == DirectoryService.recordType_groups:
-                yield GroupRecord(
-                    service    = self,
-                    recordType = recordType,
-                    shortName  = entryShortName,
-                    members    = entryData,
-                )
-
-            else:
-                # Subclass should cover the remaining record types
-                raise UnknownRecordTypeError("Unknown record type: %s" % (recordType,))
-
-    def recordWithShortName(self, recordType, shortName):
-        for entryShortName, entryData in self.entriesForRecordType(recordType):
-            if entryShortName == shortName:
-                if recordType == DirectoryService.recordType_users:
-                    return self.userRecordClass(
-                        service       = self,
-                        recordType    = recordType,
-                        shortName     = entryShortName,
-                        cryptPassword = entryData,
-                    )
-
-                if recordType == DirectoryService.recordType_groups:
-                    return GroupRecord(
-                        service    = self,
-                        recordType = recordType,
-                        shortName  = entryShortName,
-                        members    = entryData,
-                    )
-
-                # Subclass should cover the remaining record types
-                raise UnknownRecordTypeError("Unknown record type: %s" % (recordType,))
-
-        return None
-
-    def entriesForRecordType(self, recordType):
-        if recordType == DirectoryService.recordType_users:
-            recordFile = self.userFile
-        elif recordType == DirectoryService.recordType_groups:
-            recordFile = self.groupFile
-        else:
-            raise UnknownRecordTypeError("Unknown record type: %s" % (recordType,))
-
-        if recordFile is None:
-            return
-
-        try:
-            handle = recordFile.open()
-        except IOError, OSError:
-            self.log_error("Auth file (for %s) not found: %s" % (recordType, recordFile.path))
-            return
-
-        try:
-            for entry in handle:
-                if entry and entry[0] != "#":
-                    try:
-                        shortName, rest = entry.rstrip("\n").split(":", 1)
-                    except ValueError:
-                        continue
-                    yield shortName, rest
-        finally:
-            handle.close()
-
-class AbstractDirectoryRecord(DirectoryRecord):
-    """
-    Abstract Apache-compatible implementation of L{IDirectoryRecord}.
-    """
-    def __init__(self, service, recordType, shortName):
-        super(AbstractDirectoryRecord, self).__init__(
-            service               = service,
-            recordType            = recordType,
-            guid                  = None,
-            enabled               = True,
-            shortNames            = (shortName,),
-        )
-
-class AbstractUserRecord(AbstractDirectoryRecord):
-    def __init__(self, service, recordType, shortName, cryptPassword=None):
-        super(AbstractUserRecord, self).__init__(service, recordType, shortName)
-
-        self._cryptPassword = cryptPassword
-
-    def groups(self):
-        for group in self.service.listRecords(DirectoryService.recordType_groups):
-            for member in group.members():
-                if member == self:
-                    yield group
-                    continue
-
-class BasicUserRecord(AbstractUserRecord):
-    """
-    Apache UserFile implementation of L{IDirectoryRecord}.
-    """
-    def verifyCredentials(self, credentials):
-        if self._cryptPassword in ("", "*", "x"):
-            return False
-
-        if isinstance(credentials, UsernamePassword):
-            return crypt(credentials.password, self._cryptPassword) == self._cryptPassword
-
-        return super(BasicUserRecord, self).verifyCredentials(credentials)
-
-class BasicDirectoryService(AbstractDirectoryService):
-    """
-    Apache UserFile/GroupFile implementation of L{IDirectoryService}.
-    """
-    baseGUID = "DDF1E45C-CADE-4FCD-8AE6-B4B41D72B325"
-    userRecordClass = BasicUserRecord
-
-class DigestUserRecord(AbstractUserRecord):
-    """
-    Apache DigestUserFile implementation of L{IDirectoryRecord}.
-    """
-    def verifyCredentials(self, credentials):
-        raise NotImplementedError()
-
-class DigestDirectoryService(AbstractDirectoryService):
-    """
-    Apache DigestUserFile/GroupFile implementation of L{IDirectoryService}.
-    """
-    baseGUID = "0C719D1B-0A14-4074-8740-6D96A7D0C787"
-    userRecordClass = DigestUserRecord
-
-class GroupRecord(AbstractDirectoryRecord):
-    """
-    Apache GroupFile implementation of L{IDirectoryRecord}.
-    """
-    def __init__(self, service, recordType, shortName, members=()):
-        super(GroupRecord, self).__init__(service, recordType, shortName)
-
-        if type(members) is str:
-            members = tuple(m.strip() for m in members.split(","))
-
-        self._members = members
-
-    def members(self):
-        for shortName in self._members:
-            yield self.service.recordWithShortName(DirectoryService.recordType_users, shortName)

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -33,6 +33,7 @@
 from twisted.cred.credentials import UsernamePassword
 from twisted.web2.auth.digest import DigestedCredentials
 
+from twistedcaldav.directory import augment
 from twistedcaldav.directory.cachingdirectory import CachingDirectoryService,\
     CachingDirectoryRecord
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
@@ -63,7 +64,11 @@
             'node' : '/Search',
             'cacheTimeout' : 30,
         }
-        ignored = ('requireComputerRecord',)
+        ignored = (
+            'requireComputerRecord',
+            'restrictEnabledRecords',
+            'restrictToGroup'
+        )
         params = self.getParams(params, defaults, ignored)
 
         super(OpenDirectoryService, self).__init__(params['cacheTimeout'])
@@ -154,26 +159,6 @@
             ):
                 yield GUID
 
-    def _calendarUserAddresses(self, recordType, recordData):
-        """
-        Extract specific attributes from the directory record for use as calendar user address.
-        
-        @param recordData: a C{dict} containing the attributes retrieved from the directory.
-        @return: a C{set} of C{str} for each expanded calendar user address.
-        """
-        # Now get the addresses
-        result = set()
-        
-        # Add each email address as a mailto URI
-        emails = recordData.get(dsattributes.kDSNAttrEMailAddress)
-        if emails is not None:
-            if isinstance(emails, str):
-                emails = [emails]
-            for email in emails:
-                result.add("mailto:%s" % (email.lower(),))
-                
-        return result
-
     def recordTypes(self):
         return (
             self.recordType_users,
@@ -558,33 +543,6 @@
                                % (recordType, recordShortName, recordNodeName))
                 continue
 
-            # Determine enabled state
-            if recordType == self.recordType_groups:
-                enabledForCalendaring = False
-            else:
-                enabledForCalendaring = True
-
-            if enabledForCalendaring:
-                calendarUserAddresses = self._calendarUserAddresses(recordType, value)
-            else:
-                # Some records we want to keep even though they are not enabled for calendaring.
-                # Others we discard.
-                if recordType not in (
-                    self.recordType_users,
-                    self.recordType_groups,
-                ):
-                    self.log_debug(
-                        "Record (%s) %s is not enabled for calendaring"
-                        % (recordType, recordShortName)
-                    )
-                    continue
-
-                self.log_debug(
-                    "Record (%s) %s is not enabled for calendaring but may be used in ACLs"
-                    % (recordType, recordShortName)
-                )
-                calendarUserAddresses = ()
-
             # Special case for groups, which have members.
             if recordType == self.recordType_groups:
                 memberGUIDs = value.get(dsattributes.kDSNAttrGroupMembers)
@@ -611,11 +569,16 @@
                 firstName             = recordFirstName,
                 lastName              = recordLastName,
                 emailAddresses        = recordEmailAddresses,
-                enabledForCalendaring = enabledForCalendaring,
-                calendarUserAddresses = calendarUserAddresses,
                 memberGUIDs           = memberGUIDs,
             )
-            if enabledForCalendaring:
+
+            # Look up augment information
+            # TODO: this needs to be deferred but for now we hard code the deferred result because
+            # we know it is completing immediately.
+            d = augment.AugmentService.getAugmentRecord(record.guid)
+            d.addCallback(lambda x:record.addAugmentInformation(x))
+
+            if record.enabledForCalendaring:
                 enabledRecords.append(record)
             else:
                 disabledRecords.append(record)
@@ -693,8 +656,6 @@
     def __init__(
         self, service, recordType, guid, nodeName, shortNames, authIDs,
         fullName, firstName, lastName, emailAddresses,
-        enabledForCalendaring,
-        calendarUserAddresses,
         memberGUIDs,
     ):
         super(OpenDirectoryRecord, self).__init__(
@@ -707,8 +668,6 @@
             firstName             = firstName,
             lastName              = lastName,
             emailAddresses        = emailAddresses,
-            enabledForCalendaring = enabledForCalendaring,
-            calendarUserAddresses = calendarUserAddresses,
         )
         self.nodeName = nodeName
         self._memberGUIDs = tuple(memberGUIDs)

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/augment.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/augment.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/augment.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -14,12 +14,16 @@
 # limitations under the License.
 ##
 
-from twistedcaldav.database import AbstractADBAPIDatabase
-from twistedcaldav.directory.xmlaccountsparser import XMLAccountsParser,\
-    RECORD_TYPES
 
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+from twistedcaldav.database import AbstractADBAPIDatabase
+from twistedcaldav.directory.xmlaugmentsparser import XMLAugmentsParser
+import time
 
+from twistedcaldav.log import Logger
+
+log = Logger()
+
 class AugmentRecord(object):
     """
     Augmented directory record information
@@ -28,18 +32,18 @@
     def __init__(
         self,
         guid,
-        enabled,
-        hostedAt,
-        enabledForCalendaring,
-        autoSchedule,
-        calendarUserAddresses,  
+        enabled=False,
+        hostedAt="",
+        enabledForCalendaring=False,
+        autoSchedule=False,
+        calendarUserAddresses=None,  
     ):
         self.guid = guid
         self.enabled = enabled
         self.hostedAt = hostedAt
         self.enabledForCalendaring = enabledForCalendaring
         self.autoSchedule = autoSchedule
-        self.calendarUserAddresses = calendarUserAddresses
+        self.calendarUserAddresses = calendarUserAddresses if calendarUserAddresses else set()
 
 class AugmentDB(object):
     """
@@ -61,17 +65,34 @@
         
         raise NotImplementedError("Child class must define this.")
 
+    def refresh(self):
+        """
+        Refresh any cached data.
+        """
+        pass
+        
+AugmentService = AugmentDB()   # Global augment service
+
+
 class AugmentXMLDB(AugmentDB):
     """
     XMLFile based augment database implementation.
     """
     
-    def __init__(self, xmlfilepath):
+    def __init__(self, xmlFiles, cacheTimeout=30):
         
-        self.xmlfilepath = xmlfilepath
+        self.xmlFiles = xmlFiles
+        self.cacheTimeout = cacheTimeout * 60 # Value is mins we want secs
+        self.lastCached = 0
         self.db = {}
         
-        self._parseXML()
+        try:
+            self.db = self._parseXML()
+        except RuntimeError:
+            log.error("Failed to parse XML augments file - fatal error on startup")
+            raise
+            
+        self.lastCached = time.time()
 
     def getAugmentRecord(self, guid):
         """
@@ -83,32 +104,33 @@
         @return: L{Deferred}
         """
         
+        # May need to re-cache
+        if self.lastCached + self.cacheTimeout <= time.time():
+            self.refresh()
+            
         return succeed(self.db.get(guid))
 
+    def refresh(self):
+        """
+        Refresh any cached data.
+        """
+        try:
+            self.db = self._parseXML()
+        except RuntimeError:
+            log.error("Failed to parse XML augments file during cache refresh - ignoring")
+        self.lastCached = time.time()
+
     def _parseXML(self):
         
-        # We will re-use the XML account format and associated classes
+        # Do each file
+        results = {}
+        for xmlFile in self.xmlFiles:
+            
+            # Creating a parser does the parse
+            XMLAugmentsParser(xmlFile, results)
         
-        # Create a parser and do the parse
-        parser = XMLAccountsParser(self.xmlfilepath, externalUpdate=False)
-        
-        # Add all records to our DB
-        for recordType in RECORD_TYPES.values():
-            for record in parser.items[recordType].itervalues():
-                
-                # Create augment record from XML account record
-                augment = AugmentRecord(
-                    guid=record.guid,
-                    enabled=record.enabled,
-                    hostedAt=record.hostedAt,
-                    enabledForCalendaring=record.enabledForCalendaring,
-                    autoSchedule=record.autoSchedule,
-                    calendarUserAddresses=record.calendarUserAddresses,
-                )
-                
-                self.db[augment.guid] = augment
+        return results
 
-
 class AugmentADAPI(AugmentDB, AbstractADBAPIDatabase):
     """
     DBAPI based augment database implementation.

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -334,27 +334,20 @@
 
     def __init__(
         self, service, recordType, guid,
-        enabled=False, hostedAt="",
         shortNames=(), authIDs=set(),
         fullName=None, firstName=None, lastName=None, emailAddresses=set(),
-        enabledForCalendaring=None,
-        calendarUserAddresses=set(),
         uid=None,
     ):
         super(CachingDirectoryRecord, self).__init__(
             service               = service,
             recordType            = recordType,
             guid                  = guid,
-            enabled               = enabled,
-            hostedAt              = hostedAt,
             shortNames            = shortNames,
             authIDs               = authIDs,
             fullName              = fullName,
             firstName             = firstName,
             lastName              = lastName,
             emailAddresses        = emailAddresses,
-            enabledForCalendaring = enabledForCalendaring,
-            calendarUserAddresses = calendarUserAddresses,
             uid                   = uid,
         )
         

Added: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/calendaruserproxyloader.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/calendaruserproxyloader.py	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/calendaruserproxyloader.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,138 @@
+##
+# Copyright (c) 2009 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from xml.etree.ElementTree import ElementTree
+from xml.parsers.expat import ExpatError
+from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
+from twistedcaldav.config import config
+from twisted.internet.defer import inlineCallbacks
+import types
+
+"""
+XML based calendar user proxy loader.
+"""
+
+__all__ = [
+    "XMLCalendarUserProxyLoader",
+]
+
+from twistedcaldav.log import Logger
+
+log = Logger()
+
+ELEMENT_PROXIES           = "proxies"
+ELEMENT_RECORD            = "record"
+
+ELEMENT_GUID              = "guid"
+ELEMENT_PROXIES           = "proxies"
+ELEMENT_READ_ONLY_PROXIES = "read-only-proxies"
+ELEMENT_MEMBER            = "member"
+
+ATTRIBUTE_REPEAT          = "repeat"
+
+class XMLCalendarUserProxyLoader(object):
+    """
+    XML calendar user proxy configuration file parser and loader.
+    """
+    def __repr__(self):
+        return "<%s %r>" % (self.__class__.__name__, self.xmlFile)
+
+    def __init__(self, xmlFile):
+
+        self.items = []
+        self.xmlFile = xmlFile
+
+        # Read in XML
+        try:
+            tree = ElementTree(file=self.xmlFile)
+        except ExpatError, e:
+            log.error("Unable to parse file '%s' because: %s" % (self.xmlFile, e,), raiseException=RuntimeError)
+
+        # Verify that top-level element is correct
+        proxies_node = tree.getroot()
+        if proxies_node.tag != ELEMENT_PROXIES:
+            log.error("Ignoring file '%s' because it is not a proxies file" % (self.xmlFile,), raiseException=RuntimeError)
+
+        self._parseXML(proxies_node)
+
+    def _parseXML(self, rootnode):
+        """
+        Parse the XML root node from the augments configuration document.
+        @param rootnode: the L{Element} to parse.
+        """
+        for child in rootnode.getchildren():
+            
+            if child.tag != ELEMENT_RECORD:
+                log.error("Unknown augment type: '%s' in augment file: '%s'" % (child.tag, self.xmlFile,), raiseException=RuntimeError)
+
+            repeat = int(child.get(ATTRIBUTE_REPEAT, "1"))
+
+            guid = None
+            write_proxies = set()
+            read_proxies = set()
+            for node in child.getchildren():
+                
+                if node.tag == ELEMENT_GUID:
+                    guid = node.text
+
+                elif node.tag in (
+                    ELEMENT_PROXIES,
+                    ELEMENT_READ_ONLY_PROXIES,
+                ):
+                    self._parseMembers(node, write_proxies if node.tag == ELEMENT_PROXIES else read_proxies)
+                else:
+                    log.error("Invalid element '%s' in proxies file: '%s'" % (node.tag, self.xmlFile,), raiseException=RuntimeError)
+                    
+            # Must have at least a guid
+            if not guid:
+                log.error("Invalid record '%s' without a guid in proxies file: '%s'" % (child, self.xmlFile,), raiseException=RuntimeError)
+                
+            if repeat > 1:
+                for i in xrange(1, repeat+1):
+                    self._buildRecord(guid, write_proxies, read_proxies, i)
+            else:
+                self._buildRecord(guid, write_proxies, read_proxies)
+
+    def _parseMembers(self, node, addto):
+        for child in node.getchildren():
+            if child.tag == ELEMENT_MEMBER:
+                addto.add(child.text)
+    
+    def _buildRecord(self, guid, write_proxies, read_proxies, count=None):
+
+        def expandCount(value, count):
+            
+            if type(value) in types.StringTypes:
+                return value % (count,) if count and "%" in value else value
+            else:
+                return value
+        
+        guid = expandCount(guid, count)
+        write_proxies = set([expandCount(member, count) for member in write_proxies])
+        read_proxies = set([expandCount(member, count) for member in read_proxies])
+            
+        self.items.append((guid, write_proxies, read_proxies,))
+
+    @inlineCallbacks
+    def updateProxyDB(self):
+        
+        db = CalendarUserProxyDatabase(config.DataRoot)
+        for item in self.items:
+            guid, write_proxies, read_proxies = item
+            for proxy in write_proxies:
+                yield db.setGroupMembers("%s#%s" % (guid, "calendar-proxy-write"), (proxy,))
+            for proxy in read_proxies:
+                yield db.setGroupMembers("%s#%s" % (guid, "calendar-proxy-read"), (proxy,))

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -298,11 +298,8 @@
 
     def __init__(
         self, service, recordType, guid,
-        enabled=False, hostedAt="",
         shortNames=(), authIDs=set(), fullName=None,
         firstName=None, lastName=None, emailAddresses=set(),
-        enabledForCalendaring=False,
-        calendarUserAddresses=set(),
         uid=None,
     ):
         assert service.realmName is not None
@@ -315,29 +312,21 @@
         if uid is None:
             uid = guid
 
-        if enabledForCalendaring and recordType == service.recordType_groups:
-            raise AssertionError("Groups may not be enabled for calendaring")
-
-        if enabledForCalendaring:
-            calendarUserAddresses = set(calendarUserAddresses)
-            calendarUserAddresses.add("urn:uuid:%s" % (guid,))
-        else:
-            assert len(calendarUserAddresses) == 0
-
         self.service               = service
         self.recordType            = recordType
         self.guid                  = guid
         self.uid                   = uid
-        self.enabled               = enabled
-        self.hostedAt              = hostedAt
+        self.enabled               = False
+        self.hostedAt              = ""
         self.shortNames            = shortNames
         self.authIDs               = authIDs
         self.fullName              = fullName
         self.firstName             = firstName
         self.lastName              = lastName
         self.emailAddresses        = emailAddresses
-        self.enabledForCalendaring = enabledForCalendaring
-        self.calendarUserAddresses = calendarUserAddresses
+        self.enabledForCalendaring = False
+        self.autoSchedule          = False
+        self.calendarUserAddresses = set()
 
     def __cmp__(self, other):
         if not isinstance(other, DirectoryRecord):
@@ -357,6 +346,31 @@
 
         return h
 
+    def addAugmentInformation(self, augment):
+        
+        if augment:
+            self.enabled = augment.enabled
+            self.hostedAt = augment.hostedAt
+            self.enabledForCalendaring = augment.enabledForCalendaring
+            self.autoSchedule = augment.autoSchedule
+            self.calendarUserAddresses = set(augment.calendarUserAddresses)
+
+            if self.enabledForCalendaring and self.recordType == self.service.recordType_groups:
+                raise AssertionError("Groups may not be enabled for calendaring")
+    
+            if self.enabledForCalendaring:
+                for email in self.emailAddresses:
+                    self.calendarUserAddresses.add("mailto:%s" % (email.lower(),))
+                self.calendarUserAddresses.add("urn:uuid:%s" % (self.guid,))
+            else:
+                assert len(self.calendarUserAddresses) == 0
+
+        else:
+            self.enabled = False
+            self.hostedAt = ""
+            self.enabledForCalendaring = False
+            self.calendarUserAddresses = set()
+
     def members(self):
         return ()
 

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -50,7 +50,6 @@
 from twistedcaldav.cache import DisabledCacheNotifier, PropfindCacheMixin
 
 from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
-from twistedcaldav.directory.resourceinfo import ResourceInfoDatabase
 from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyPrincipalResource
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
 from twistedcaldav.directory.util import NotFilePath
@@ -61,7 +60,6 @@
 from twistedcaldav import caldavxml, customxml
 from twistedcaldav.customxml import calendarserver_namespace
 from twistedcaldav.directory.wiki import getWikiACL
-from twistedcaldav.partitions import partitions
 from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
 
 log = Logger()
@@ -764,39 +762,11 @@
     ##
 
     def setAutoSchedule(self, autoSchedule):
-        self._resource_info_index().setAutoSchedule(self.record.guid, autoSchedule)
+        self.record.autoSchedule = autoSchedule
 
-    @inlineCallbacks
     def getAutoSchedule(self):
-        value = (yield self._resource_info_index().getAutoSchedule(self.record.guid))
-        if value is None:
-            # No value has been explicitly set yet.  If this is a user/group
-            # the default should be False.  If resource/location, True.
-            if self.record.recordType in (DirectoryService.recordType_locations,
-                DirectoryService.recordType_resources):
-                yield self.setAutoSchedule(True)
-                returnValue(True)
-            else:
-                yield self.setAutoSchedule(False)
-                returnValue(False)
-        else:
-            returnValue(value)
+        return self.record.autoSchedule
 
-
-    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
-        if not hasattr(self.pcollection, "resource_info_db"):
-            setattr(self.pcollection, "resource_info_db", ResourceInfoDatabase(config.DataRoot))
-        return self.pcollection.resource_info_db
-
-
     ##
     # Static
     ##

Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sqldb.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sqldb.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sqldb.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,368 +0,0 @@
-##
-# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-SQL (sqlite) based user/group/resource directory service implementation.
-"""
-
-"""
-SCHEMA:
-
-User Database:
-
-ROW: RECORD_TYPE, SHORT_NAME (unique), PASSWORD, NAME
-
-Group Database:
-
-ROW: SHORT_NAME, MEMBER_SHORT_NAME
-
-CUAddress database:
-
-ROW: ADDRESS (unqiue), SHORT_NAME
-
-"""
-
-__all__ = [
-    "SQLDirectoryService",
-]
-
-from twisted.cred.credentials import UsernamePassword
-from twisted.python.filepath import FilePath
-
-from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
-from twistedcaldav.directory.xmlaccountsparser import XMLAccountsParser
-from twistedcaldav.sql import AbstractSQLDatabase
-from twistedcaldav.sql import db_prefix
-
-import os
-
-class SQLDirectoryManager(AbstractSQLDatabase):
-    """
-    House keeping operations on the SQL DB, including loading from XML file,
-    and record dumping. This can be used as a standalong DB management tool.
-    """
-    dbType = "DIRECTORYSERVICE"
-    dbFilename = db_prefix + "accounts"
-    dbFormatVersion = "3"
-
-    def __init__(self, path):
-        path = os.path.join(path, SQLDirectoryManager.dbFilename)
-        super(SQLDirectoryManager, self).__init__(path, True)
-
-    def loadFromXML(self, xmlFile):
-        parser = XMLAccountsParser(xmlFile)
-       
-        # Totally wipe existing DB and start from scratch
-        if os.path.exists(self.dbpath):
-            os.remove(self.dbpath)
-
-        self._db_execute("insert into SERVICE (REALM) values (:1)", parser.realm)
-
-        # Now add records to db
-        for item in parser.items.values():
-            for entry in item.itervalues():
-                self._add_to_db(entry)
-        self._db_commit()
-
-    def getRealm(self):
-        for realm in self._db_execute("select REALM from SERVICE"):
-            return realm[0].decode("utf-8")
-        else:
-            return ""
-
-    def listRecords(self, recordType):
-        # Get each account record
-        for shortName, guid, password, name in self._db_execute(
-            """
-            select SHORT_NAME, GUID, PASSWORD, NAME
-              from ACCOUNTS
-             where RECORD_TYPE = :1
-            """, recordType
-        ):
-            # See if we have members
-            members = self.members(shortName)
-                
-            # See if we are a member of any groups
-            groups = self.groups(shortName)
-                
-            # Get calendar user addresses
-            calendarUserAddresses = self.calendarUserAddresses(shortName)
-            
-            yield shortName, guid, password, name, members, groups, calendarUserAddresses
-
-    def getRecord(self, recordType, shortName):
-        # Get individual account record
-        for shortName, guid, password, name in self._db_execute(
-            """
-            select SHORT_NAME, GUID, PASSWORD, NAME
-              from ACCOUNTS
-             where RECORD_TYPE = :1
-               and SHORT_NAME  = :2
-            """, recordType, shortName
-        ):
-            break
-        else:
-            return None
-        
-        # See if we have members
-        members = self.members(shortName)
-            
-        # See if we are a member of any groups
-        groups = self.groups(shortName)
-            
-        # Get calendar user addresses
-        calendarUserAddresses = self.calendarUserAddresses(shortName)
-        
-        return shortName, guid, password, name, members, groups, calendarUserAddresses
-            
-    def members(self, shortName):
-        members = set()
-        for member in self._db_execute(
-            """
-            select MEMBER_RECORD_TYPE, MEMBER_SHORT_NAME
-              from GROUPS
-             where SHORT_NAME = :1
-            """, shortName
-        ):
-            members.add(tuple(member))
-        return members
-
-    def groups(self, shortName):
-        groups = set()
-        for (name,) in self._db_execute(
-            """
-            select SHORT_NAME
-              from GROUPS
-             where MEMBER_SHORT_NAME = :1
-            """, shortName
-        ):
-            groups.add(name)
-        return groups
-
-    def calendarUserAddresses(self, shortName):
-        calendarUserAddresses = set()
-        for (address,) in self._db_execute(
-            """
-            select ADDRESS
-              from ADDRESSES
-             where SHORT_NAME = :1
-            """, shortName
-        ):
-            calendarUserAddresses.add(address)
-        return calendarUserAddresses
-
-    def _add_to_db(self, record):
-        # Do regular account entry
-        recordType = record.recordType
-        shortName = record.shortNames[0]
-        guid = record.guid
-        password = record.password
-        name = record.fullName
-
-        self._db_execute(
-            """
-            insert into ACCOUNTS (RECORD_TYPE, SHORT_NAME, GUID, PASSWORD, NAME)
-            values (:1, :2, :3, :4, :5)
-            """, recordType, shortName, guid, password, name
-        )
-        
-        # Check for members
-        for memberRecordType, memberShortName in record.members:
-            self._db_execute(
-                """
-                insert into GROUPS (SHORT_NAME, MEMBER_RECORD_TYPE, MEMBER_SHORT_NAME)
-                values (:1, :2, :3)
-                """, shortName, memberRecordType, memberShortName
-            )
-                
-        # CUAddress
-        for cuaddr in record.calendarUserAddresses:
-            self._db_execute(
-                """
-                insert into ADDRESSES (ADDRESS, SHORT_NAME)
-                values (:1, :2)
-                """, cuaddr, shortName
-            )
-       
-    def _delete_from_db(self, shortName):
-        """
-        Deletes the specified entry from all dbs.
-        @param name: the name of the resource to delete.
-        @param shortName: the short name of the resource to delete.
-        """
-        self._db_execute("delete from ACCOUNTS  where SHORT_NAME        = :1", shortName)
-        self._db_execute("delete from GROUPS    where SHORT_NAME        = :1", shortName)
-        self._db_execute("delete from GROUPS    where MEMBER_SHORT_NAME = :1", shortName)
-        self._db_execute("delete from ADDRESSES where SHORT_NAME        = :1", shortName)
-    
-    def _db_version(self):
-        """
-        @return: the schema version assigned to this index.
-        """
-        return SQLDirectoryManager.dbFormatVersion
-        
-    def _db_type(self):
-        """
-        @return: the collection type assigned to this index.
-        """
-        return SQLDirectoryManager.dbType
-        
-    def _db_init_data_tables(self, q):
-        """
-        Initialise the underlying database tables.
-        @param q:           a database cursor to use.
-        """
-        #
-        # SERVICE table
-        #
-        q.execute("create table SERVICE (REALM text)")
-
-        #
-        # ACCOUNTS table
-        #
-        q.execute(
-            """
-            create table ACCOUNTS (
-                RECORD_TYPE  text,
-                SHORT_NAME   text,
-                GUID         text,
-                PASSWORD     text,
-                NAME         text
-            )
-            """
-        )
-
-        #
-        # GROUPS table
-        #
-        q.execute(
-            """
-            create table GROUPS (
-                SHORT_NAME          text,
-                MEMBER_RECORD_TYPE  text,
-                MEMBER_SHORT_NAME   text
-            )
-            """
-        )
-
-        #
-        # ADDRESSES table
-        #
-        q.execute(
-            """
-            create table ADDRESSES (
-                ADDRESS     text unique,
-                SHORT_NAME  text
-            )
-            """
-        )
-
-class SQLDirectoryService(DirectoryService):
-    """
-    XML based implementation of L{IDirectoryService}.
-    """
-    baseGUID = "8256E464-35E0-4DBB-A99C-F0E30C231675"
-    realmName = None
-
-    def __repr__(self):
-        return "<%s %r: %r>" % (self.__class__.__name__, self.realmName, self.manager.dbpath)
-
-    def __init__(self, dbParentPath, xmlFile=None):
-        super(SQLDirectoryService, self).__init__()
-
-        if type(dbParentPath) is str:
-            dbParentPath = FilePath(dbParentPath)
-            
-        self.manager = SQLDirectoryManager(dbParentPath.path)
-        if xmlFile:
-            self.manager.loadFromXML(xmlFile)
-        self.realmName = self.manager.getRealm()
-
-    def recordTypes(self):
-        recordTypes = (
-            DirectoryService.recordType_users,
-            DirectoryService.recordType_groups,
-            DirectoryService.recordType_locations,
-            DirectoryService.recordType_resources,
-        )
-        return recordTypes
-
-    def listRecords(self, recordType):
-        for result in self.manager.listRecords(recordType):
-            yield SQLDirectoryRecord(
-                service               = self,
-                recordType            = recordType,
-                shortName             = result[0],
-                guid                  = result[1],
-                password              = result[2],
-                name                  = result[3],
-                members               = result[4],
-                groups                = result[5],
-                calendarUserAddresses = result[6],
-            )
-
-    def recordWithShortName(self, recordType, shortName):
-        result = self.manager.getRecord(recordType, shortName)
-        if result:
-            return SQLDirectoryRecord(
-                service               = self,
-                recordType            = recordType,
-                shortName             = result[0],
-                guid                  = result[1],
-                password              = result[2],
-                name                  = result[3],
-                members               = result[4],
-                groups                = result[5],
-                calendarUserAddresses = result[6],
-            )
-
-        return None
-
-class SQLDirectoryRecord(DirectoryRecord):
-    """
-    XML based implementation implementation of L{IDirectoryRecord}.
-    """
-    def __init__(self, service, recordType, shortName, guid, password, name, members, groups, calendarUserAddresses):
-        super(SQLDirectoryRecord, self).__init__(
-            service               = service,
-            recordType            = recordType,
-            guid                  = guid,
-            shortNames            = (shortName,),
-            fullName              = name,
-            calendarUserAddresses = calendarUserAddresses,
-        )
-
-        self.password = password
-        self._members = members
-        self._groups  = groups
-
-    def members(self):
-        for recordType, shortName in self._members:
-            yield self.service.recordWithShortName(recordType, shortName)
-
-    def groups(self):
-        for shortName in self._groups:
-            yield self.service.recordWithShortName(DirectoryService.recordType_groups, shortName)
-
-    def verifyCredentials(self, credentials):
-        if isinstance(credentials, UsernamePassword):
-            return credentials.password == self.password
-
-        return super(SQLDirectoryRecord, self).verifyCredentials(credentials)
-
-if __name__ == '__main__':
-    mgr = SQLDirectoryManager("./")
-    mgr.loadFromXML("test/accounts.xml")

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sudo.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sudo.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/sudo.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -127,11 +127,12 @@
             guid=None,
             shortNames=(shortName,),
             fullName=shortName,
-            enabledForCalendaring=False,
         )
 
         self.password = entry['password']
 
+        self.enabled = True     # Explicitly enabled
+
     def verifyCredentials(self, credentials):
         if IUsernamePassword.providedBy(credentials):
             return credentials.checkPassword(self.password)

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -23,54 +23,40 @@
     <uid>admin</uid>
     <guid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</guid>
     <password>nimda</password>
-    <enable>true</enable>
     <name>Administrators</name>
   </user>
   <user>
     <uid>wsanchez</uid>
     <guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
     <password>zehcnasw</password>
-    <enable>true</enable>
     <name>Wilfredo Sanchez</name>
     <email-address>wsanchez at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:wsanchez at example.com</cuaddr>
   </user>
   <user>
     <uid>cdaboo</uid>
     <guid>5A985493-EE2C-4665-94CF-4DFEA3A89500</guid>
     <password>oobadc</password>
-    <enable>true</enable>
     <name>Cyrus Daboo</name>
     <email-address>cdaboo at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:cdaboo at example.com</cuaddr>
   </user>
   <user>
     <uid>lecroy</uid>
     <guid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</guid>
     <password>yorcel</password>
-    <enable>true</enable>
     <name>Chris Lecroy</name>
     <email-address>lecroy at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:lecroy at example.com</cuaddr>
   </user>
   <user>
     <uid>dreid</uid>
     <guid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
     <password>dierd</password>
-    <enable>true</enable>
     <name>David Reid</name>
     <email-address>dreid at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:dreid at example.com</cuaddr>
   </user>
   <user>
     <uid>nocalendar</uid>
     <guid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</guid>
     <password>radnelacon</password>
-    <enable>true</enable>
     <name>No Calendar</name>
     <email-address>nocalendar at example.com</email-address>
   </user>
@@ -78,15 +64,12 @@
     <uid>user%02d</uid>
     <guid>user%02d</guid>
     <password>%02duser</password>
-    <enable>true</enable>
     <name>User %02d</name>
-    <enable-calendar>true</enable-calendar>
   </user>
   <group>
     <uid>managers</uid>
     <guid>9FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
     <password>managers</password>
-    <enable>true</enable>
     <name>Managers</name>
     <members>
       <member type="users">lecroy</member>
@@ -96,7 +79,6 @@
     <uid>admin</uid>
     <guid>admin</guid>
     <password>admin</password>
-    <enable>true</enable>
     <name>Administrators</name>
     <members>
       <member type="groups">managers</member>
@@ -106,7 +88,6 @@
     <uid>grunts</uid>
     <guid>grunts</guid>
     <password>grunts</password>
-    <enable>true</enable>
     <name>We do all the work</name>
     <members>
       <member>wsanchez</member>
@@ -118,7 +99,6 @@
     <uid>right_coast</uid>
     <guid>right_coast</guid>
     <password>right_coast</password>
-    <enable>true</enable>
     <name>East Coast</name>
     <members>
       <member>cdaboo</member>
@@ -128,7 +108,6 @@
     <uid>left_coast</uid>
     <guid>left_coast</guid>
     <password>left_coast</password>
-    <enable>true</enable>
     <name>West Coast</name>
     <members>
       <member>wsanchez</member>
@@ -140,7 +119,6 @@
     <uid>both_coasts</uid>
     <guid>both_coasts</guid>
     <password>both_coasts</password>
-    <enable>true</enable>
     <name>Both Coasts</name>
     <members>
       <member type="groups">right_coast</member>
@@ -151,7 +129,6 @@
     <uid>recursive1_coasts</uid>
     <guid>recursive1_coasts</guid>
     <password>recursive1_coasts</password>
-    <enable>true</enable>
     <name>Recursive1 Coasts</name>
     <members>
       <member type="groups">recursive2_coasts</member>
@@ -162,7 +139,6 @@
     <uid>recursive2_coasts</uid>
     <guid>recursive2_coasts</guid>
     <password>recursive2_coasts</password>
-    <enable>true</enable>
     <name>Recursive2 Coasts</name>
     <members>
       <member type="groups">recursive1_coasts</member>
@@ -173,7 +149,6 @@
     <uid>non_calendar_group</uid>
     <guid>non_calendar_group</guid>
     <password>non_calendar_group</password>
-    <enable>true</enable>
     <name>Non-calendar group</name>
     <members>
       <member>cdaboo</member>
@@ -184,89 +159,49 @@
     <uid>mercury</uid>
     <guid>mercury</guid>
     <password>mercury</password>
-    <enable>true</enable>
     <name>Mecury Seven</name>
     <email-address>mercury at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:mercury at example.com</cuaddr>
-    <proxies>
-      <member type="groups">left_coast</member>
-    </proxies>
   </location>
   <location>
     <uid>gemini</uid>
     <guid>gemini</guid>
     <password>gemini</password>
-    <enable>true</enable>
     <name>Gemini Twelve</name>
     <email-address>gemini at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:gemini at example.com</cuaddr>
-    <auto-schedule>true</auto-schedule>
-    <proxies>
-      <member>wsanchez</member>
-    </proxies>
   </location>
   <location>
     <uid>apollo</uid>
     <guid>apollo</guid>
     <password>apollo</password>
-    <enable>true</enable>
     <name>Apollo Eleven</name>
     <email-address>apollo at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:apollo at example.com</cuaddr>
-    <proxies>
-      <member type="groups">both_coasts</member>
-    </proxies>
   </location>
   <location>
     <uid>orion</uid>
     <guid>orion</guid>
     <password>orion</password>
-    <enable>true</enable>
     <name>Orion</name>
     <email-address>orion at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:orion at example.com</cuaddr>
-    <proxies>
-      <member type="groups">recursive1_coasts</member>
-    </proxies>
   </location>
   <resource>
     <uid>transporter</uid>
     <guid>transporter</guid>
     <password>transporter</password>
-    <enable>true</enable>
     <name>Mass Transporter</name>
     <email-address>transporter at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:transporter at example.com</cuaddr>
   </resource>
   <resource>
     <uid>ftlcpu</uid>
     <guid>ftlcpu</guid>
     <password>ftlcpu</password>
-    <enable>true</enable>
     <name>Faster-Than-Light Microprocessor</name>
     <email-address>ftlcpu at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:ftlcpu at example.com</cuaddr>
   </resource>
   <resource>
     <uid>non_calendar_proxy</uid>
     <guid>non_calendar_proxy</guid>
     <password>non_calendar_proxy</password>
-    <enable>true</enable>
     <name>Non-calendar proxy</name>
     <email-address>non_calendar_proxy at example.com</email-address>
-    <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:non_calendar_proxy at example.com</cuaddr>
-    <proxies>
-      <member type="groups">non_calendar_group</member>
-    </proxies>
-    <read-only-proxies>
-      <member type="groups">recursive2_coasts</member>
-    </read-only-proxies>
   </resource>
 </accounts>

Copied: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments-test.xml (from rev 4485, CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments.xml)
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments-test.xml	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments-test.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2009 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<!DOCTYPE accounts SYSTEM "../../../conf/auth/augments.dtd">
+
+<augments>
+  <record>
+    <guid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <cuaddr>mailto:wsanchez at example.com</cuaddr>
+  </record>
+  <record>
+    <guid>5A985493-EE2C-4665-94CF-4DFEA3A89500</guid>
+    <enable>false</enable>
+  </record>
+  <record>
+    <guid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</guid>
+    <enable>true</enable>
+    <enable-calendar>false</enable-calendar>
+  </record>
+  <record>
+    <guid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
+    <enable>true</enable>
+    <hosted-at>00001</hosted-at>
+  </record>
+  <record>
+    <guid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</guid>
+    <enable>true</enable>
+    <hosted-at>00002</hosted-at>
+  </record>
+  <record>
+    <guid>6A73326A-F781-47E7-A9F8-AF47364D4152</guid>
+    <enable>true</enable>
+    <hosted-at>00002</hosted-at>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <auto-schedule>true</auto-schedule>
+    <cuaddr>mailto:usera at example.com</cuaddr>
+    <cuaddr>mailto:user.a at example.com</cuaddr>
+    <cuaddr>mailto:user_a at example.com</cuaddr>
+  </record>
+</augments>

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments.xml	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/augments.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-Copyright (c) 2009 Apple Inc. All rights reserved.
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -16,47 +16,113 @@
 limitations under the License.
  -->
 
-<!DOCTYPE accounts SYSTEM "../../../conf/auth/accounts.dtd">
+<!DOCTYPE augments SYSTEM "../../../conf/auth/augments.dtd">
 
-<accounts realm="Test">
-  <user>
+<augments realm="Test">
+  <record>
     <guid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</guid>
     <enable>true</enable>
-  </user>
-  <user>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
     <guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
     <enable>true</enable>
     <enable-calendar>true</enable-calendar>
-    <cuaddr>mailto:wsanchez at example.com</cuaddr>
-  </user>
-  <user>
+  </record>
+  <record>
     <guid>5A985493-EE2C-4665-94CF-4DFEA3A89500</guid>
-    <enable>false</enable>
-  </user>
-  <user>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
     <guid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</guid>
     <enable>true</enable>
-    <enable-calendar>false</enable-calendar>
-  </user>
-  <user>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
     <guid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
     <enable>true</enable>
-    <hosted-at>00001</hosted-at>
-  </user>
-  <user>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
     <guid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</guid>
     <enable>true</enable>
-    <hosted-at>00002</hosted-at>
-  </user>
-  <user>
-    <guid>6A73326A-F781-47E7-A9F8-AF47364D4152</guid>
+    <enable-calendar>false</enable-calendar>
+  </record>
+  <record repeat="2">
+    <guid>user%02d</guid>
     <enable>true</enable>
-    <hosted-at>00002</hosted-at>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
+    <guid>9FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
     <enable>true</enable>
+  </record>
+  <record>
+    <guid>admin</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>grunts</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>right_coast</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>left_coast</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>both_coasts</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>recursive1_coasts</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>recursive2_coasts</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>non_calendar_group</guid>
+    <enable>true</enable>
+  </record>
+  <record>
+    <guid>mercury</guid>
+    <enable>true</enable>
     <enable-calendar>true</enable-calendar>
-    <auto-schedule>true</auto-schedule>
-    <cuaddr>mailto:usera at example.com</cuaddr>
-    <cuaddr>mailto:user.a at example.com</cuaddr>
-    <cuaddr>mailto:user_a at example.com</cuaddr>
-  </user>
-</accounts>
+  </record>
+  <record>
+    <guid>gemini</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
+    <guid>apollo</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
+    <guid>orion</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
+    <guid>transporter</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
+    <guid>ftlcpu</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+  <record>
+    <guid>non_calendar_proxy</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+  </record>
+</augments>

Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/basic
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/basic	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/basic	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,4 +0,0 @@
-wsanchez:Cytm0Bwm7CPJs
-cdaboo:I.Ef5FJl5GVh2
-dreid:LVhqAv4qSrYPs
-lecroy:/7/5VDrkrLxY.

Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/digest
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/digest	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/digest	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,4 +0,0 @@
-wsanchez:Test:decbe233ab3d997cacc2fc058b19db8c
-cdaboo:Test:61164bf3d607d072fe8a7ac420b24aac
-dreid:Test:8ee67801004b2752f72b84e7064889a6
-lecroy:Test:60d4feb424430953be045738041e51be

Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/groups
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/groups	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/groups	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,4 +0,0 @@
-managers: lecroy
-grunts: wsanchez, cdaboo, dreid
-right_coast: cdaboo
-left_coast: wsanchez, dreid, lecroy

Added: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/proxies.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/proxies.xml	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/proxies.xml	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<!DOCTYPE proxies SYSTEM "proxies.dtd">
+
+<proxies>
+  <record>
+    <guid>mercury</guid>
+    <proxies>
+      <member>left_coast</member>
+    </proxies>
+  </record>
+  <record>
+    <guid>gemini</guid>
+    <proxies>
+      <member>6423F94A-6B76-4A3A-815B-D52CFD77935D</member>
+    </proxies>
+  </record>
+  <record>
+    <guid>apollo</guid>
+    <proxies>
+      <member>both_coasts</member>
+    </proxies>
+  </record>
+  <record>
+    <guid>orion</guid>
+    <proxies>
+      <member>recursive1_coasts</member>
+    </proxies>
+  </record>
+  <record>
+    <guid>non_calendar_proxy</guid>
+    <proxies>
+      <member>non_calendar_group</member>
+    </proxies>
+    <read-only-proxies>
+      <member>recursive2_coasts</member>
+    </read-only-proxies>
+  </record>
+</proxies>

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_aggregate.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_aggregate.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_aggregate.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,20 +14,18 @@
 # limitations under the License.
 ##
 
-from twistedcaldav.directory.apache import BasicDirectoryService
 from twistedcaldav.directory.xmlfile import XMLDirectoryService
 from twistedcaldav.directory.aggregate import AggregateDirectoryService
 
-from twistedcaldav.directory.test.test_apache import digestRealm, basicUserFile, groupFile
-from twistedcaldav.directory.test.test_xmlfile import xmlFile
+from twistedcaldav.directory.test.test_xmlfile import xmlFile, augmentsFile
 
 import twistedcaldav.directory.test.util
+from twistedcaldav.directory import augment
 
 apache_prefix = "apache:"
 xml_prefix = "xml:"
 
 testServices = (
-    (apache_prefix, twistedcaldav.directory.test.test_apache.Apache  ),
     (xml_prefix   , twistedcaldav.directory.test.test_xmlfile.XMLFile),
 )
 
@@ -65,16 +63,9 @@
         """
         Returns an IDirectoryService.
         """
-        apacheService = BasicDirectoryService(
-            {
-                'realmName' : digestRealm,
-                'userFile' : basicUserFile,
-                'groupFile' : groupFile,
-            }
-        )
-        apacheService.recordTypePrefix = apache_prefix
-
         xmlService = XMLDirectoryService({'xmlFile' : xmlFile})
         xmlService.recordTypePrefix = xml_prefix
 
-        return AggregateDirectoryService((apacheService, xmlService))
+        augment.AugmentService = augment.AugmentXMLDB(xmlFiles=(augmentsFile.path,))
+
+        return AggregateDirectoryService((xmlService,))

Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_apache.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_apache.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_apache.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,128 +0,0 @@
-##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import os
-
-from twisted.python.filepath import FilePath
-
-import twistedcaldav.directory.test.util
-from twistedcaldav.directory.apache import BasicDirectoryService, DigestDirectoryService
-from twistedcaldav.directory.directory import DirectoryService
-
-digestRealm = "Test"
-
-basicUserFile  = FilePath(os.path.join(os.path.dirname(__file__), "basic"))
-digestUserFile = FilePath(os.path.join(os.path.dirname(__file__), "digest"))
-groupFile      = FilePath(os.path.join(os.path.dirname(__file__), "groups"))
-
-# FIXME: Add tests for GUID hooey, once we figure out what that means here
-
-class Apache (object):
-    recordTypes = set((
-        DirectoryService.recordType_users,
-        DirectoryService.recordType_groups
-    ))
-
-    users = {
-        "wsanchez": { "password": "foo",  "guid": None, "addresses": () },
-        "cdaboo"  : { "password": "bar",  "guid": None, "addresses": () },
-        "dreid"   : { "password": "baz",  "guid": None, "addresses": () },
-        "lecroy"  : { "password": "quux", "guid": None, "addresses": () },
-    }
-
-    groups = {
-        "managers"   : { "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users, "lecroy"),)                                         },
-        "grunts"     : { "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users, "wsanchez"),
-                                                                    (DirectoryService.recordType_users, "cdaboo"),
-                                                                    (DirectoryService.recordType_users, "dreid")) },
-        "right_coast": { "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users, "cdaboo"),)                                         },
-        "left_coast" : { "guid": None, "addresses": (), "members": ((DirectoryService.recordType_users, "wsanchez"),
-                                                                    (DirectoryService.recordType_users, "dreid"),
-                                                                    (DirectoryService.recordType_users, "lecroy")) },
-    }
-
-    locations = {
-    }
-
-    resources = {
-    }
-
-    def service(self):
-        return self.serviceClass(
-            {
-                'realmName' : digestRealm,
-                'userFile' : self.userFile(),
-                'groupFile' : self.groupFile(),
-            }
-        )
-
-    userFileName = None
-
-    def userFile(self):
-        if not hasattr(self, "_userFile"):
-            if self.userFileName is None:
-                raise NotImplementedError("Test subclass needs to specify userFileName.")
-            self._userFile = FilePath(self.mktemp())
-            basicUserFile.copyTo(self._userFile)
-        return self._userFile
-
-    def groupFile(self):
-        if not hasattr(self, "_groupFile"):
-            self._groupFile = FilePath(self.mktemp())
-            groupFile.copyTo(self._groupFile)
-        return self._groupFile
-
-    def test_changedGroupFile(self):
-        self.groupFile().open("w").write("grunts: wsanchez\n")
-        self.assertEquals(self.recordNames(DirectoryService.recordType_groups), set(("grunts",)))
-
-    def test_recordTypes_user(self):
-        """
-        IDirectoryService.recordTypes(userFile)
-        """
-        self.assertEquals(set(self.serviceClass({'realmName':digestRealm, 'userFile':self.userFile()}).recordTypes()), set((DirectoryService.recordType_users,)))
-
-    userEntry = None
-
-    def test_changedUserFile(self):
-        if self.userEntry is None:
-            raise NotImplementedError("Test subclass needs to specify userEntry.")
-        self.userFile().open("w").write(self.userEntry[1])
-        self.assertEquals(self.recordNames(DirectoryService.recordType_users), set((self.userEntry[0],)))
-
-class Basic (Apache, twistedcaldav.directory.test.util.BasicTestCase,
-    twistedcaldav.directory.test.util.NonCachingTestCase):
-    """
-    Test Apache-Compatible UserFile/GroupFile directory implementation.
-    """
-    serviceClass = BasicDirectoryService
-
-    userFileName = basicUserFile
-    userEntry = ("wsanchez", "wsanchez:Cytm0Bwm7CPJs\n")
-
-class Digest (Apache, twistedcaldav.directory.test.util.DigestTestCase,
-    twistedcaldav.directory.test.util.NonCachingTestCase):
-    """
-    Test Apache-Compatible DigestFile/GroupFile directory implementation.
-    """
-    serviceClass = DigestDirectoryService
-
-    userFileName = digestUserFile
-    userEntry = ("wsanchez", "wsanchez:Test:decbe233ab3d997cacc2fc058b19db8c\n")
-
-    def test_verifyCredentials_digest(self):
-        raise NotImplementedError() # Use super's implementation
-    test_verifyCredentials_digest.todo = "unimplemented"

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_augment.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_augment.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_augment.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -16,11 +16,12 @@
 
 from twistedcaldav.test.util import TestCase
 from twistedcaldav.directory.augment import AugmentXMLDB, AugmentSqliteDB
-from twisted.python.filepath import FilePath
 from twisted.internet.defer import inlineCallbacks
+from twistedcaldav.directory.xmlaugmentsparser import XMLAugmentsParser
+import cStringIO
 import os
 
-xmlFile = FilePath(os.path.join(os.path.dirname(__file__), "augments.xml"))
+xmlFile = os.path.join(os.path.dirname(__file__), "augments-test.xml")
 
 testRecords = (
     {"guid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "enabled":True,  "hostedAt":"", "enabledForCalendaring":False, "autoSchedule":False, "calendarUserAddresses":set()},
@@ -54,13 +55,42 @@
     @inlineCallbacks
     def test_read(self):
         
-        db = AugmentXMLDB(xmlFile)
+        db = AugmentXMLDB((xmlFile,))
 
         for item in testRecords:
             yield self._checkRecord(db, item)
 
         yield self._checkNoRecord(db, "D11F03A0-97EA-48AF-9A6C-FAC7F3975767")
 
+    def test_parseErrors(self):
+        
+        db = {}
+        self.assertRaises(RuntimeError, XMLAugmentsParser, cStringIO.StringIO(""), db)
+        self.assertRaises(RuntimeError, XMLAugmentsParser, cStringIO.StringIO("""<?xml version="1.0" encoding="utf-8"?>
+<accounts>
+    <foo/>
+</accounts>
+"""), db)
+        self.assertRaises(RuntimeError, XMLAugmentsParser, cStringIO.StringIO("""<?xml version="1.0" encoding="utf-8"?>
+<augments>
+    <foo/>
+</augments>
+"""), db)
+        self.assertRaises(RuntimeError, XMLAugmentsParser, cStringIO.StringIO("""<?xml version="1.0" encoding="utf-8"?>
+<augments>
+  <record>
+    <enable>true</enable>
+  </record>
+</augments>
+"""), db)
+        self.assertRaises(RuntimeError, XMLAugmentsParser, cStringIO.StringIO("""<?xml version="1.0" encoding="utf-8"?>
+  <record>
+    <guid>admin</guid>
+    <enable>true</enable>
+    <foo/>
+  </record>
+"""), db)
+
 class AugmentSqliteTests(AugmentTests):
 
     @inlineCallbacks
@@ -68,7 +98,7 @@
         
         db = AugmentSqliteDB(self.mktemp())
 
-        dbxml = AugmentXMLDB(xmlFile)
+        dbxml = AugmentXMLDB((xmlFile,))
         for record in dbxml.db.values():
             yield db.addAugmentRecord(record)
 

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_cachedirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_cachedirectory.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_cachedirectory.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -20,6 +20,7 @@
 from twistedcaldav.directory.directory import DirectoryService
 from twistedcaldav.directory.util import uuidFromName
 from uuid import uuid4
+from twistedcaldav.directory.augment import AugmentRecord
 
 class TestDirectoryService (CachingDirectoryService):
 
@@ -62,9 +63,17 @@
                         firstName             = "",
                         lastName              = "",
                         emailAddresses        = record.get("email"),
-                        calendarUserAddresses = record.get("cua"),
+                    ) 
+                    
+                    augmentRecord = AugmentRecord(
+                        guid = cacheRecord.guid,
+                        enabled=True,
                         enabledForCalendaring = True,
-                    ) 
+                        calendarUserAddresses = set(record.get("cua")),
+                    )
+                    
+                    cacheRecord.addAugmentInformation(augmentRecord)
+
                     self.recordCacheForType(recordType).addRecord(cacheRecord,
                         indexType, indexKey)
 

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_calendar.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_calendar.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_calendar.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -36,11 +36,11 @@
         super(ProvisionedCalendars, self).setUp()
         
         # Setup the initial directory
-        self.xmlfile = self.mktemp()
-        fd = open(self.xmlfile, "w")
+        self.xmlFile = self.mktemp()
+        fd = open(self.xmlFile, "w")
         fd.write(open(xmlFile.path, "r").read())
         fd.close()
-        self.directoryService = XMLDirectoryService({'xmlFile' : self.xmlfile})
+        self.directoryService = XMLDirectoryService({'xmlFile' : self.xmlFile})
         
         # Set up a principals hierarchy for each service we're testing with
         name = "principals"

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_guidchange.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_guidchange.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_guidchange.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -37,11 +37,11 @@
         super(ProvisionedPrincipals, self).setUp()
         
         # Setup the initial directory
-        self.xmlfile = self.mktemp()
-        fd = open(self.xmlfile, "w")
+        self.xmlFile = self.mktemp()
+        fd = open(self.xmlFile, "w")
         fd.write(open(xmlFile.path, "r").read())
         fd.close()
-        self.directoryService = XMLDirectoryService({'xmlFile' : self.xmlfile})
+        self.directoryService = XMLDirectoryService({'xmlFile' : self.xmlFile})
         
         # Set up a principals hierarchy for each service we're testing with
         name = "principals"
@@ -78,7 +78,7 @@
         
         def privs1(result):
             # Change GUID in record
-            fd = open(self.xmlfile, "w")
+            fd = open(self.xmlFile, "w")
             fd.write(open(xmlFile.path, "r").read().replace(oldUID, newUID))
             fd.close()
             fd = None

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectory.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectory.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -21,6 +21,7 @@
 else:
     import twisted.web2.auth.digest
     import twistedcaldav.directory.test.util
+    from twistedcaldav.directory import augment
     from twistedcaldav.directory.directory import DirectoryService
     from twistedcaldav.directory.appleopendirectory import OpenDirectoryRecord
     import dsattributes
@@ -52,6 +53,7 @@
         def setUp(self):
             super(OpenDirectory, self).setUp()
             self._service = OpenDirectoryService({'node' : "/Search"}, dosetup=False)
+            augment.AugmentService = augment.AugmentXMLDB(xmlFiles=())
 
         def tearDown(self):
             for call in self._service._delayedCalls:
@@ -72,8 +74,6 @@
                 firstName             = "Some",
                 lastName              = "User",
                 emailAddresses        = set(("someuser at example.com",)),
-                calendarUserAddresses = set(("mailtoguid at example.com",)),
-                enabledForCalendaring = True,
                 memberGUIDs           = [],
             )
 
@@ -94,8 +94,6 @@
                 firstName             = "Some",
                 lastName              = "User",
                 emailAddresses        = set(("someuser at example.com",)),
-                calendarUserAddresses = set(("mailtoguid at example.com",)),
-                enabledForCalendaring = True,
                 memberGUIDs           = [],
             )
 

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -25,11 +25,10 @@
 
 from twistedcaldav.static import CalendarHomeProvisioningFile
 from twistedcaldav.config import config
-from twistedcaldav.directory.apache import BasicDirectoryService, DigestDirectoryService
+from twistedcaldav.directory import augment
 from twistedcaldav.directory.directory import DirectoryService
-from twistedcaldav.directory.test.test_apache import basicUserFile, digestUserFile, groupFile, digestRealm
 from twistedcaldav.directory.xmlfile import XMLDirectoryService
-from twistedcaldav.directory.test.test_xmlfile import xmlFile
+from twistedcaldav.directory.test.test_xmlfile import xmlFile, augmentsFile
 from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
 from twistedcaldav.directory.principal import DirectoryPrincipalTypeProvisioningResource
 from twistedcaldav.directory.principal import DirectoryPrincipalResource
@@ -48,20 +47,6 @@
         super(ProvisionedPrincipals, self).setUp()
 
         self.directoryServices = (
-            BasicDirectoryService(
-                {
-                    'realmName' : digestRealm,
-                    'userFile' : basicUserFile,
-                    'groupFile' : groupFile,
-                }
-            ),
-            DigestDirectoryService(
-                {
-                    'realmName' : digestRealm,
-                    'userFile' : digestUserFile,
-                    'groupFile' : groupFile,
-                }
-            ),
             XMLDirectoryService(
                 {
                     'xmlFile' : xmlFile,
@@ -81,6 +66,8 @@
 
             self.principalRootResources[directory.__class__.__name__] = provisioningResource
 
+        augment.AugmentService = augment.AugmentXMLDB(xmlFiles=(augmentsFile.path,))
+
     def test_hierarchy(self):
         """
         DirectoryPrincipalProvisioningResource.listChildren(),
@@ -216,6 +203,7 @@
                     self.failIf(principal is not None)
 
         # Explicitly check the disabled record
+        provisioningResource = self.principalRootResources['XMLDirectoryService']
         self.failIf(provisioningResource.principalForCalendarUserAddress("mailto:nocalendar at example.com") is not None)
         self.failIf(provisioningResource.principalForCalendarUserAddress("urn:uuid:543D28BA-F74F-4D5F-9243-B3E3A61171E5") is not None)
         self.failIf(provisioningResource.principalForCalendarUserAddress("/principals/users/nocalendar/") is not None)
@@ -421,7 +409,7 @@
             def qname(self):
                 return self.ns, self.name
 
-        provisioningResource = self.principalRootResources['BasicDirectoryService']
+        provisioningResource = self.principalRootResources['XMLDirectoryService']
 
         expected = (
             ("DAV:", "displayname", "morgen", "fullName", "morgen"),

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -18,7 +18,8 @@
 from twisted.web2.dav import davxml
 
 from twistedcaldav.directory.directory import DirectoryService
-from twistedcaldav.directory.test.test_xmlfile import xmlFile
+from twistedcaldav.directory.test.test_xmlfile import xmlFile, augmentsFile,\
+    proxiesFile
 from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
 from twistedcaldav.directory.principal import DirectoryPrincipalResource
 from twistedcaldav.directory.xmlaccountsparser import XMLAccountsParser
@@ -26,16 +27,21 @@
 
 import twistedcaldav.test.util
 from twistedcaldav.config import config
+from twistedcaldav.directory import augment
+from twistedcaldav.directory.calendaruserproxyloader import XMLCalendarUserProxyLoader
+import os
 
-
 class ProxyPrincipals (twistedcaldav.test.util.TestCase):
     """
     Directory service provisioned principals.
     """
+    
+    @inlineCallbacks
     def setUp(self):
         super(ProxyPrincipals, self).setUp()
 
         self.directoryService = XMLDirectoryService({'xmlFile' : xmlFile})
+        augment.AugmentService = augment.AugmentXMLDB(xmlFiles=(augmentsFile.path,))
 
         # Set up a principals hierarchy for each service we're testing with
         self.principalRootResources = {}
@@ -48,6 +54,10 @@
 
         self.principalRootResources[self.directoryService.__class__.__name__] = provisioningResource
 
+        config.DataRoot = self.mktemp()
+        os.mkdir(config.DataRoot)
+        yield XMLCalendarUserProxyLoader(proxiesFile.path).updateProxyDB()
+
     def _getPrincipalByShortName(self, type, name):
         provisioningResource = self.principalRootResources[self.directoryService.__class__.__name__]
         return provisioningResource.principalForShortName(type, name)

Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_sqldb.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_sqldb.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_sqldb.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,51 +0,0 @@
-##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import os
-
-from twisted.python.filepath import FilePath
-
-#import twistedcaldav.directory.test.util
-#import twistedcaldav.directory.test.test_xmlfile
-#from twistedcaldav.directory.sqldb import SQLDirectoryService
-
-xmlFile = FilePath(os.path.join(os.path.dirname(__file__), "accounts.xml"))
-
-# FIXME: Add tests for GUID hooey, once we figure out what that means here
-
-# class SQLDB (
-#     twistedcaldav.directory.test.test_xmlfile.XMLFileBase,
-#     twistedcaldav.directory.test.util.BasicTestCase,
-#     twistedcaldav.directory.test.util.DigestTestCase
-# ):
-#     """
-#     Test SQL directory implementation.
-#     """
-#     def service(self):
-#         return SQLDirectoryService(os.getcwd(), self.xmlFile())
-# 
-#     def test_verifyCredentials_digest(self):
-#         super(SQLDB, self).test_verifyCredentials_digest()
-#     test_verifyCredentials_digest.todo = ""
-# 
-#     def test_verifyRealmFromDB(self):
-#         # Make sure the database has been initialized with the XML file
-#         self.service()
-# 
-#         # Then get an instance without using the XML file
-#         service = SQLDirectoryService(os.getcwd(), None)
-# 
-#         self.assertEquals(service.realmName, "Test")

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -17,16 +17,15 @@
 import os
 
 from twisted.python.filepath import FilePath
-from twisted.internet.defer import inlineCallbacks
 
-from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
+from twistedcaldav.directory import augment
 from twistedcaldav.directory.directory import DirectoryService
 import twistedcaldav.directory.test.util
 from twistedcaldav.directory.xmlfile import XMLDirectoryService
-from twistedcaldav.directory.resourceinfo import ResourceInfoDatabase
-from twistedcaldav.config import config
 
 xmlFile = FilePath(os.path.join(os.path.dirname(__file__), "accounts.xml"))
+augmentsFile = FilePath(os.path.join(os.path.dirname(__file__), "augments.xml"))
+proxiesFile = FilePath(os.path.join(os.path.dirname(__file__), "proxies.xml"))
 
 # FIXME: Add tests for GUID hooey, once we figure out what that means here
 
@@ -88,6 +87,12 @@
             xmlFile.copyTo(self._xmlFile)
         return self._xmlFile
 
+    def augmentsFile(self):
+        if not hasattr(self, "_augmentsFile"):
+            self._augmentsFile = FilePath(self.mktemp())
+            augmentsFile.copyTo(self._augmentsFile)
+        return self._augmentsFile
+
 class XMLFile (
     XMLFileBase,
     twistedcaldav.directory.test.util.BasicTestCase,
@@ -97,7 +102,9 @@
     Test XML file based directory implementation.
     """
     def service(self):
-        return XMLDirectoryService({'xmlFile' : self.xmlFile()}, alwaysStat=True)
+        directory = XMLDirectoryService({'xmlFile' : self.xmlFile()}, alwaysStat=True)
+        augment.AugmentService = augment.AugmentXMLDB(xmlFiles=(self.augmentsFile().path,))
+        return directory
 
     def test_changedXML(self):
         service = self.service()
@@ -110,7 +117,6 @@
     <uid>admin</uid>
     <guid>admin</guid>
     <password>nimda</password>
-    <enable>true</enable>
     <name>Super User</name>
   </user>
 </accounts>
@@ -131,7 +137,6 @@
                 set(expectedRecords)
             )
 
-    @inlineCallbacks
     def test_okAutoSchedule(self):
         service = self.service()
 
@@ -143,14 +148,26 @@
     <uid>my office</uid>
     <guid>myoffice</guid>
     <password>nimda</password>
-    <enable>true</enable>
     <name>Super User</name>
-    <enable-calendar>true</enable-calendar>
-    <auto-schedule>true</auto-schedule>
   </location>
 </accounts>
 """
         )
+        self.augmentsFile().open("w").write(
+"""<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE accounts SYSTEM "accounts.dtd">
+<augments>
+  <record>
+    <guid>myoffice</guid>
+    <enable>true</enable>
+    <enable-calendar>true</enable-calendar>
+    <auto-schedule>true</auto-schedule>
+  </record>
+</augments>
+"""
+        )
+        augment.AugmentService.refresh()
+
         for recordType, expectedRecords in (
             ( DirectoryService.recordType_users     , ()             ),
             ( DirectoryService.recordType_groups    , ()             ),
@@ -165,8 +182,7 @@
                 set(r.shortNames[0] for r in service.listRecords(recordType)),
                 set(expectedRecords)
             )
-        resourceInfoDatabase = ResourceInfoDatabase(config.DataRoot)
-        self.assertTrue((yield resourceInfoDatabase.getAutoSchedule(service.recordWithShortName(DirectoryService.recordType_locations, "my office").guid)))
+        self.assertTrue(service.recordWithShortName(DirectoryService.recordType_locations, "my office").autoSchedule)
 
 
     def test_okDisableCalendar(self):
@@ -179,18 +195,17 @@
   <group>
     <uid>enabled</uid>
     <password>enabled</password>
-    <enable>true</enable>
     <name>Enabled</name>
   </group>
   <group>
     <uid>disabled</uid>
     <password>disabled</password>
-    <enable>true</enable>
     <name>Disabled</name>
   </group>
 </accounts>
 """
         )
+        
         for recordType, expectedRecords in (
             ( DirectoryService.recordType_users     , ()                       ),
             ( DirectoryService.recordType_groups    , ("enabled", "disabled")  ),
@@ -210,54 +225,3 @@
         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()
-
-        self.xmlFile().open("w").write(
-"""<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE accounts SYSTEM "accounts.dtd">
-<accounts realm="Test Realm">
-  <user>
-    <uid>test</uid>
-    <guid>test</guid>
-    <password>nimda</password>
-    <enable>true</enable>
-    <name>Test</name>
-    <enable-calendar>true</enable-calendar>
-  </user>
-  <location>
-    <uid>my office</uid>
-    <guid>myoffice</guid>
-    <password>nimda</password>
-    <enable>true</enable>
-    <name>Super User</name>
-    <enable-calendar>true</enable-calendar>
-    <auto-schedule>true</auto-schedule>
-    <proxies>
-        <member>test</member>
-    </proxies>
-  </location>
-</accounts>
-"""
-        )
-        for recordType, expectedRecords in (
-            ( DirectoryService.recordType_users     , ("test",)      ),
-            ( DirectoryService.recordType_groups    , ()             ),
-            ( DirectoryService.recordType_locations , ("my office",) ),
-            ( DirectoryService.recordType_resources , ()             ),
-        ):
-            # Fault records in
-            for name in expectedRecords:
-                service.recordWithShortName(recordType, name)
-
-            self.assertEquals(
-                set(r.shortNames[0] for r in service.listRecords(recordType)),
-                set(expectedRecords)
-            )
-        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)
-

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -27,11 +27,8 @@
 
 from twisted.python.filepath import FilePath
 
-from twistedcaldav.config import config
 from twistedcaldav.directory.directory import DirectoryService
 from twistedcaldav.log import Logger
-from twistedcaldav.directory.resourceinfo import ResourceInfoDatabase
-from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
 
 log = Logger()
 
@@ -44,19 +41,12 @@
 ELEMENT_SHORTNAME         = "uid"
 ELEMENT_GUID              = "guid"
 ELEMENT_PASSWORD          = "password"
-ELEMENT_ENABLE            = "enable"
-ELEMENT_HOSTEDAT          = "hosted-at"
 ELEMENT_NAME              = "name"
 ELEMENT_FIRST_NAME        = "first-name"
 ELEMENT_LAST_NAME         = "last-name"
 ELEMENT_EMAIL_ADDRESS     = "email-address"
 ELEMENT_MEMBERS           = "members"
 ELEMENT_MEMBER            = "member"
-ELEMENT_ENABLECALENDAR    = "enable-calendar"
-ELEMENT_CUADDR            = "cuaddr"
-ELEMENT_AUTOSCHEDULE      = "auto-schedule"
-ELEMENT_PROXIES           = "proxies"
-ELEMENT_READ_ONLY_PROXIES = "read-only-proxies"
 
 ATTRIBUTE_REALM           = "realm"
 ATTRIBUTE_REPEAT          = "repeat"
@@ -102,44 +92,7 @@
             log.error("Ignoring file %r because it is not a repository builder file" % (self.xmlFile,))
             return
         self._parseXML(accounts_node)
-        if externalUpdate:
-            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.
@@ -155,19 +108,6 @@
                 if item is not None:
                     item.groups.add(group.shortNames[0])
 
-        def updateProxyFor(proxier):
-            # Update proxy membership
-            for recordType, shortName in proxier.proxies:
-                item = self.items[recordType].get(shortName)
-                if item is not None:
-                    item.proxyFor.add((proxier.recordType, proxier.shortNames[0]))
-
-            # Update read-only proxy membership
-            for recordType, shortName in proxier.readOnlyProxies:
-                item = self.items[recordType].get(shortName)
-                if item is not None:
-                    item.readOnlyProxyFor.add((proxier.recordType, proxier.shortNames[0]))
-
         for child in node._get_childNodes():
             child_name = child._get_localName()
             if child_name is None:
@@ -196,7 +136,6 @@
         for records in self.items.itervalues():
             for principal in records.itervalues():
                 updateMembership(principal)
-                updateProxyFor(principal)
                 
 class XMLAccountRecord (object):
     """
@@ -210,21 +149,12 @@
         self.shortNames = []
         self.guid = None
         self.password = None
-        self.enabled = True
-        self.hostedAt = ""
         self.fullName = None
         self.firstName = None
         self.lastName = None
         self.emailAddresses = set()
         self.members = set()
         self.groups = set()
-        self.calendarUserAddresses = set()
-        self.autoSchedule = False
-        self.enabledForCalendaring = False
-        self.proxies = set()
-        self.proxyFor = set()
-        self.readOnlyProxies = set()
-        self.readOnlyProxyFor = set()
 
     def repeat(self, ctr):
         """
@@ -264,29 +194,16 @@
                 emailAddresses.add(emailAddr % ctr)
             else:
                 emailAddresses.add(emailAddr)
-        calendarUserAddresses = set()
-        for cuaddr in self.calendarUserAddresses:
-            if cuaddr.find("%") != -1:
-                calendarUserAddresses.add(cuaddr % ctr)
-            else:
-                calendarUserAddresses.add(cuaddr)
         
         result = XMLAccountRecord(self.recordType)
         result.shortNames = shortNames
         result.guid = guid
         result.password = password
-        result.enabled = self.enabled
-        result.hostedAt = self.hostedAt
         result.fullName = fullName
         result.firstName = firstName
         result.lastName = lastName
         result.emailAddresses = emailAddresses
         result.members = self.members
-        result.calendarUserAddresses = calendarUserAddresses
-        result.autoSchedule = self.autoSchedule
-        result.enabledForCalendaring = self.enabledForCalendaring
-        result.proxies = self.proxies
-        result.readOnlyProxies = self.readOnlyProxies
         return result
 
     def parseXML(self, node):
@@ -302,12 +219,6 @@
                     self.guid = child.firstChild.data.encode("utf-8")
                     if len(self.guid) < 4:
                         self.guid += "?" * (4 - len(self.guid))
-            elif child_name == ELEMENT_ENABLE:
-                if child.firstChild is not None:
-                    self.enabled = (child.firstChild.data.encode("utf-8") == VALUE_TRUE)
-            elif child_name == ELEMENT_HOSTEDAT:
-                if child.firstChild is not None:
-                    self.hostedAt = child.firstChild.data.encode("utf-8")
             elif child_name == ELEMENT_PASSWORD:
                 if child.firstChild is not None:
                     self.password = child.firstChild.data.encode("utf-8")
@@ -325,26 +236,9 @@
                     self.emailAddresses.add(child.firstChild.data.encode("utf-8").lower())
             elif child_name == ELEMENT_MEMBERS:
                 self._parseMembers(child, self.members)
-            elif child_name == ELEMENT_ENABLECALENDAR:
-                if child.firstChild is not None:
-                    self.enabledForCalendaring = (child.firstChild.data.encode("utf-8") == VALUE_TRUE)
-            elif child_name == ELEMENT_CUADDR:
-                if child.firstChild is not None:
-                    self.calendarUserAddresses.add(child.firstChild.data.encode("utf-8"))
-            elif child_name == ELEMENT_AUTOSCHEDULE:
-                if child.firstChild is not None:
-                    self.autoSchedule = (child.firstChild.data.encode("utf-8") == VALUE_TRUE)
-            elif child_name == ELEMENT_PROXIES:
-                self._parseMembers(child, self.proxies)
-            elif child_name == ELEMENT_READ_ONLY_PROXIES:
-                self._parseMembers(child, self.readOnlyProxies)
             else:
                 raise RuntimeError("Unknown account attribute: %s" % (child_name,))
 
-        if self.enabledForCalendaring:
-            for email in self.emailAddresses:
-                self.calendarUserAddresses.add("mailto:%s" % (email,))
-
         if not self.shortNames:
             self.shortNames.append(self.guid)
 

Added: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaugmentsparser.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaugmentsparser.py	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaugmentsparser.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -0,0 +1,141 @@
+##
+# Copyright (c) 2009 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from xml.etree.ElementTree import ElementTree
+from xml.parsers.expat import ExpatError
+import types
+
+"""
+XML based augment configuration file handling.
+"""
+
+__all__ = [
+    "XMLAugmentsParser",
+]
+
+from twistedcaldav.log import Logger
+
+log = Logger()
+
+ELEMENT_AUGMENTS          = "augments"
+ELEMENT_RECORD            = "record"
+
+ELEMENT_GUID              = "guid"
+ELEMENT_ENABLE            = "enable"
+ELEMENT_HOSTEDAT          = "hosted-at"
+ELEMENT_ENABLECALENDAR    = "enable-calendar"
+ELEMENT_AUTOSCHEDULE      = "auto-schedule"
+ELEMENT_CUADDR            = "cuaddr"
+
+ATTRIBUTE_REPEAT          = "repeat"
+
+VALUE_TRUE                = "true"
+VALUE_FALSE               = "false"
+
+ELEMENT_AUGMENTRECORD_MAP = {
+    ELEMENT_GUID:           "guid",
+    ELEMENT_ENABLE:         "enabled",
+    ELEMENT_HOSTEDAT:       "hostedAt",
+    ELEMENT_ENABLECALENDAR: "enabledForCalendaring",
+    ELEMENT_AUTOSCHEDULE:   "autoSchedule",
+    ELEMENT_CUADDR:         "calendarUserAddresses",
+}
+
+class XMLAugmentsParser(object):
+    """
+    XML augments configuration file parser.
+    """
+    def __repr__(self):
+        return "<%s %r>" % (self.__class__.__name__, self.xmlFile)
+
+    def __init__(self, xmlFile, items):
+
+        self.items = items
+        self.xmlFile = xmlFile
+
+        # Read in XML
+        try:
+            tree = ElementTree(file=self.xmlFile)
+        except ExpatError, e:
+            log.error("Unable to parse file '%s' because: %s" % (self.xmlFile, e,), raiseException=RuntimeError)
+
+        # Verify that top-level element is correct
+        augments_node = tree.getroot()
+        if augments_node.tag != ELEMENT_AUGMENTS:
+            log.error("Ignoring file '%s' because it is not a augments file" % (self.xmlFile,), raiseException=RuntimeError)
+
+        self._parseXML(augments_node)
+
+    def _parseXML(self, rootnode):
+        """
+        Parse the XML root node from the augments configuration document.
+        @param rootnode: the L{Element} to parse.
+        """
+        for child in rootnode.getchildren():
+            
+            if child.tag != ELEMENT_RECORD:
+                log.error("Unknown augment type: '%s' in augment file: '%s'" % (child.tag, self.xmlFile,), raiseException=RuntimeError)
+
+            repeat = int(child.get(ATTRIBUTE_REPEAT, "1"))
+
+            fields = {}
+            for node in child.getchildren():
+                
+                if node.tag in (
+                    ELEMENT_GUID,
+                    ELEMENT_HOSTEDAT,
+                ):
+                    fields[node.tag] = node.text
+                elif node.tag in (
+                    ELEMENT_ENABLE,
+                    ELEMENT_ENABLECALENDAR,
+                    ELEMENT_AUTOSCHEDULE,
+                ):
+                    fields[node.tag] = node.text == VALUE_TRUE
+                elif node.tag == ELEMENT_CUADDR:
+                    fields.setdefault(node.tag, set()).add(node.text)
+                else:
+                    log.error("Invalid element '%s' in augment file: '%s'" % (node.tag, self.xmlFile,), raiseException=RuntimeError)
+                    
+            # Must have at least a guid
+            if ELEMENT_GUID not in fields:
+                log.error("Invalid record '%s' without a guid in augment file: '%s'" % (child, self.xmlFile,), raiseException=RuntimeError)
+                
+            if repeat > 1:
+                for i in xrange(1, repeat+1):
+                    self.buildRecord(fields, i)
+            else:
+                self.buildRecord(fields)
+    
+    def buildRecord(self, fields, count=None):
+        
+        from twistedcaldav.directory.augment import AugmentRecord
+
+        def expandCount(value, count):
+            
+            if type(value) in types.StringTypes:
+                return value % (count,) if count and "%" in value else value
+            elif type(value) == set:
+                return set([item % (count,) if count and "%" in item else item for item in value])
+            else:
+                return value
+        
+        actualFields = {}
+        for k,v in fields.iteritems():
+            actualFields[ELEMENT_AUGMENTRECORD_MAP[k]] = expandCount(v, count)
+
+        record = AugmentRecord(**actualFields)
+        self.items[record.guid] = record

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -29,6 +29,7 @@
 from twisted.web2.auth.digest import DigestedCredentials
 from twisted.python.filepath import FilePath
 
+from twistedcaldav.directory import augment
 from twistedcaldav.directory.directory import DirectoryService
 from twistedcaldav.directory.cachingdirectory import CachingDirectoryService,\
     CachingDirectoryRecord
@@ -79,23 +80,29 @@
         for recordType in recordTypes:
             for xmlPrincipal in self._accounts()[recordType].itervalues():
                 
+                record = XMLDirectoryRecord(
+                    service       = self,
+                    recordType    = recordType,
+                    shortNames    = tuple(xmlPrincipal.shortNames),
+                    xmlPrincipal  = xmlPrincipal,
+                )
+                
+                # Look up augment information
+                # TODO: this needs to be deferred but for now we hard code the deferred result because
+                # we know it is completing immediately.
+                d = augment.AugmentService.getAugmentRecord(record.guid)
+                d.addCallback(lambda x:record.addAugmentInformation(x))
+
                 matched = False
                 if indexType == self.INDEX_TYPE_GUID:
-                    matched = indexKey == xmlPrincipal.guid
+                    matched = indexKey == record.guid
                 elif indexType == self.INDEX_TYPE_SHORTNAME:
-                    matched = indexKey in xmlPrincipal.shortNames
+                    matched = indexKey in record.shortNames
                 elif indexType == self.INDEX_TYPE_CUA:
-                    matched = indexKey in xmlPrincipal.calendarUserAddresses
+                    matched = indexKey in record.calendarUserAddresses
                 
                 if matched:
-                    record = XMLDirectoryRecord(
-                        service       = self,
-                        recordType    = recordType,
-                        shortNames    = tuple(xmlPrincipal.shortNames),
-                        xmlPrincipal  = xmlPrincipal,
-                    )
-                    self.recordCacheForType(recordType).addRecord(record,
-                        indexType, indexKey)
+                    self.recordCacheForType(recordType).addRecord(record, indexType, indexKey)
             
     def recordsMatchingFields(self, fields, operand="or", recordType=None):
         # Default, brute force method search of underlying XML data
@@ -186,15 +193,11 @@
             service               = service,
             recordType            = recordType,
             guid                  = xmlPrincipal.guid,
-            enabled               = xmlPrincipal.enabled,
-            hostedAt              = xmlPrincipal.hostedAt,
             shortNames            = shortNames,
             fullName              = xmlPrincipal.fullName,
             firstName             = xmlPrincipal.firstName,
             lastName              = xmlPrincipal.lastName,
             emailAddresses        = xmlPrincipal.emailAddresses,
-            enabledForCalendaring = xmlPrincipal.enabledForCalendaring,
-            calendarUserAddresses = xmlPrincipal.calendarUserAddresses,
         )
 
         self.password          = xmlPrincipal.password

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -352,8 +352,10 @@
     #
     # Attach methods to Logger
     #
-    def log_emit(self, message, __level__=level, **kwargs):
+    def log_emit(self, message, __level__=level, raiseException=None, **kwargs):
         self.emit(__level__, message, **kwargs)
+        if raiseException:
+            raise raiseException(message)
 
     def will_emit(self, __level__=level):
         return self.willLogAtLevel(__level__)
@@ -369,8 +371,10 @@
     #
     # Attach methods to LoggingMixIn
     #
-    def log_emit(self, message, __level__=level, **kwargs):
+    def log_emit(self, message, __level__=level, raiseException=None, **kwargs):
         self.logger.emit(__level__, message, **kwargs)
+        if raiseException:
+            raise raiseException(message)
 
     def will_emit(self=log_emit, __level__=level):
         return self.logger.willLogAtLevel(__level__)

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/resource.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/resource.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -902,7 +902,7 @@
                 ))
 
             elif name == "auto-schedule":
-                autoSchedule = (yield self.getAutoSchedule())
+                autoSchedule = self.getAutoSchedule()
                 returnValue(customxml.AutoSchedule("true" if autoSchedule else "false"))
 
         result = (yield super(CalendarPrincipalResource, self).readProperty(property, request))
@@ -913,8 +913,8 @@
             "%r is not a WebDAVElement instance" % (property,)
         )
 
-        if property.qname() == (caldav_namespace, "auto-schedule"):
-            self.setAutoSchedule(autoSchedule)
+        #if property.qname() == (caldav_namespace, "auto-schedule"):
+        #    self.setAutoSchedule(autoSchedule)
 
         return super(CalendarPrincipalResource, self).writeProperty(property, request)
 

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/implicit.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/implicit.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -26,6 +26,7 @@
 from twistedcaldav import caldavxml
 from twistedcaldav.caldavxml import caldav_namespace
 from twistedcaldav.customxml import TwistedSchedulingObjectResource
+from twistedcaldav.directory.principal import DirectoryCalendarPrincipalResource
 from twistedcaldav.ical import Property
 from twistedcaldav.log import Logger
 from twistedcaldav.method import report_common
@@ -321,6 +322,8 @@
     def extractCalendarData(self):
         
         # Get the originator who is the authenticated user
+        # TODO: the originator actually needs to be the owner of the calendar collection not the authenticated
+        # principal, who might be a proxy or admin
         self.originatorPrincipal = None
         self.originator = ""
         authz_principal = self.resource.currentPrincipal(self.request).children[0]
@@ -328,6 +331,10 @@
             originatorPrincipalURL = str(authz_principal)
             if originatorPrincipalURL:
                 self.originatorPrincipal = (yield self.request.locateResource(originatorPrincipalURL))
+                if not isinstance(self.originatorPrincipal, DirectoryCalendarPrincipalResource):
+                    log.error("Originator '%s' is not enabled for calendaring" % (originatorPrincipalURL,))
+                    raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "invalid-originator")))
+
                 if self.originatorPrincipal:
                     # Pick the first mailto cu address or the first other type
                     for item in self.originatorPrincipal.calendarUserAddresses():

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/processing.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/processing.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -282,7 +282,7 @@
                 raise ImplicitProcessorException(iTIPRequestStatus.NO_USER_SUPPORT)
 
             log.debug("ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:REQUEST, UID: '%s' - new processed" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid))
-            autoprocessed = (yield self.recipient.principal.getAutoSchedule())
+            autoprocessed = 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"
             
@@ -305,7 +305,7 @@
             result = (True, autoprocessed, changes,)
         else:
             # Processing update to existing event
-            autoprocessed = (yield self.recipient.principal.getAutoSchedule())
+            autoprocessed = self.recipient.principal.getAutoSchedule()
             new_calendar, rids = iTipProcessing.processRequest(self.message, self.recipient_calendar, self.recipient.cuaddr, autoprocessing=autoprocessed)
             if new_calendar:
      
@@ -366,7 +366,7 @@
         else:
             # Need to check for auto-respond attendees. These need to suppress the inbox message
             # if the cancel is processed.
-            autoprocessed = (yield self.recipient.principal.getAutoSchedule())
+            autoprocessed = 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/cdaboo/partition-4464/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/stdconfig.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/stdconfig.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -45,6 +45,15 @@
     },
 }
 
+DEFAULT_AUGMENT_PARAMS = {
+    "twistedcaldav.directory.augment.AugmentXMLDB": {
+        "xmlFiles": ["/etc/caldavd/augments.xml",],
+    },
+    "twistedcaldav.directory.augment.AugmentSqliteDB": {
+        "dbpath": "/etc/caldavd/augments.sqlite",
+    },
+}
+
 DEFAULT_CONFIG = {
     # Note: Don't use None values below; that confuses the command-line parser.
 
@@ -97,6 +106,23 @@
     },
 
     #
+    # Augment service
+    #
+    #    Augments for the directory service records to add calendar specific attributes.
+    #
+    "AugmentService": {
+        "type": "twistedcaldav.directory.augment.AugmentXMLDB",
+        "params": DEFAULT_AUGMENT_PARAMS["twistedcaldav.directory.augment.AugmentXMLDB"],
+    },
+
+    #
+    # Proxy loader
+    #
+    #    Allows for initialization of the proxy database from an XML file.
+    #
+    "ProxyLoadFromFile": "",
+
+    #
     # Special principals
     #
     "AdminPrincipals": [],                       # Principals with "DAV:all" access (relative URLs)
@@ -446,6 +472,13 @@
             if param not in DEFAULT_SERVICE_PARAMS[configDict.DirectoryService.type]:
                 del configDict.DirectoryService.params[param]
 
+def _postUpdateAugmentService(configDict):
+    if configDict.AugmentService.type in DEFAULT_AUGMENT_PARAMS:
+        for param in tuple(configDict.AugmentService.params):
+            if param not in DEFAULT_AUGMENT_PARAMS[configDict.AugmentService.type]:
+                log.warn("Parameter %s is not supported by service %s" % (param, configDict.AugmentService.type))
+                del configDict.AugmentService.params[param]
+
 def _updateACLs(configDict):
     #
     # Base resource ACLs
@@ -653,6 +686,7 @@
 POST_UPDATE_HOOKS = (
     _updateHostName,
     _postUpdateDirectoryService,
+    _postUpdateAugmentService,
     _updateACLs,
     _updateRejectClients,
     _updateDropBox,

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_upgrade.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_upgrade.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_upgrade.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2009 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -39,7 +39,11 @@
             "directory", "test", "accounts.xml")
         config.DirectoryService.params.xmlFile = xmlFile
 
+        xmlAugmentsFile = os.path.join(os.path.dirname(os.path.dirname(__file__)),
+            "directory", "test", "augments.xml")
+        config.AugmentService.params.xmlFiles = (xmlAugmentsFile,)
 
+
     def setUpInitialStates(self):
         self.setUpXMLDirectory()
 
@@ -349,10 +353,10 @@
             {
                 "@contents" : None,
             },
-            ResourceInfoDatabase.dbFilename :
-            {
-                "@contents" : None,
-            }
+#            ResourceInfoDatabase.dbFilename :
+#            {
+#                "@contents" : None,
+#            }
         }
 
         root = self.createHierarchy(before)
@@ -463,10 +467,10 @@
             {
                 "@contents" : None,
             },
-            ResourceInfoDatabase.dbFilename :
-            {
-                "@contents" : None,
-            }
+#            ResourceInfoDatabase.dbFilename :
+#            {
+#                "@contents" : None,
+#            }
         }
 
         root = self.createHierarchy(before)
@@ -593,10 +597,10 @@
             {
                 "@contents" : None,
             },
-            ResourceInfoDatabase.dbFilename :
-            {
-                "@contents" : None,
-            }
+#            ResourceInfoDatabase.dbFilename :
+#            {
+#                "@contents" : None,
+#            }
         }
 
         root = self.createHierarchy(before)
@@ -724,10 +728,10 @@
             {
                 "@contents" : None,
             },
-            ResourceInfoDatabase.dbFilename :
-            {
-                "@contents" : None,
-            }
+#            ResourceInfoDatabase.dbFilename :
+#            {
+#                "@contents" : None,
+#            }
         }
 
         root = self.createHierarchy(before)
@@ -825,10 +829,10 @@
             {
                 "@contents" : None,
             },
-            ResourceInfoDatabase.dbFilename :
-            {
-                "@contents" : None,
-            }
+#            ResourceInfoDatabase.dbFilename :
+#            {
+#                "@contents" : None,
+#            }
         }
 
 
@@ -866,18 +870,18 @@
             {
                 "@contents" : "1",
             },
-            CalendarUserProxyDatabase.dbFilename :
-            {
-                "@contents" : None,
-            },
+#            CalendarUserProxyDatabase.dbFilename :
+#            {
+#                "@contents" : None,
+#            },
             MailGatewayTokensDatabase.dbFilename :
             {
                 "@contents" : None,
             },
-            ResourceInfoDatabase.dbFilename :
-            {
-                "@contents" : None,
-            }
+#            ResourceInfoDatabase.dbFilename :
+#            {
+#                "@contents" : None,
+#            }
         }
         root = self.createHierarchy(before)
         config.DocumentRoot = root
@@ -889,28 +893,28 @@
         calendarUserProxyDatabase = CalendarUserProxyDatabase(root)
         resourceInfoDatabase = ResourceInfoDatabase(root)
 
-        for guid, info in assignments.iteritems():
+#        for guid, info in assignments.iteritems():
+#
+#            proxyGroup = "%s#calendar-proxy-write" % (guid,)
+#            result = set([row[0] for row in calendarUserProxyDatabase._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", proxyGroup)])
+#            if info[1]:
+#                self.assertTrue(info[1] in result)
+#            else:
+#                self.assertTrue(not result)
+#
+#            readOnlyProxyGroup = "%s#calendar-proxy-read" % (guid,)
+#            result = set([row[0] for row in calendarUserProxyDatabase._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", readOnlyProxyGroup)])
+#            if info[2]:
+#                self.assertTrue(info[2] in result)
+#            else:
+#                self.assertTrue(not result)
+#
+#            autoSchedule = resourceInfoDatabase._db_value_for_sql("select AUTOSCHEDULE from RESOURCEINFO where GUID = :1", guid)
+#            autoSchedule = autoSchedule == 1
+#            self.assertEquals(info[0], autoSchedule)
 
-            proxyGroup = "%s#calendar-proxy-write" % (guid,)
-            result = set([row[0] for row in calendarUserProxyDatabase._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", proxyGroup)])
-            if info[1]:
-                self.assertTrue(info[1] in result)
-            else:
-                self.assertTrue(not result)
 
-            readOnlyProxyGroup = "%s#calendar-proxy-read" % (guid,)
-            result = set([row[0] for row in calendarUserProxyDatabase._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", readOnlyProxyGroup)])
-            if info[2]:
-                self.assertTrue(info[2] in result)
-            else:
-                self.assertTrue(not result)
 
-            autoSchedule = resourceInfoDatabase._db_value_for_sql("select AUTOSCHEDULE from RESOURCEINFO where GUID = :1", guid)
-            autoSchedule = autoSchedule == 1
-            self.assertEquals(info[0], autoSchedule)
-
-
-
 event01_before = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//Apple Inc.//iCal 3.0//EN

Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/upgrade.py	2009-08-20 20:17:42 UTC (rev 4501)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/upgrade.py	2009-08-21 18:10:27 UTC (rev 4502)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2009 Apple Inc. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -252,31 +252,35 @@
 
 
     def migrateResourceInfo(config, directory, uid, gid):
-        log.info("Fetching delegate assignments and auto-schedule settings from directory")
-        resourceInfoDatabase = ResourceInfoDatabase(config.DataRoot)
-        calendarUserProxyDatabase = CalendarUserProxyDatabase(config.DataRoot)
-        resourceInfo = directory.getResourceInfo()
-        for guid, autoSchedule, proxy, readOnlyProxy in resourceInfo:
-            resourceInfoDatabase.setAutoScheduleInDatabase(guid, autoSchedule)
-            if proxy:
-                calendarUserProxyDatabase.setGroupMembersInDatabase(
-                    "%s#calendar-proxy-write" % (guid,),
-                    [proxy]
-                )
-            if readOnlyProxy:
-                calendarUserProxyDatabase.setGroupMembersInDatabase(
-                    "%s#calendar-proxy-read" % (guid,),
-                    [readOnlyProxy]
-                )
+        # TODO: we need to account for the new augments database. This means migrating from the pre-resource info
+        # implementation and the resource-info implementation
+        pass
 
-        dbPath = os.path.join(config.DataRoot, ResourceInfoDatabase.dbFilename)
-        if os.path.exists(dbPath):
-            os.chown(dbPath, uid, gid)
+#        log.info("Fetching delegate assignments and auto-schedule settings from directory")
+#        resourceInfoDatabase = ResourceInfoDatabase(config.DataRoot)
+#        calendarUserProxyDatabase = CalendarUserProxyDatabase(config.DataRoot)
+#        resourceInfo = directory.getResourceInfo()
+#        for guid, autoSchedule, proxy, readOnlyProxy in resourceInfo:
+#            resourceInfoDatabase.setAutoScheduleInDatabase(guid, autoSchedule)
+#            if proxy:
+#                calendarUserProxyDatabase.setGroupMembersInDatabase(
+#                    "%s#calendar-proxy-write" % (guid,),
+#                    [proxy]
+#                )
+#            if readOnlyProxy:
+#                calendarUserProxyDatabase.setGroupMembersInDatabase(
+#                    "%s#calendar-proxy-read" % (guid,),
+#                    [readOnlyProxy]
+#                )
+#
+#        dbPath = os.path.join(config.DataRoot, ResourceInfoDatabase.dbFilename)
+#        if os.path.exists(dbPath):
+#            os.chown(dbPath, uid, gid)
+#
+#        dbPath = os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)
+#        if os.path.exists(dbPath):
+#            os.chown(dbPath, uid, gid)
 
-        dbPath = os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)
-        if os.path.exists(dbPath):
-            os.chown(dbPath, uid, gid)
-
     def createMailTokensDatabase(config, uid, gid):
         # Cause the tokens db to be created on disk so we can set the
         # permissions on it now
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090821/623e7877/attachment-0001.html>


More information about the calendarserver-changes mailing list