[CalendarServer-changes] [12829] CalendarServer/branches/users/sagen/move2who

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 5 20:18:19 PST 2014


Revision: 12829
          http://trac.calendarserver.org//changeset/12829
Author:   sagen at apple.com
Date:     2014-03-05 20:18:19 -0800 (Wed, 05 Mar 2014)
Log Message:
-----------
Modifying delegate assignments via PROPPATCH works

Modified Paths:
--------------
    CalendarServer/branches/users/sagen/move2who/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py
    CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py
    CalendarServer/branches/users/sagen/move2who/txdav/dps/commands.py
    CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py
    CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py
    CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py
    CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py
    CalendarServer/branches/users/sagen/move2who/txdav/who/test/test_delegates.py

Modified: CalendarServer/branches/users/sagen/move2who/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/twistedcaldav/directory/calendaruserproxy.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/twistedcaldav/directory/calendaruserproxy.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -284,7 +284,7 @@
         principals = []
         newUIDs = set()
         for uri in members:
-            principal = self.pcollection._principalForURI(uri)
+            principal = yield self.pcollection._principalForURI(uri)
             # Invalid principals MUST result in an error.
             if principal is None or principal.principalURL() != uri:
                 raise HTTPError(StatusResponse(
@@ -298,7 +298,7 @@
         # Get the old set of UIDs
         # oldUIDs = (yield self._index().getMembers(self.uid))
         oldPrincipals = yield self.groupMembers()
-        oldUIDs = [p.uid for p in oldPrincipals]
+        oldUIDs = [p.principalUID() for p in oldPrincipals]
 
         # Change membership
         yield self.setGroupMemberSetPrincipals(principals)
@@ -309,19 +309,24 @@
 
         changedUIDs = newUIDs.symmetric_difference(oldUIDs)
         for uid in changedUIDs:
-            principal = self.pcollection.principalForUID(uid)
+            principal = yield self.pcollection.principalForUID(uid)
             if principal:
                 yield principal.cacheNotifier.changed()
 
         returnValue(True)
 
 
+    @inlineCallbacks
     def setGroupMemberSetPrincipals(self, principals):
-        # Map the principals to UIDs.
-        return self._index().setGroupMembers(
-            self.uid,
-            [p.principalUID() for p in principals],
+
+        # Find our pseudo-record
+        record = yield self.parent.record.service.recordWithShortName(
+            self._recordTypeFromProxyType(),
+            self.parent.principalUID()
         )
+        # Set the members
+        memberRecords = [p.record for p in principals]
+        yield record.setMembers(memberRecords)
 
 
     ##

Modified: CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -1244,6 +1244,19 @@
 
 
     @classproperty
+    def _removeDelegatesQuery(cls):
+        de = schema.DELEGATES
+        return Delete(
+            From=de,
+            Where=(
+                de.DELEGATOR == Parameter("delegator")
+            ).And(
+                de.READ_WRITE == Parameter("readWrite")
+            )
+        )
+
+
+    @classproperty
     def _removeDelegateGroupQuery(cls):
         ds = schema.DELEGATE_GROUPS
         return Delete(
@@ -1259,6 +1272,19 @@
 
 
     @classproperty
+    def _removeDelegateGroupsQuery(cls):
+        ds = schema.DELEGATE_GROUPS
+        return Delete(
+            From=ds,
+            Where=(
+                ds.DELEGATOR == Parameter("delegator")
+            ).And(
+                ds.READ_WRITE == Parameter("readWrite")
+            )
+        )
+
+
+    @classproperty
     def _selectDelegatesQuery(cls):
         de = schema.DELEGATES
         return Select(
@@ -1463,6 +1489,24 @@
         )
 
 
+    def removeDelegates(self, delegator, readWrite):
+        """
+        Removes all rows for this delegator/readWrite combination from the
+        DELEGATES table.
+
+        @param delegator: the UID of the delegator
+        @type delegator: C{unicode}
+        @param readWrite: remove read and write access if True, otherwise
+            read-only access
+        @type readWrite: C{boolean}
+        """
+        return self._removeDelegatesQuery.on(
+            self,
+            delegator=delegator.encode("utf-8"),
+            readWrite=1 if readWrite else 0
+        )
+
+
     def removeDelegateGroup(self, delegator, delegateGroupID, readWrite):
         """
         Removes a row from the DELEGATE_GROUPS table.  The delegate should be a
@@ -1484,6 +1528,24 @@
         )
 
 
+    def removeDelegateGroups(self, delegator, readWrite):
+        """
+        Removes all rows for this delegator/readWrite combination from the
+        DELEGATE_GROUPS table.
+
+        @param delegator: the UID of the delegator
+        @type delegator: C{unicode}
+        @param readWrite: remove read and write access if True, otherwise
+            read-only access
+        @type readWrite: C{boolean}
+        """
+        return self._removeDelegateGroupsQuery.on(
+            self,
+            delegator=delegator.encode("utf-8"),
+            readWrite=1 if readWrite else 0
+        )
+
+
     @inlineCallbacks
     def delegates(self, delegator, readWrite, expanded=False):
         """

Modified: CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -35,7 +35,7 @@
 from txdav.dps.commands import (
     RecordWithShortNameCommand, RecordWithUIDCommand, RecordWithGUIDCommand,
     RecordsWithRecordTypeCommand, RecordsWithEmailAddressCommand,
-    MembersCommand, GroupsCommand,
+    MembersCommand, GroupsCommand, SetMembersCommand,
     VerifyPlaintextPasswordCommand, VerifyHTTPDigestCommand
 )
 import txdav.who.delegates
@@ -290,7 +290,7 @@
     def verifyCredentials(self, credentials):
 
         # XYZZY REMOVE THIS, it bypasses all authentication!:
-        returnValue(True)
+        # returnValue(True)
 
         if isinstance(credentials, UsernamePassword):
             log.debug("UsernamePassword")
@@ -362,6 +362,17 @@
         )
 
 
+    def setMembers(self, members):
+        log.debug("DPS Client setMembers")
+        memberUIDs = [m.uid.encode("utf-8") for m in members]
+        return self.service._call(
+            SetMembersCommand,
+            lambda x: x['success'],
+            uid=self.uid.encode("utf-8"),
+            memberUIDs=memberUIDs
+        )
+
+
     @property
     def calendarUserAddresses(self):
         if not self.hasCalendars:

Modified: CalendarServer/branches/users/sagen/move2who/txdav/dps/commands.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/dps/commands.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/dps/commands.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -98,6 +98,7 @@
     ]
 
 
+
 class GroupsCommand(amp.Command):
     arguments = [
         ('uid', amp.String()),
@@ -108,6 +109,17 @@
 
 
 
+class SetMembersCommand(amp.Command):
+    arguments = [
+        ('uid', amp.String()),
+        ('memberUIDs', amp.ListOf(amp.String())),
+    ]
+    response = [
+        ('success', amp.Boolean()),
+    ]
+
+
+
 class VerifyPlaintextPasswordCommand(amp.Command):
     arguments = [
         ('uid', amp.String()),

Modified: CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -39,7 +39,7 @@
 from txdav.dps.commands import (
     RecordWithShortNameCommand, RecordWithUIDCommand, RecordWithGUIDCommand,
     RecordsWithRecordTypeCommand, RecordsWithEmailAddressCommand,
-    MembersCommand, GroupsCommand,
+    MembersCommand, GroupsCommand, SetMembersCommand,
     VerifyPlaintextPasswordCommand, VerifyHTTPDigestCommand,
     # UpdateRecordsCommand, RemoveRecordsCommand
 )
@@ -194,6 +194,36 @@
         returnValue(response)
 
 
+    @SetMembersCommand.responder
+    @inlineCallbacks
+    def setMembers(self, uid, memberUIDs):
+        uid = uid.decode("utf-8")
+        memberUIDs = [m.decode("utf-8") for m in memberUIDs]
+        log.debug("Set Members: {u} -> {m}", u=uid, m=memberUIDs)
+        try:
+            record = (yield self._directory.recordWithUID(uid))
+        except Exception as e:
+            log.error("Failed in setMembers", error=e)
+            record = None
+
+        if record is not None:
+            memberRecords = []
+            for memberUID in memberUIDs:
+                memberRecord = yield self._directory.recordWithUID(memberUID)
+                if memberRecord is not None:
+                    memberRecords.append(memberRecord)
+            yield record.setMembers(memberRecords)
+            success = True
+        else:
+            success = False
+
+        response = {
+            "success": success,
+        }
+        log.debug("Responding with: {response}", response=response)
+        returnValue(response)
+
+
     @GroupsCommand.responder
     @inlineCallbacks
     def groups(self, uid):

Modified: CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -54,7 +54,6 @@
         augmented = []
         txn = self.service._store.newTransaction()
         groupUIDs = yield txn.groupsFor(self.uid)
-        print("XYZZY GROU UIDS", groupUIDs)
         for groupUID in groupUIDs:
             groupRecord = yield self.service.recordWithShortName(
                 RecordType.group, groupUID

Modified: CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -25,7 +25,9 @@
     DirectoryRecord as BaseDirectoryRecord
 )
 from twext.who.expression import MatchExpression, MatchType
-from twext.who.idirectory import RecordType as BaseRecordType, FieldName
+from twext.who.idirectory import (
+    RecordType as BaseRecordType, FieldName, NotAllowedError
+)
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.python.constants import Names, NamedConstant
 
@@ -64,19 +66,6 @@
         the members will consist of the records who have delegated *to*
         this record.
         """
-        # Here are some delegate assignments to test with:
-        # txn = self.service._store.newTransaction()
-        # yield txn.addDelegate(u"E415DBA7-40B5-49F5-A7CC-ACC81E4DEC79", u"494E462A-B16A-4A90-B77F-B9019DD73DAA", True)
-        # yield txn.addDelegate(u"__wsanchez__", u"__cdaboo__", True)
-        # yield txn.addDelegate(u"__wsanchez__", u"__dre__", False)
-        # groupID, name, membershipHash = (
-        #     yield txn.groupByUID(u"494E462A-B16A-4A90-B77F-B9019DD73DAA")
-        # )
-        # print("XYZZY", groupID, name, membershipHash)
-        # yield txn.addDelegateGroup(u"E415DBA7-40B5-49F5-A7CC-ACC81E4DEC79", groupID, False)
-        # yield txn.commit()
-        ###
-
         parentUID, proxyType = self.uid.split("#")
         txn = self.service._store.newTransaction()
 
@@ -105,6 +94,45 @@
         returnValue(records)
 
 
+
+    @inlineCallbacks
+    def setMembers(self, memberRecords):
+        """
+        Replace the members of this group with the new members.
+
+        @param memberRecords: The new members of the group
+        @type memberRecords: iterable of L{iDirectoryRecord}s
+        """
+
+        if self.recordType not in (
+            RecordType.readDelegateGroup, RecordType.writeDelegateGroup
+        ):
+            raise NotAllowedError("Setting members not supported")
+
+        parentUID, proxyType = self.uid.split("#")
+        readWrite = (self.recordType is RecordType.writeDelegateGroup)
+
+        log.debug(
+            "Setting delegate assignments for {u} ({rw}) to {m}".format(
+                u=parentUID, rw=("write" if readWrite else "read"),
+                m=[r.uid for r in memberRecords]
+            )
+        )
+
+        txn = self.service._store.newTransaction()
+
+        yield txn.removeDelegates(parentUID, readWrite)
+        yield txn.removeDelegateGroups(parentUID, readWrite)
+
+        delegator = yield self.service._masterDirectory.recordWithUID(parentUID)
+
+        for delegate in memberRecords:
+            yield addDelegate(txn, delegator, delegate, readWrite)
+
+        yield txn.commit()
+
+
+
 def recordTypeToProxyType(recordType):
     return {
         RecordType.readDelegateGroup: "calendar-proxy-read",
@@ -276,11 +304,3 @@
             if record is not None:
                 records.append(record)
     returnValue(records)
-
-
-def allGroupDelegates(txn):
-    """
-    @return: the UIDs of all groups which are currently delegated to
-    @rtype: a Deferred which fires with a set() of UIDs C{unicode}
-    """
-    return txn.allGroupDelegates()

Modified: CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -22,7 +22,6 @@
 from twext.enterprise.dal.record import fromTable
 from twext.enterprise.dal.syntax import Delete, Select
 from twext.enterprise.jobqueue import WorkItem, PeerConnectionPool
-from txdav.who.delegates import allGroupDelegates
 from twext.who.idirectory import RecordType
 from twisted.internet.defer import inlineCallbacks, returnValue
 from txdav.common.datastore.sql_tables import schema
@@ -447,7 +446,7 @@
 
     @inlineCallbacks
     def groupsToRefresh(self, txn):
-        delegatedUIDs = set((yield allGroupDelegates(txn)))
+        delegatedUIDs = set((yield txn.allGroupDelegates()))
         self.log.info(
             "There are {count} group delegates", count=len(delegatedUIDs)
         )

Modified: CalendarServer/branches/users/sagen/move2who/txdav/who/test/test_delegates.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/test/test_delegates.py	2014-03-06 04:17:29 UTC (rev 12828)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/test/test_delegates.py	2014-03-06 04:18:19 UTC (rev 12829)
@@ -19,14 +19,14 @@
 """
 
 from txdav.who.delegates import (
-    addDelegate, removeDelegate, delegatesOf, delegatedTo, allGroupDelegates
+    addDelegate, removeDelegate, delegatesOf, delegatedTo,
+    DirectoryService, RecordType as DelegateRecordType
 )
 from txdav.who.groups import GroupCacher
 from twext.who.idirectory import RecordType
 from twext.who.test.test_xml import xmlService
 from twisted.internet.defer import inlineCallbacks
 from twistedcaldav.test.util import StoreTestCase
-from uuid import UUID
 
 
 class DelegationTest(StoreTestCase):
@@ -34,14 +34,19 @@
     @inlineCallbacks
     def setUp(self):
         yield super(DelegationTest, self).setUp()
+        self.store = self.storeUnderTest()
         self.xmlService = xmlService(self.mktemp(), xmlData=testXMLConfig)
         self.groupCacher = GroupCacher(self.xmlService)
+        self.delegateService = DirectoryService(
+            self.xmlService.realmName,
+            self.store
+        )
+        self.delegateService.setMasterDirectory(self.xmlService)
 
 
     @inlineCallbacks
     def test_directDelegation(self):
-        store = self.storeUnderTest()
-        txn = store.newTransaction()
+        txn = self.store.newTransaction()
 
         delegator = yield self.xmlService.recordWithUID(u"__wsanchez__")
         delegate1 = yield self.xmlService.recordWithUID(u"__sagen__")
@@ -50,24 +55,68 @@
         # Add 1 delegate
         yield addDelegate(txn, delegator, delegate1, True)
         delegates = (yield delegatesOf(txn, delegator, True))
-        self.assertEquals(["sagen"], [d.shortNames[0] for d in delegates])
+        self.assertEquals(["__sagen__"], [d.uid for d in delegates])
         delegators = (yield delegatedTo(txn, delegate1, True))
-        self.assertEquals(["wsanchez"], [d.shortNames[0] for d in delegators])
+        self.assertEquals(["__wsanchez__"], [d.uid for d in delegators])
 
+        yield txn.commit()  # So delegateService will see the changes
+        txn = self.store.newTransaction()
+
+        # The "proxy-write" pseudoGroup will have one member
+        pseudoGroup = yield self.delegateService.recordWithShortName(
+            DelegateRecordType.writeDelegateGroup,
+            u"__wsanchez__"
+        )
+        self.assertEquals(pseudoGroup.uid, u"__wsanchez__#calendar-proxy-write")
+        self.assertEquals(
+            [r.uid for r in (yield pseudoGroup.members())],
+            [u"__sagen__"]
+        )
+        # The "proxy-read" pseudoGroup will have no members
+        pseudoGroup = yield self.delegateService.recordWithShortName(
+            DelegateRecordType.readDelegateGroup,
+            u"__wsanchez__"
+        )
+        self.assertEquals(pseudoGroup.uid, u"__wsanchez__#calendar-proxy-read")
+        self.assertEquals(
+            [r.uid for r in (yield pseudoGroup.members())],
+            []
+        )
+        # The "proxy-write-for" pseudoGroup will have one member
+        pseudoGroup = yield self.delegateService.recordWithShortName(
+            DelegateRecordType.writeDelegatorGroup,
+            u"__sagen__"
+        )
+        self.assertEquals(pseudoGroup.uid, u"__sagen__#calendar-proxy-write-for")
+        self.assertEquals(
+            [r.uid for r in (yield pseudoGroup.members())],
+            [u"__wsanchez__"]
+        )
+        # The "proxy-read-for" pseudoGroup will have no members
+        pseudoGroup = yield self.delegateService.recordWithShortName(
+            DelegateRecordType.readDelegatorGroup,
+            u"__sagen__"
+        )
+        self.assertEquals(pseudoGroup.uid, u"__sagen__#calendar-proxy-read-for")
+        self.assertEquals(
+            [r.uid for r in (yield pseudoGroup.members())],
+            []
+        )
+
         # Add another delegate
         yield addDelegate(txn, delegator, delegate2, True)
         delegates = (yield delegatesOf(txn, delegator, True))
         self.assertEquals(
-            set(["sagen", "cdaboo"]),
-            set([d.shortNames[0] for d in delegates])
+            set(["__sagen__", "__cdaboo__"]),
+            set([d.uid for d in delegates])
         )
         delegators = (yield delegatedTo(txn, delegate2, True))
-        self.assertEquals(["wsanchez"], [d.shortNames[0] for d in delegators])
+        self.assertEquals(["__wsanchez__"], [d.uid for d in delegators])
 
         # Remove 1 delegate
         yield removeDelegate(txn, delegator, delegate1, True)
         delegates = (yield delegatesOf(txn, delegator, True))
-        self.assertEquals(["cdaboo"], [d.shortNames[0] for d in delegates])
+        self.assertEquals(["__cdaboo__"], [d.uid for d in delegates])
         delegators = (yield delegatedTo(txn, delegate1, True))
         self.assertEquals(0, len(delegators))
 
@@ -78,11 +127,40 @@
         delegators = (yield delegatedTo(txn, delegate2, True))
         self.assertEquals(0, len(delegators))
 
+        yield txn.commit()  # So delegateService will see the changes
 
+        # Now set delegate assignments by using pseudoGroup.setMembers()
+        pseudoGroup = yield self.delegateService.recordWithShortName(
+            DelegateRecordType.writeDelegateGroup,
+            u"__wsanchez__"
+        )
+        yield pseudoGroup.setMembers([delegate1, delegate2])
+
+        # Verify the assignments were made
+        txn = self.store.newTransaction()
+        delegates = (yield delegatesOf(txn, delegator, True))
+        self.assertEquals(
+            set(["__sagen__", "__cdaboo__"]),
+            set([d.uid for d in delegates])
+        )
+        yield txn.commit()
+
+        # Set a different group of assignments:
+        yield pseudoGroup.setMembers([delegate2])
+
+        # Verify the assignments were made
+        txn = self.store.newTransaction()
+        delegates = (yield delegatesOf(txn, delegator, True))
+        self.assertEquals(
+            set(["__cdaboo__"]),
+            set([d.uid for d in delegates])
+        )
+        yield txn.commit()
+
+
     @inlineCallbacks
     def test_indirectDelegation(self):
-        store = self.storeUnderTest()
-        txn = store.newTransaction()
+        txn = self.store.newTransaction()
 
         delegator = yield self.xmlService.recordWithUID(u"__wsanchez__")
         delegate1 = yield self.xmlService.recordWithUID(u"__sagen__")
@@ -108,15 +186,15 @@
         yield self.groupCacher.refreshGroup(txn, group2.uid)
         delegates = (yield delegatesOf(txn, delegator, True, expanded=True))
         self.assertEquals(
-            set(["sagen", "cdaboo", "glyph"]),
-            set([d.shortNames[0] for d in delegates])
+            set(["__sagen__", "__cdaboo__", "__glyph__"]),
+            set([d.uid for d in delegates])
         )
         delegators = (yield delegatedTo(txn, delegate1, True))
-        self.assertEquals(["wsanchez"], [d.shortNames[0] for d in delegators])
+        self.assertEquals(["__wsanchez__"], [d.uid for d in delegators])
 
         # Verify we can ask for all delegated-to groups
         yield addDelegate(txn, delegator, group2, True)
-        groups = (yield allGroupDelegates(txn))
+        groups = (yield txn.allGroupDelegates())
         self.assertEquals(
             set([u'__sub_group_1__', u'__top_group_1__']), set(groups)
         )
@@ -125,8 +203,8 @@
         yield addDelegate(txn, delegator, delegate1, True)
         delegates = (yield delegatesOf(txn, delegator, True, expanded=True))
         self.assertEquals(
-            set(["sagen", "cdaboo", "glyph"]),
-            set([d.shortNames[0] for d in delegates])
+            set(["__sagen__", "__cdaboo__", "__glyph__"]),
+            set([d.uid for d in delegates])
         )
 
         # Add a member to the group; they become a delegate
@@ -142,28 +220,31 @@
         )
         delegates = (yield delegatesOf(txn, delegator, True, expanded=True))
         self.assertEquals(
-            set(["sagen", "cdaboo", "glyph", "dre"]),
-            set([d.shortNames[0] for d in delegates])
+            set(["__sagen__", "__cdaboo__", "__glyph__", "__dre__"]),
+            set([d.uid for d in delegates])
         )
 
         # Remove delegate access from the top group
         yield removeDelegate(txn, delegator, group1, True)
         delegates = (yield delegatesOf(txn, delegator, True, expanded=True))
         self.assertEquals(
-            set(["sagen", "cdaboo"]),
-            set([d.shortNames[0] for d in delegates])
+            set(["__sagen__", "__cdaboo__"]),
+            set([d.uid for d in delegates])
         )
 
         # Remove delegate access from the sub group
         yield removeDelegate(txn, delegator, group2, True)
         delegates = (yield delegatesOf(txn, delegator, True, expanded=True))
         self.assertEquals(
-            set(["sagen"]),
-            set([d.shortNames[0] for d in delegates])
+            set(["__sagen__"]),
+            set([d.uid for d in delegates])
         )
+        yield txn.commit()
 
 
 
+
+
 testXMLConfig = """<?xml version="1.0" encoding="utf-8"?>
 
 <directory realm="xyzzy">
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140305/b3ff31de/attachment-0001.html>


More information about the calendarserver-changes mailing list