<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12986] CalendarServer/branches/users/sagen/move2who-4</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12986">12986</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2014-03-21 11:47:20 -0700 (Fri, 21 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>The test for calendarserver_manage_principals works now</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssagenmove2who4calendarservertoolsprincipalspy">CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4calendarservertoolstestprincipalscaldavdplist">CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/caldavd.plist</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4calendarservertoolstestprincipalsresourceslocationsxml">CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/resources-locations.xml</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4calendarservertoolstestprincipalsusersgroupsxml">CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/users-groups.xml</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4calendarservertoolstesttest_principalspy">CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_principals.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectorytestaccountsxml">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/accounts.xml</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssagenmove2who4calendarservertoolsprincipalspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py (12985 => 12986)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py        2014-03-21 02:05:52 UTC (rev 12985)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py        2014-03-21 18:47:20 UTC (rev 12986)
</span><span class="lines">@@ -32,7 +32,9 @@
</span><span class="cx"> from twisted.internet import reactor
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue, succeed
</span><span class="cx"> from twistedcaldav.config import config
</span><del>-from txdav.who.delegates import addDelegate, removeDelegate
</del><ins>+from txdav.who.delegates import (
+    addDelegate, removeDelegate, RecordType as DelegateRecordType
+)
</ins><span class="cx"> from txdav.who.idirectory import AutoScheduleMode
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -84,7 +86,7 @@
</span><span class="cx">     print(&quot;  --get-auto-schedule-mode: read auto-schedule mode&quot;)
</span><span class="cx">     print(&quot;  --set-auto-accept-group=principal: set auto-accept-group&quot;)
</span><span class="cx">     print(&quot;  --get-auto-accept-group: read auto-accept-group&quot;)
</span><del>-    print(&quot;  --add {locations|resources|addresses} 'full name' [record name] [GUID]: add a principal&quot;)
</del><ins>+    print(&quot;  --add {locations|resources|addresses} full-name record-name UID: add a principal&quot;)
</ins><span class="cx">     print(&quot;  --remove: remove a principal&quot;)
</span><span class="cx">     print(&quot;  --set-geo=url: set the geo: url for an address (e.g. geo:37.331741,-122.030333)&quot;)
</span><span class="cx">     print(&quot;  --get-geo: get the geo: url for an address&quot;)
</span><span class="lines">@@ -358,7 +360,7 @@
</span><span class="cx"> def runListPrincipalTypes(service, store):
</span><span class="cx">     directory = store.directoryService()
</span><span class="cx">     for recordType in directory.recordTypes():
</span><del>-        print(directory.recordTypeToOldString(recordType))
</del><ins>+        print(directory.recordTypeToOldName(recordType))
</ins><span class="cx">     return succeed(None)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -446,6 +448,20 @@
</span><span class="cx"> def runAddPrincipal(service, store, addType, uid, shortNames, fullNames):
</span><span class="cx">     directory = store.directoryService()
</span><span class="cx">     recordType = directory.oldNameToRecordType(addType)
</span><ins>+
+    # See if that UID is in use
+    record = yield directory.recordWithUID(uid)
+    if record is not None:
+        print(&quot;UID already in use: {uid}&quot;.format(uid=uid))
+        returnValue(None)
+
+    # See if the shortnames are in use
+    for shortName in shortNames:
+        record = yield directory.recordWithShortName(recordType, shortName)
+        if record is not None:
+            print(&quot;Record name already in use: {name}&quot;.format(name=shortName))
+            returnValue(None)
+
</ins><span class="cx">     fields = {
</span><span class="cx">         directory.fieldName.recordType: recordType,
</span><span class="cx">         directory.fieldName.uid: uid,
</span><span class="lines">@@ -454,6 +470,7 @@
</span><span class="cx">     }
</span><span class="cx">     record = DirectoryRecord(directory, fields)
</span><span class="cx">     yield record.service.updateRecords([record], create=True)
</span><ins>+    print(&quot;Added '{name}'&quot;.format(name=fullNames[0]))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -531,7 +548,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> @inlineCallbacks
</span><del>-def _addRemoveProxy(fn, store, record, proxyType, *proxyIDs):
</del><ins>+def _addRemoveProxy(msg, fn, store, record, proxyType, *proxyIDs):
</ins><span class="cx">     directory = store.directoryService()
</span><span class="cx">     readWrite = (proxyType == &quot;write&quot;)
</span><span class="cx">     for proxyID in proxyIDs:
</span><span class="lines">@@ -542,80 +559,83 @@
</span><span class="cx">             txn = store.newTransaction()
</span><span class="cx">             yield fn(txn, record, proxyRecord, readWrite)
</span><span class="cx">             yield txn.commit()
</span><ins>+            print(
+                &quot;{msg} {proxy} as a {proxyType} proxy for {record}&quot;.format(
+                    msg=msg, proxy=prettyRecord(proxyRecord),
+                    proxyType=proxyType, record=prettyRecord(record)
+                )
+            )
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+@inlineCallbacks
</ins><span class="cx"> def action_addProxy(store, record, proxyType, *proxyIDs):
</span><del>-    return _addRemoveProxy(addDelegate, store, record, proxyType, *proxyIDs)
</del><ins>+    yield _addRemoveProxy(&quot;Added&quot;, addDelegate, store, record, proxyType, *proxyIDs)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def action_removeProxy(store, record, *proxyIDs):
</span><span class="cx">     # Write
</span><del>-    yield _addRemoveProxy(removeDelegate, store, record, &quot;write&quot;, *proxyIDs)
</del><ins>+    yield _addRemoveProxy(&quot;Removed&quot;, removeDelegate, store, record, &quot;write&quot;, *proxyIDs)
</ins><span class="cx">     # Read
</span><del>-    yield _addRemoveProxy(removeDelegate, store, record, &quot;read&quot;, *proxyIDs)
</del><ins>+    yield _addRemoveProxy(&quot;Removed&quot;, removeDelegate, store, record, &quot;read&quot;, *proxyIDs)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-# @inlineCallbacks
-# def setProxies(store, principal, readProxyPrincipals, writeProxyPrincipals, directory=None):
-#     &quot;&quot;&quot;
-#     Set read/write proxies en masse for a principal
-#     @param principal: DirectoryPrincipalResource
-#     @param readProxyPrincipals: a list of principal IDs (see principalForPrincipalID)
-#     @param writeProxyPrincipals: a list of principal IDs (see principalForPrincipalID)
-#     &quot;&quot;&quot;
</del><ins>+@inlineCallbacks
+def setProxies(record, readProxyRecords, writeProxyRecords):
+    &quot;&quot;&quot;
+    Set read/write proxies en masse for a record
+    @param record: L{IDirectoryRecord}
+    @param readProxyRecords: a list of records
+    @param writeProxyRecords: a list of records
+    &quot;&quot;&quot;
</ins><span class="cx"> 
</span><del>-#     proxyTypes = [
-#         (&quot;read&quot;, readProxyPrincipals),
-#         (&quot;write&quot;, writeProxyPrincipals),
-#     ]
-#     for proxyType, proxyIDs in proxyTypes:
-#         if proxyIDs is None:
-#             continue
-#         subPrincipal = proxySubprincipal(principal, proxyType)
-#         if subPrincipal is None:
-#             raise ProxyError(&quot;Unable to edit %s proxies for %s\n&quot; % (proxyType,
-#                 prettyPrincipal(principal)))
-#         memberURLs = []
-#         for proxyID in proxyIDs:
-#             proxyPrincipal = yield principalForPrincipalID(proxyID, directory=directory)
-#             proxyURL = proxyPrincipal.url()
-#             memberURLs.append(davxml.HRef(proxyURL))
-#         membersProperty = davxml.GroupMemberSet(*memberURLs)
-#         yield subPrincipal.writeProperty(membersProperty, None)
-#         if store is not None:
-#             # Schedule work the PeerConnectionPool will pick up as overdue
-#             yield schedulePolledGroupCachingUpdate(store)
</del><ins>+    proxyTypes = [
+        (DelegateRecordType.readDelegateGroup, readProxyRecords),
+        (DelegateRecordType.writeDelegateGroup, writeProxyRecords),
+    ]
+    for recordType, proxyRecords in proxyTypes:
+        if proxyRecords is None:
+            continue
+        proxyGroup = yield record.service.recordWithShortName(
+            recordType, record.uid
+        )
+        yield proxyGroup.setMembers(proxyRecords)
</ins><span class="cx"> 
</span><ins>+    # if store is not None:
+    #     # Schedule work the PeerConnectionPool will pick up as overdue
+    #     yield schedulePolledGroupCachingUpdate(store)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><del>-# @inlineCallbacks
-# def getProxies(principal, directory=None):
-#     &quot;&quot;&quot;
-#     Returns a tuple containing the GUIDs for read proxies and write proxies
-#     of the given principal
-#     &quot;&quot;&quot;
</del><span class="cx"> 
</span><del>-#     proxies = {
-#         &quot;read&quot;: [],
-#         &quot;write&quot;: [],
-#     }
-#     for proxyType in proxies.iterkeys():
-#         subPrincipal = proxySubprincipal(principal, proxyType)
-#         if subPrincipal is not None:
-#             membersProperty = (yield subPrincipal.readProperty(davxml.GroupMemberSet, None))
-#             if membersProperty.children:
-#                 for member in membersProperty.children:
-#                     proxyPrincipal = yield principalForPrincipalID(str(member), directory=directory)
-#                     proxies[proxyType].append(proxyPrincipal.record.guid)
</del><ins>+@inlineCallbacks
+def getProxies(record):
+    &quot;&quot;&quot;
+    Returns a tuple containing the records for read proxies and write proxies
+    of the given record
+    &quot;&quot;&quot;
</ins><span class="cx"> 
</span><del>-#     returnValue((proxies['read'], proxies['write']))
</del><ins>+    allProxies = {
+        DelegateRecordType.readDelegateGroup: [],
+        DelegateRecordType.writeDelegateGroup: [],
+    }
+    for recordType in allProxies.iterkeys():
+        proxyGroup = yield record.service.recordWithShortName(
+            recordType, record.uid
+        )
+        allProxies[recordType] = yield proxyGroup.members()
</ins><span class="cx"> 
</span><ins>+    returnValue(
+        (
+            allProxies[DelegateRecordType.readDelegateGroup],
+            allProxies[DelegateRecordType.writeDelegateGroup]
+        )
+    )
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> def action_getAutoScheduleMode(store, record):
</span><span class="cx">     print(
</span><span class="cx">         &quot;Auto-schedule mode for {record} is {mode}&quot;.format(
</span><span class="lines">@@ -782,6 +802,13 @@
</span><span class="cx">     this fancier later.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><ins>+    if len(args) != 3:
+        print(
+            &quot;When adding a principal, you must provide full-name, record-name, &quot;
+            &quot;and UID&quot;
+        )
+        sys.exit(64)
+
</ins><span class="cx">     fullName = args[0].decode(&quot;utf-8&quot;)
</span><span class="cx">     shortName = args[1].decode(&quot;utf-8&quot;)
</span><span class="cx">     uid = args[2].decode(&quot;utf-8&quot;)
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4calendarservertoolstestprincipalscaldavdplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/caldavd.plist (12985 => 12986)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/caldavd.plist        2014-03-21 02:05:52 UTC (rev 12985)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/caldavd.plist        2014-03-21 18:47:20 UTC (rev 12986)
</span><span class="lines">@@ -139,7 +139,7 @@
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.xmlfile.XMLDirectoryService&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;xmlFile&lt;/key&gt;
</span><span class="lines">@@ -159,7 +159,7 @@
</span><span class="cx">       &lt;true/&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.xmlfile.XMLDirectoryService&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;xmlFile&lt;/key&gt;
</span><span class="lines">@@ -168,17 +168,18 @@
</span><span class="cx">         &lt;array&gt;
</span><span class="cx">             &lt;string&gt;resources&lt;/string&gt;
</span><span class="cx">             &lt;string&gt;locations&lt;/string&gt;
</span><ins>+            &lt;string&gt;addresses&lt;/string&gt;
</ins><span class="cx">         &lt;/array&gt;
</span><span class="cx">       &lt;/dict&gt;
</span><span class="cx">     &lt;/dict&gt;
</span><del>-    
</del><ins>+
</ins><span class="cx">     &lt;!-- Open Directory Service (Mac OS X) --&gt;
</span><span class="cx">     &lt;!--
</span><span class="cx">     &lt;key&gt;DirectoryService&lt;/key&gt;
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.appleopendirectory.OpenDirectoryService&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;node&lt;/key&gt;
</span><span class="lines">@@ -202,7 +203,7 @@
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.augment.AugmentXMLDB&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;xmlFiles&lt;/key&gt;
</span><span class="lines">@@ -211,14 +212,14 @@
</span><span class="cx">         &lt;/array&gt;
</span><span class="cx">       &lt;/dict&gt;
</span><span class="cx">     &lt;/dict&gt;
</span><del>-    
</del><ins>+
</ins><span class="cx">     &lt;!-- Sqlite Augment Service --&gt;
</span><span class="cx">     &lt;!--
</span><span class="cx">     &lt;key&gt;AugmentService&lt;/key&gt;
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.augment.AugmentSqliteDB&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;dbpath&lt;/key&gt;
</span><span class="lines">@@ -233,7 +234,7 @@
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.augment.AugmentPostgreSQLDB&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;host&lt;/key&gt;
</span><span class="lines">@@ -249,7 +250,7 @@
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.calendaruserproxy.ProxySqliteDB&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;dbpath&lt;/key&gt;
</span><span class="lines">@@ -263,7 +264,7 @@
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;type&lt;/key&gt;
</span><span class="cx">       &lt;string&gt;twistedcaldav.directory.calendaruserproxy.ProxyPostgreSQLDB&lt;/string&gt;
</span><del>-      
</del><ins>+
</ins><span class="cx">       &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">       &lt;dict&gt;
</span><span class="cx">         &lt;key&gt;host&lt;/key&gt;
</span><span class="lines">@@ -692,7 +693,7 @@
</span><span class="cx">     &lt;!-- Support for Content-Encoding compression options as specified in RFC2616 Section 3.5 --&gt;
</span><span class="cx">     &lt;key&gt;ResponseCompression&lt;/key&gt;
</span><span class="cx">     &lt;false/&gt;
</span><del>-    
</del><ins>+
</ins><span class="cx">     &lt;!-- The retry-after value (in seconds) to return with a 503 error. --&gt;
</span><span class="cx">     &lt;key&gt;HTTPRetryAfter&lt;/key&gt;
</span><span class="cx">     &lt;integer&gt;180&lt;/integer&gt;
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4calendarservertoolstestprincipalsresourceslocationsxml"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/resources-locations.xml (12985 => 12986)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/resources-locations.xml        2014-03-21 02:05:52 UTC (rev 12985)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/resources-locations.xml        2014-03-21 18:47:20 UTC (rev 12986)
</span><span class="lines">@@ -18,7 +18,110 @@
</span><span class="cx"> 
</span><span class="cx"> &lt;!DOCTYPE accounts SYSTEM &quot;accounts.dtd&quot;&gt;
</span><span class="cx"> 
</span><del>-&lt;accounts realm=&quot;Test Realm&quot;&gt;
</del><ins>+&lt;directory realm=&quot;Test Realm&quot;&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location01&lt;/short-name&gt;
+    &lt;uid&gt;location01&lt;/uid&gt;
+    &lt;full-name&gt;Room 01&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location02&lt;/short-name&gt;
+    &lt;uid&gt;location02&lt;/uid&gt;
+    &lt;full-name&gt;Room 02&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location03&lt;/short-name&gt;
+    &lt;uid&gt;location03&lt;/uid&gt;
+    &lt;full-name&gt;Room 03&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location04&lt;/short-name&gt;
+    &lt;uid&gt;location04&lt;/uid&gt;
+    &lt;full-name&gt;Room 04&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location05&lt;/short-name&gt;
+    &lt;uid&gt;location05&lt;/uid&gt;
+    &lt;full-name&gt;Room 05&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location06&lt;/short-name&gt;
+    &lt;uid&gt;location06&lt;/uid&gt;
+    &lt;full-name&gt;Room 06&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location07&lt;/short-name&gt;
+    &lt;uid&gt;location07&lt;/uid&gt;
+    &lt;full-name&gt;Room 07&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location08&lt;/short-name&gt;
+    &lt;uid&gt;location08&lt;/uid&gt;
+    &lt;full-name&gt;Room 08&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location09&lt;/short-name&gt;
+    &lt;uid&gt;location09&lt;/uid&gt;
+    &lt;full-name&gt;Room 09&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;location&quot;&gt;
+    &lt;short-name&gt;location10&lt;/short-name&gt;
+    &lt;uid&gt;location10&lt;/uid&gt;
+    &lt;full-name&gt;Room 10&lt;/full-name&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource01&lt;/short-name&gt;
+    &lt;uid&gt;resource01&lt;/uid&gt;
+    &lt;full-name&gt;Resource 01&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource02&lt;/short-name&gt;
+    &lt;uid&gt;resource02&lt;/uid&gt;
+    &lt;full-name&gt;Resource 02&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource03&lt;/short-name&gt;
+    &lt;uid&gt;resource03&lt;/uid&gt;
+    &lt;full-name&gt;Resource 03&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource04&lt;/short-name&gt;
+    &lt;uid&gt;resource04&lt;/uid&gt;
+    &lt;full-name&gt;Resource 04&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource05&lt;/short-name&gt;
+    &lt;uid&gt;resource05&lt;/uid&gt;
+    &lt;full-name&gt;Resource 05&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource06&lt;/short-name&gt;
+    &lt;uid&gt;resource06&lt;/uid&gt;
+    &lt;full-name&gt;Resource 06&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource07&lt;/short-name&gt;
+    &lt;uid&gt;resource07&lt;/uid&gt;
+    &lt;full-name&gt;Resource 07&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource08&lt;/short-name&gt;
+    &lt;uid&gt;resource08&lt;/uid&gt;
+    &lt;full-name&gt;Resource 08&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource09&lt;/short-name&gt;
+    &lt;uid&gt;resource09&lt;/uid&gt;
+    &lt;full-name&gt;Resource 09&lt;/full-name&gt;
+  &lt;/record&gt;
+  &lt;record type=&quot;resource&quot;&gt;
+    &lt;short-name&gt;resource10&lt;/short-name&gt;
+    &lt;uid&gt;resource10&lt;/uid&gt;
+    &lt;full-name&gt;Resource 10&lt;/full-name&gt;
+  &lt;/record&gt;
+
+  &lt;!--
</ins><span class="cx">   &lt;location repeat=&quot;10&quot;&gt;
</span><span class="cx">     &lt;uid&gt;location%02d&lt;/uid&gt;
</span><span class="cx">     &lt;guid&gt;location%02d&lt;/guid&gt;
</span><span class="lines">@@ -31,4 +134,5 @@
</span><span class="cx">     &lt;password&gt;resource%02d&lt;/password&gt;
</span><span class="cx">     &lt;name&gt;Resource %02d&lt;/name&gt;
</span><span class="cx">   &lt;/resource&gt;
</span><del>-&lt;/accounts&gt;
</del><ins>+--&gt;
+&lt;/directory&gt;
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4calendarservertoolstestprincipalsusersgroupsxml"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/users-groups.xml (12985 => 12986)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/users-groups.xml        2014-03-21 02:05:52 UTC (rev 12985)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/principals/users-groups.xml        2014-03-21 18:47:20 UTC (rev 12986)
</span><span class="lines">@@ -18,7 +18,95 @@
</span><span class="cx"> 
</span><span class="cx"> &lt;!DOCTYPE accounts SYSTEM &quot;accounts.dtd&quot;&gt;
</span><span class="cx"> 
</span><del>-&lt;accounts realm=&quot;Test Realm&quot;&gt;
</del><ins>+&lt;directory realm=&quot;Test Realm&quot;&gt;
+ &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user01&lt;/short-name&gt;
+    &lt;uid&gt;user01&lt;/uid&gt;
+    &lt;password&gt;user01&lt;/password&gt;
+    &lt;full-name&gt;User 01&lt;/full-name&gt;
+    &lt;email&gt;user01@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user02&lt;/short-name&gt;
+    &lt;uid&gt;user02&lt;/uid&gt;
+    &lt;password&gt;user02&lt;/password&gt;
+    &lt;full-name&gt;User 02&lt;/full-name&gt;
+    &lt;email&gt;user02@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user03&lt;/short-name&gt;
+    &lt;uid&gt;user03&lt;/uid&gt;
+    &lt;password&gt;user03&lt;/password&gt;
+    &lt;full-name&gt;User 03&lt;/full-name&gt;
+    &lt;email&gt;user03@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user04&lt;/short-name&gt;
+    &lt;uid&gt;user04&lt;/uid&gt;
+    &lt;password&gt;user04&lt;/password&gt;
+    &lt;full-name&gt;User 04&lt;/full-name&gt;
+    &lt;email&gt;user04@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user05&lt;/short-name&gt;
+    &lt;uid&gt;user05&lt;/uid&gt;
+    &lt;password&gt;user05&lt;/password&gt;
+    &lt;full-name&gt;User 05&lt;/full-name&gt;
+    &lt;email&gt;user05@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user06&lt;/short-name&gt;
+    &lt;uid&gt;user06&lt;/uid&gt;
+    &lt;password&gt;user06&lt;/password&gt;
+    &lt;full-name&gt;User 06&lt;/full-name&gt;
+    &lt;email&gt;user06@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user07&lt;/short-name&gt;
+    &lt;uid&gt;user07&lt;/uid&gt;
+    &lt;password&gt;user07&lt;/password&gt;
+    &lt;full-name&gt;User 07&lt;/full-name&gt;
+    &lt;email&gt;user07@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user08&lt;/short-name&gt;
+    &lt;uid&gt;user08&lt;/uid&gt;
+    &lt;password&gt;user08&lt;/password&gt;
+    &lt;full-name&gt;User 08&lt;/full-name&gt;
+    &lt;email&gt;user08@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user09&lt;/short-name&gt;
+    &lt;uid&gt;user09&lt;/uid&gt;
+    &lt;password&gt;user09&lt;/password&gt;
+    &lt;full-name&gt;User 09&lt;/full-name&gt;
+    &lt;email&gt;user09@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user10&lt;/short-name&gt;
+    &lt;uid&gt;user10&lt;/uid&gt;
+    &lt;password&gt;user10&lt;/password&gt;
+    &lt;full-name&gt;User 10&lt;/full-name&gt;
+    &lt;email&gt;user10@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;group&quot;&gt;
+    &lt;uid&gt;e5a6142c-4189-4e9e-90b0-9cd0268b314b&lt;/uid&gt;
+    &lt;short-name&gt;testgroup1&lt;/short-name&gt;
+    &lt;full-name&gt;Group 01&lt;/full-name&gt;
+      &lt;member-uid type=&quot;users&quot;&gt;user01&lt;/member-uid&gt;
+      &lt;member-uid type=&quot;users&quot;&gt;user02&lt;/member-uid&gt;
+  &lt;/record&gt;
+  &lt;!--
</ins><span class="cx">   &lt;user repeat=&quot;10&quot;&gt;
</span><span class="cx">     &lt;uid&gt;user%02d&lt;/uid&gt;
</span><span class="cx">     &lt;guid&gt;user%02d&lt;/guid&gt;
</span><span class="lines">@@ -37,4 +125,5 @@
</span><span class="cx">       &lt;member type=&quot;users&quot;&gt;user02&lt;/member&gt;
</span><span class="cx">     &lt;/members&gt;
</span><span class="cx">   &lt;/group&gt;
</span><del>-&lt;/accounts&gt;
</del><ins>+  --&gt;
+&lt;/directory&gt;
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4calendarservertoolstesttest_principalspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_principals.py (12985 => 12986)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_principals.py        2014-03-21 02:05:52 UTC (rev 12985)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_principals.py        2014-03-21 18:47:20 UTC (rev 12986)
</span><span class="lines">@@ -19,18 +19,15 @@
</span><span class="cx"> 
</span><span class="cx"> from calendarserver.tools.principals import (
</span><span class="cx">     parseCreationArgs, matchStrings,
</span><del>-    updateRecord, principalForPrincipalID, getProxies, setProxies
</del><ins>+    recordForPrincipalID, getProxies, setProxies
</ins><span class="cx"> )
</span><span class="cx"> from twext.python.filepath import CachingFilePath as FilePath
</span><span class="cx"> from twisted.internet import reactor
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
</span><span class="cx"> from twistedcaldav.config import config
</span><del>-from twistedcaldav.directory import calendaruserproxy
-from twistedcaldav.directory.directory import DirectoryError
</del><span class="cx"> from twistedcaldav.test.util import (
</span><del>-    TestCase, CapturingProcessProtocol, ErrorOutput
</del><ins>+    TestCase, StoreTestCase, CapturingProcessProtocol, ErrorOutput
</ins><span class="cx"> )
</span><del>-from txdav.who.util import directoryFromConfig
</del><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -39,8 +36,8 @@
</span><span class="cx">     def setUp(self):
</span><span class="cx">         super(ManagePrincipalsTestCase, self).setUp()
</span><span class="cx"> 
</span><del>-        # Since this test operates on proxy db, we need to assign the service:
-        calendaruserproxy.ProxyDBService = calendaruserproxy.ProxySqliteDB(os.path.abspath(self.mktemp()))
</del><ins>+        # # Since this test operates on proxy db, we need to assign the service:
+        # calendaruserproxy.ProxyDBService = calendaruserproxy.ProxySqliteDB(os.path.abspath(self.mktemp()))
</ins><span class="cx"> 
</span><span class="cx">         testRoot = os.path.join(os.path.dirname(__file__), &quot;principals&quot;)
</span><span class="cx">         templateName = os.path.join(testRoot, &quot;caldavd.plist&quot;)
</span><span class="lines">@@ -50,11 +47,11 @@
</span><span class="cx"> 
</span><span class="cx">         databaseRoot = os.path.abspath(&quot;_spawned_scripts_db&quot; + str(os.getpid()))
</span><span class="cx">         newConfig = template % {
</span><del>-            &quot;ServerRoot&quot; : os.path.abspath(config.ServerRoot),
-            &quot;DataRoot&quot; : os.path.abspath(config.DataRoot),
-            &quot;DatabaseRoot&quot; : databaseRoot,
-            &quot;DocumentRoot&quot; : os.path.abspath(config.DocumentRoot),
-            &quot;LogRoot&quot; : os.path.abspath(config.LogRoot),
</del><ins>+            &quot;ServerRoot&quot;: os.path.abspath(config.ServerRoot),
+            &quot;DataRoot&quot;: os.path.abspath(config.DataRoot),
+            &quot;DatabaseRoot&quot;: databaseRoot,
+            &quot;DocumentRoot&quot;: os.path.abspath(config.DocumentRoot),
+            &quot;LogRoot&quot;: os.path.abspath(config.LogRoot),
</ins><span class="cx">         }
</span><span class="cx">         configFilePath = FilePath(os.path.join(config.ConfigRoot, &quot;caldavd.plist&quot;))
</span><span class="cx">         configFilePath.setContent(newConfig)
</span><span class="lines">@@ -62,18 +59,33 @@
</span><span class="cx">         self.configFileName = configFilePath.path
</span><span class="cx">         config.load(self.configFileName)
</span><span class="cx"> 
</span><del>-        origUsersFile = FilePath(os.path.join(os.path.dirname(__file__),
-            &quot;principals&quot;, &quot;users-groups.xml&quot;))
</del><ins>+        origUsersFile = FilePath(
+            os.path.join(
+                os.path.dirname(__file__),
+                &quot;principals&quot;,
+                &quot;users-groups.xml&quot;
+            )
+        )
</ins><span class="cx">         copyUsersFile = FilePath(os.path.join(config.DataRoot, &quot;accounts.xml&quot;))
</span><span class="cx">         origUsersFile.copyTo(copyUsersFile)
</span><span class="cx"> 
</span><del>-        origResourcesFile = FilePath(os.path.join(os.path.dirname(__file__),
-            &quot;principals&quot;, &quot;resources-locations.xml&quot;))
</del><ins>+        origResourcesFile = FilePath(
+            os.path.join(
+                os.path.dirname(__file__),
+                &quot;principals&quot;,
+                &quot;resources-locations.xml&quot;
+            )
+        )
</ins><span class="cx">         copyResourcesFile = FilePath(os.path.join(config.DataRoot, &quot;resources.xml&quot;))
</span><span class="cx">         origResourcesFile.copyTo(copyResourcesFile)
</span><span class="cx"> 
</span><del>-        origAugmentFile = FilePath(os.path.join(os.path.dirname(__file__),
-            &quot;principals&quot;, &quot;augments.xml&quot;))
</del><ins>+        origAugmentFile = FilePath(
+            os.path.join(
+                os.path.dirname(__file__),
+                &quot;principals&quot;,
+                &quot;augments.xml&quot;
+            )
+        )
</ins><span class="cx">         copyAugmentFile = FilePath(os.path.join(config.DataRoot, &quot;augments.xml&quot;))
</span><span class="cx">         origAugmentFile.copyTo(copyAugmentFile)
</span><span class="cx"> 
</span><span class="lines">@@ -116,6 +128,7 @@
</span><span class="cx">         self.assertTrue(&quot;users&quot; in results)
</span><span class="cx">         self.assertTrue(&quot;locations&quot; in results)
</span><span class="cx">         self.assertTrue(&quot;resources&quot; in results)
</span><ins>+        self.assertTrue(&quot;addresses&quot; in results)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -135,28 +148,36 @@
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_addRemove(self):
</span><del>-        results = yield self.runCommand(&quot;--add&quot;, &quot;resources&quot;, &quot;New Resource&quot;,
-            &quot;newresource&quot;, &quot;edaa6ae6-011b-4d89-ace3-6b688cdd91d9&quot;)
</del><ins>+        results = yield self.runCommand(
+            &quot;--add&quot;, &quot;resources&quot;,
+            &quot;New Resource&quot;, &quot;newresource&quot;, &quot;newresourceuid&quot;
+        )
</ins><span class="cx">         self.assertTrue(&quot;Added 'New Resource'&quot; in results)
</span><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--get-auto-schedule&quot;,
-            &quot;resources:newresource&quot;)
-        self.assertTrue(results.startswith('Auto-schedule for &quot;New Resource&quot; (resources:newresource) is true'))
</del><ins>+        results = yield self.runCommand(
+            &quot;--get-auto-schedule-mode&quot;,
+            &quot;resources:newresource&quot;
+        )
+        self.assertTrue(
+            results.startswith(
+                'Auto-schedule mode for &quot;New Resource&quot; newresourceuid (resource) newresource is Default'
+            )
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--get-auto-schedule-mode&quot;,
-            &quot;resources:newresource&quot;)
-        self.assertTrue(results.startswith('Auto-schedule mode for &quot;New Resource&quot; (resources:newresource) is default'))
-
</del><span class="cx">         results = yield self.runCommand(&quot;--list-principals=resources&quot;)
</span><span class="cx">         self.assertTrue(&quot;newresource&quot; in results)
</span><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--add&quot;, &quot;resources&quot;, &quot;New Resource&quot;,
-            &quot;newresource1&quot;, &quot;edaa6ae6-011b-4d89-ace3-6b688cdd91d9&quot;)
-        self.assertTrue(&quot;Duplicate guid&quot; in results)
</del><ins>+        results = yield self.runCommand(
+            &quot;--add&quot;, &quot;resources&quot;, &quot;New Resource&quot;,
+            &quot;newresource1&quot;, &quot;newresourceuid&quot;
+        )
+        self.assertTrue(&quot;UID already in use: newresourceuid&quot; in results)
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--add&quot;, &quot;resources&quot;, &quot;New Resource&quot;,
-            &quot;newresource&quot;, &quot;fdaa6ae6-011b-4d89-ace3-6b688cdd91d9&quot;)
-        self.assertTrue(&quot;Duplicate shortName&quot; in results)
</del><ins>+        results = yield self.runCommand(
+            &quot;--add&quot;, &quot;resources&quot;, &quot;New Resource&quot;,
+            &quot;newresource&quot;, &quot;uniqueuid&quot;
+        )
+        self.assertTrue(&quot;Record name already in use&quot; in results)
</ins><span class="cx"> 
</span><span class="cx">         results = yield self.runCommand(&quot;--remove&quot;, &quot;resources:newresource&quot;)
</span><span class="cx">         self.assertTrue(&quot;Removed 'New Resource'&quot; in results)
</span><span class="lines">@@ -167,29 +188,13 @@
</span><span class="cx"> 
</span><span class="cx">     def test_parseCreationArgs(self):
</span><span class="cx"> 
</span><del>-        self.assertEquals((&quot;full name&quot;, None, None),
-            parseCreationArgs((&quot;full name&quot;,)))
-
-        self.assertEquals((&quot;full name&quot;, &quot;short name&quot;, None),
-            parseCreationArgs((&quot;full name&quot;, &quot;short name&quot;)))
-
-        guid = &quot;02C3DE93-E655-4856-47B76B8BB1A7BDCE&quot;
-
-        self.assertEquals((&quot;full name&quot;, &quot;short name&quot;, guid),
-            parseCreationArgs((&quot;full name&quot;, &quot;short name&quot;, guid)))
-
-        self.assertEquals((&quot;full name&quot;, &quot;short name&quot;, guid),
-            parseCreationArgs((&quot;full name&quot;, guid, &quot;short name&quot;)))
-
-        self.assertEquals((&quot;full name&quot;, None, guid),
-            parseCreationArgs((&quot;full name&quot;, guid)))
-
-        self.assertRaises(
-            ValueError,
-            parseCreationArgs, (&quot;full name&quot;, &quot;non guid&quot;, &quot;non guid&quot;)
</del><ins>+        self.assertEquals(
+            (&quot;full name&quot;, &quot;short name&quot;, &quot;uid&quot;),
+            parseCreationArgs((&quot;full name&quot;, &quot;short name&quot;, &quot;uid&quot;))
</ins><span class="cx">         )
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def test_matchStrings(self):
</span><span class="cx">         self.assertEquals(&quot;abc&quot;, matchStrings(&quot;a&quot;, (&quot;abc&quot;, &quot;def&quot;)))
</span><span class="cx">         self.assertEquals(&quot;def&quot;, matchStrings(&quot;de&quot;, (&quot;abc&quot;, &quot;def&quot;)))
</span><span class="lines">@@ -201,161 +206,126 @@
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_modifyWriteProxies(self):
</span><del>-        results = yield self.runCommand(&quot;--add-write-proxy=users:user01&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Added &quot;Test User 01&quot; (users:user01) as a write proxy for &quot;Room 01&quot; (locations:location01)'))
</del><ins>+        results = yield self.runCommand(
+            &quot;--add-write-proxy=users:user01&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(
+            results.startswith('Added &quot;User 01&quot; user01 (user) user01 as a write proxy for &quot;Room 01&quot; location01 (location) location01')
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--list-write-proxies&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(&quot;Test User 01&quot; in results)
</del><ins>+        results = yield self.runCommand(
+            &quot;--list-write-proxies&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(&quot;User 01&quot; in results)
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--remove-proxy=users:user01&quot;,
-            &quot;locations:location01&quot;)
</del><ins>+        results = yield self.runCommand(
+            &quot;--remove-proxy=users:user01&quot;, &quot;locations:location01&quot;
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--list-write-proxies&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue('No write proxies for &quot;Room 01&quot; (locations:location01)' in results)
</del><ins>+        results = yield self.runCommand(
+            &quot;--list-write-proxies&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(
+            'No write proxies for &quot;Room 01&quot; location01 (location) location01' in results
+        )
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_modifyReadProxies(self):
</span><del>-        results = yield self.runCommand(&quot;--add-read-proxy=users:user01&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Added &quot;Test User 01&quot; (users:user01) as a read proxy for &quot;Room 01&quot; (locations:location01)'))
</del><ins>+        results = yield self.runCommand(
+            &quot;--add-read-proxy=users:user01&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(
+            results.startswith('Added &quot;User 01&quot; user01 (user) user01 as a read proxy for &quot;Room 01&quot; location01 (location) location01')
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--list-read-proxies&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(&quot;Test User 01&quot; in results)
</del><ins>+        results = yield self.runCommand(
+            &quot;--list-read-proxies&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(&quot;User 01&quot; in results)
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--remove-proxy=users:user01&quot;,
-            &quot;locations:location01&quot;)
</del><ins>+        results = yield self.runCommand(
+            &quot;--remove-proxy=users:user01&quot;, &quot;locations:location01&quot;
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--list-read-proxies&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue('No read proxies for &quot;Room 01&quot; (locations:location01)' in results)
</del><ins>+        results = yield self.runCommand(
+            &quot;--list-read-proxies&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(
+            'No read proxies for &quot;Room 01&quot; location01 (location) location01' in results
+        )
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def test_autoSchedule(self):
-        results = yield self.runCommand(&quot;--get-auto-schedule&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Auto-schedule for &quot;Room 01&quot; (locations:location01) is false'))
-
-        results = yield self.runCommand(&quot;--set-auto-schedule=true&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Setting auto-schedule to true for &quot;Room 01&quot; (locations:location01)'))
-
-        results = yield self.runCommand(&quot;--get-auto-schedule&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Auto-schedule for &quot;Room 01&quot; (locations:location01) is true'))
-
-        results = yield self.runCommand(&quot;--set-auto-schedule=true&quot;,
-            &quot;users:user01&quot;)
-        self.assertTrue(results.startswith('Enabling auto-schedule for (users)user01 is not allowed.'))
-
-
-    @inlineCallbacks
</del><span class="cx">     def test_autoScheduleMode(self):
</span><del>-        results = yield self.runCommand(&quot;--get-auto-schedule-mode&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Auto-schedule mode for &quot;Room 01&quot; (locations:location01) is default'))
</del><ins>+        results = yield self.runCommand(
+            &quot;--get-auto-schedule-mode&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(
+            results.startswith('Auto-schedule mode for &quot;Room 01&quot; location01 (location) location01 is Default')
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--set-auto-schedule-mode=accept-if-free&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Setting auto-schedule mode to accept-if-free for &quot;Room 01&quot; (locations:location01)'))
</del><ins>+        results = yield self.runCommand(
+            &quot;--set-auto-schedule-mode=accept-if-free&quot;, &quot;locations:location01&quot;
+        )
+        self.assertTrue(
+            results.startswith('Setting auto-schedule-mode to accept if free for &quot;Room 01&quot; location01 (location) location01')
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--get-auto-schedule-mode&quot;,
-            &quot;locations:location01&quot;)
-        self.assertTrue(results.startswith('Auto-schedule mode for &quot;Room 01&quot; (locations:location01) is accept-if-free'))
</del><ins>+        results = yield self.runCommand(
+            &quot;--get-auto-schedule-mode&quot;,
+            &quot;locations:location01&quot;
+        )
+        self.assertTrue(
+            results.startswith('Auto-schedule mode for &quot;Room 01&quot; location01 (location) location01 is accept if free')
+        )
</ins><span class="cx"> 
</span><del>-        results = yield self.runCommand(&quot;--set-auto-schedule-mode=decline-if-busy&quot;,
-            &quot;users:user01&quot;)
-        self.assertTrue(results.startswith('Setting auto-schedule mode for (users)user01 is not allowed.'))
</del><ins>+        results = yield self.runCommand(
+            &quot;--set-auto-schedule-mode=decline-if-busy&quot;, &quot;users:user01&quot;
+        )
+        self.assertTrue(results.startswith('Setting auto-schedule-mode for &quot;User 01&quot; user01 (user) user01 is not allowed.'))
</ins><span class="cx"> 
</span><span class="cx">         try:
</span><del>-            results = yield self.runCommand(&quot;--set-auto-schedule-mode=bogus&quot;,
-                &quot;users:user01&quot;)
</del><ins>+            results = yield self.runCommand(
+                &quot;--set-auto-schedule-mode=bogus&quot;,
+                &quot;users:user01&quot;
+            )
</ins><span class="cx">         except ErrorOutput:
</span><span class="cx">             pass
</span><span class="cx">         else:
</span><span class="cx">             self.fail(&quot;Expected command failure&quot;)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    @inlineCallbacks
-    def test_updateRecord(self):
-        directory = directoryFromConfig(config)
-        guid = &quot;EEE28807-A8C5-46C8-A558-A08281C558A7&quot;
</del><span class="cx"> 
</span><del>-        (yield updateRecord(True, directory, &quot;locations&quot;,
-            guid=guid, fullName=&quot;Test Location&quot;, shortNames=[&quot;testlocation&quot;, ],)
-        )
-        try:
-            (yield updateRecord(True, directory, &quot;locations&quot;,
-                guid=guid, fullName=&quot;Test Location&quot;, shortNames=[&quot;testlocation&quot;, ],)
-            )
-        except DirectoryError:
-            # We're expecting an error for trying to create a record with
-            # an existing GUID
-            pass
-        else:
-            raise self.failureException(&quot;Duplicate guid expected&quot;)
</del><ins>+class SetProxiesTestCase(StoreTestCase):
</ins><span class="cx"> 
</span><del>-        record = directory.recordWithGUID(guid)
-        self.assertTrue(record is not None)
-        self.assertEquals(record.fullName, &quot;Test Location&quot;)
-        self.assertTrue(record.autoSchedule)
-
-        (yield updateRecord(False, directory, &quot;locations&quot;,
-            guid=guid, fullName=&quot;Changed&quot;, shortNames=[&quot;testlocation&quot;, ],)
-        )
-        record = directory.recordWithGUID(guid)
-        self.assertTrue(record is not None)
-        self.assertEquals(record.fullName, &quot;Changed&quot;)
-
-        directory.destroyRecord(&quot;locations&quot;, guid=guid)
-        record = directory.recordWithGUID(guid)
-        self.assertTrue(record is None)
-
-        # Create a user, change autoSchedule
-        guid = &quot;F0DE73A8-39D4-4830-8D32-1FA03ABA3470&quot;
-        (yield updateRecord(True, directory, &quot;users&quot;,
-            guid=guid, fullName=&quot;Test User&quot;, shortNames=[&quot;testuser&quot;, ],
-            autoSchedule=True)
-        )
-        record = directory.recordWithGUID(guid)
-        self.assertTrue(record is not None)
-        self.assertEquals(record.fullName, &quot;Test User&quot;)
-        self.assertTrue(record.autoSchedule)
-
-        (yield updateRecord(False, directory, &quot;users&quot;,
-            guid=guid, fullName=&quot;Test User&quot;, shortNames=[&quot;testuser&quot;, ],
-            autoSchedule=False)
-        )
-        record = directory.recordWithGUID(guid)
-        self.assertTrue(record is not None)
-        self.assertEquals(record.fullName, &quot;Test User&quot;)
-        self.assertFalse(record.autoSchedule)
-
-
</del><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_setProxies(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Read and Write proxies can be set en masse
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        directory = directoryFromConfig(config)
</del><ins>+        directory = self.directory
+        record = yield recordForPrincipalID(directory, &quot;users:user01&quot;)
</ins><span class="cx"> 
</span><del>-        principal = principalForPrincipalID(&quot;users:user01&quot;, directory=directory)
-        readProxies, writeProxies = (yield getProxies(principal, directory=directory))
-        self.assertEquals(readProxies, []) # initially empty
-        self.assertEquals(writeProxies, []) # initially empty
</del><ins>+        readProxies, writeProxies = yield getProxies(record)
+        self.assertEquals(readProxies, [])  # initially empty
+        self.assertEquals(writeProxies, [])  # initially empty
</ins><span class="cx"> 
</span><del>-        (yield setProxies(None, principal, [&quot;users:user03&quot;, &quot;users:user04&quot;], [&quot;users:user05&quot;], directory=directory))
-        readProxies, writeProxies = (yield getProxies(principal, directory=directory))
-        self.assertEquals(set(readProxies), set([&quot;user03&quot;, &quot;user04&quot;]))
-        self.assertEquals(set(writeProxies), set([&quot;user05&quot;]))
</del><ins>+        readProxies = [
+            (yield recordForPrincipalID(directory, &quot;users:user03&quot;)),
+            (yield recordForPrincipalID(directory, &quot;users:user04&quot;)),
+        ]
+        writeProxies = [
+            (yield recordForPrincipalID(directory, &quot;users:user05&quot;)),
+        ]
+        yield setProxies(record, readProxies, writeProxies)
</ins><span class="cx"> 
</span><ins>+        readProxies, writeProxies = yield getProxies(record)
+        self.assertEquals(set([r.uid for r in readProxies]), set([&quot;user03&quot;, &quot;user04&quot;]))
+        self.assertEquals(set([r.uid for r in writeProxies]), set([&quot;user05&quot;]))
+
</ins><span class="cx">         # Using None for a proxy list indicates a no-op
</span><del>-        (yield setProxies(None, principal, [], None, directory=directory))
-        readProxies, writeProxies = (yield getProxies(principal, directory=directory))
-        self.assertEquals(readProxies, []) # now empty
-        self.assertEquals(set(writeProxies), set([&quot;user05&quot;])) # unchanged
</del><ins>+        yield setProxies(record, [], None)
+        readProxies, writeProxies = yield getProxies(record)
+        self.assertEquals(readProxies, [])  # now empty
+        self.assertEquals(set([r.uid for r in writeProxies]), set([&quot;user05&quot;]))  # unchanged
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectorytestaccountsxml"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/accounts.xml (12985 => 12986)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/accounts.xml        2014-03-21 02:05:52 UTC (rev 12985)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/accounts.xml        2014-03-21 18:47:20 UTC (rev 12986)
</span><span class="lines">@@ -170,6 +170,23 @@
</span><span class="cx">     &lt;email&gt;user04@example.com&lt;/email&gt;
</span><span class="cx">   &lt;/record&gt;
</span><span class="cx"> 
</span><ins>+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user05&lt;/short-name&gt;
+    &lt;uid&gt;user05&lt;/uid&gt;
+    &lt;password&gt;user05&lt;/password&gt;
+    &lt;full-name&gt;User 05&lt;/full-name&gt;
+    &lt;email&gt;user05@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+  &lt;record type=&quot;user&quot;&gt;
+    &lt;short-name&gt;user06&lt;/short-name&gt;
+    &lt;uid&gt;user06&lt;/uid&gt;
+    &lt;password&gt;user06&lt;/password&gt;
+    &lt;full-name&gt;User 06&lt;/full-name&gt;
+    &lt;email&gt;user06@example.com&lt;/email&gt;
+  &lt;/record&gt;
+
+
</ins><span class="cx">   &lt;!-- Repeat is not (yet?) supported in twext.who.xml
</span><span class="cx">   &lt;user repeat=&quot;100&quot;&gt;
</span><span class="cx">     &lt;short-name&gt;user%02d&lt;/short-name&gt;
</span></span></pre>
</div>
</div>

</body>
</html>