<!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>[12897] CalendarServer/branches/users/sagen/move2who-2</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/12897">12897</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2014-03-13 13:33:25 -0700 (Thu, 13 Mar 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Move directoryFromConfig to its own module.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssagenmove2who2calendarservertapcaldavpy">CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/caldav.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2calendarservertaptesttest_utilpy">CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/test/test_util.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2calendarservertoolstesttest_principalspy">CalendarServer/branches/users/sagen/move2who-2/calendarserver/tools/test/test_principals.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2twistedcaldavstdconfigpy">CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/stdconfig.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2twistedcaldavtestutilpy">CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/test/util.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavcaldavdatastoretesttest_attachmentspy">CalendarServer/branches/users/sagen/move2who-2/txdav/caldav/datastore/test/test_attachments.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavdpsclientpy">CalendarServer/branches/users/sagen/move2who-2/txdav/dps/client.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavdpsserverpy">CalendarServer/branches/users/sagen/move2who-2/txdav/dps/server.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavwhodirectorypy">CalendarServer/branches/users/sagen/move2who-2/txdav/who/directory.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavwhotestaccountsaccountsxml">CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/accounts.xml</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavwhotestaccountsresourcesxml">CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/resources.xml</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavwhotestaccountsaugmentsxml">CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/augments.xml</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavwhotesttest_utilpy">CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/test_util.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who2txdavwhoutilpy">CalendarServer/branches/users/sagen/move2who-2/txdav/who/util.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssagenmove2who2calendarservertapcaldavpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/caldav.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/caldav.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/caldav.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -86,7 +86,7 @@
</span><span class="cx"> from txdav.common.datastore.work.revision_cleanup import (
</span><span class="cx"> scheduleFirstFindMinRevision
</span><span class="cx"> )
</span><del>-from txdav.dps.server import directoryFromConfig
</del><ins>+from txdav.who.util import directoryFromConfig
</ins><span class="cx"> from txdav.dps.client import DirectoryService as DirectoryProxyClientService
</span><span class="cx"> from txdav.who.groups import GroupCacher
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2calendarservertaptesttest_utilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/test/test_util.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/test/test_util.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/calendarserver/tap/test/test_util.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -21,7 +21,7 @@
</span><span class="cx"> from twistedcaldav.directory.augment import AugmentXMLDB
</span><span class="cx"> from twisted.internet.task import Clock
</span><span class="cx"> from twisted.internet.defer import succeed, inlineCallbacks
</span><del>-from txdav.dps.server import directoryFromConfig
</del><ins>+from txdav.who.util import directoryFromConfig
</ins><span class="cx">
</span><span class="cx"> class ProcessCountTestCase(TestCase):
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2calendarservertoolstesttest_principalspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/calendarserver/tools/test/test_principals.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/calendarserver/tools/test/test_principals.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/calendarserver/tools/test/test_principals.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> from twistedcaldav.test.util import (
</span><span class="cx"> TestCase, CapturingProcessProtocol, ErrorOutput
</span><span class="cx"> )
</span><del>-from txdav.dps.server import directoryFromConfig
</del><ins>+from txdav.who.util import directoryFromConfig
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2twistedcaldavstdconfigpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/stdconfig.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/stdconfig.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/stdconfig.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -374,6 +374,7 @@
</span><span class="cx"> # users, groups, locations and resources) to the server.
</span><span class="cx"> #
</span><span class="cx"> "DirectoryService": {
</span><ins>+ "Enabled": True,
</ins><span class="cx"> "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService",
</span><span class="cx"> "params": DEFAULT_SERVICE_PARAMS["twistedcaldav.directory.xmlfile.XMLDirectoryService"],
</span><span class="cx"> },
</span><span class="lines">@@ -385,7 +386,7 @@
</span><span class="cx"> # and resources.
</span><span class="cx"> #
</span><span class="cx"> "ResourceService": {
</span><del>- "Enabled" : True,
</del><ins>+ "Enabled": True,
</ins><span class="cx"> "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService",
</span><span class="cx"> "params": DEFAULT_RESOURCE_PARAMS["twistedcaldav.directory.xmlfile.XMLDirectoryService"],
</span><span class="cx"> },
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2twistedcaldavtestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/test/util.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/test/util.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/twistedcaldav/test/util.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx"> from txdav.caldav.datastore.test.util import buildCalendarStore
</span><span class="cx"> from txdav.common.datastore.file import CommonDataStore
</span><span class="cx"> from txdav.common.datastore.test.util import deriveQuota, CommonCommonTests
</span><del>-from txdav.dps.server import directoryFromConfig
</del><ins>+from txdav.who.util import directoryFromConfig
</ins><span class="cx"> from txdav.xml import element as davxml, element
</span><span class="cx"> from txweb2.dav.test.util import SimpleRequest
</span><span class="cx"> import txweb2.dav.test.util
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavcaldavdatastoretesttest_attachmentspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/txdav/caldav/datastore/test/test_attachments.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/caldav/datastore/test/test_attachments.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/caldav/datastore/test/test_attachments.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -14,7 +14,7 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx">
</span><del>-from txdav.dps.server import directoryFromConfig
</del><ins>+from txdav.who.util import directoryFromConfig
</ins><span class="cx">
</span><span class="cx"> from pycalendar.datetime import DateTime
</span><span class="cx"> from pycalendar.value import Value
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavdpsclientpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/txdav/dps/client.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/dps/client.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/dps/client.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -226,7 +226,9 @@
</span><span class="cx"> recordType=recordType.name.encode("utf-8")
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+ listRecords = recordsWithRecordType
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def recordsWithEmailAddress(self, emailAddress):
</span><span class="cx"> return self._call(
</span><span class="cx"> RecordsWithEmailAddressCommand,
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavdpsserverpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/txdav/dps/server.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/dps/server.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/dps/server.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -15,28 +15,20 @@
</span><span class="cx"> ##
</span><span class="cx">
</span><span class="cx"> import cPickle as pickle
</span><del>-import os
</del><span class="cx"> import uuid
</span><span class="cx">
</span><del>-from calendarserver.tap.util import getDBPool, storeFromConfig
</del><span class="cx"> from twext.python.log import Logger
</span><del>-from twext.who.aggregate import DirectoryService as AggregateDirectoryService
</del><span class="cx"> from twext.who.expression import MatchType, MatchFlags, Operand
</span><del>-from twext.who.idirectory import RecordType, DirectoryConfigurationError
-from twext.who.ldap import DirectoryService as LDAPDirectoryService
-from twext.who.util import ConstantsContainer
</del><ins>+from twext.who.idirectory import RecordType
</ins><span class="cx"> from twisted.application import service
</span><span class="cx"> from twisted.application.strports import service as strPortsService
</span><del>-from twisted.cred.credentials import UsernamePassword
</del><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><span class="cx"> from twisted.internet.protocol import Factory
</span><span class="cx"> from twisted.plugin import IPlugin
</span><span class="cx"> from twisted.protocols import amp
</span><span class="cx"> from twisted.python.constants import Names, NamedConstant
</span><del>-from twisted.python.filepath import FilePath
-from twisted.python.reflect import namedClass
</del><span class="cx"> from twisted.python.usage import Options, UsageError
</span><del>-from twistedcaldav.config import config, fullServerPath
</del><ins>+from twistedcaldav.config import config
</ins><span class="cx"> from twistedcaldav.stdconfig import DEFAULT_CONFIG, DEFAULT_CONFIG_FILE
</span><span class="cx"> from txdav.dps.commands import (
</span><span class="cx"> RecordWithShortNameCommand, RecordWithUIDCommand, RecordWithGUIDCommand,
</span><span class="lines">@@ -46,12 +38,10 @@
</span><span class="cx"> VerifyPlaintextPasswordCommand, VerifyHTTPDigestCommand,
</span><span class="cx"> # UpdateRecordsCommand, RemoveRecordsCommand
</span><span class="cx"> )
</span><del>-from txdav.who.augment import AugmentedDirectoryService
-from txdav.who.delegates import DirectoryService as DelegateDirectoryService
-from txdav.who.idirectory import RecordType as CalRecordType
-from txdav.who.xml import DirectoryService as XMLDirectoryService
</del><ins>+from txdav.who.util import directoryFromConfig
</ins><span class="cx"> from zope.interface import implementer
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> log = Logger()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -449,130 +439,6 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-def directoryFromConfig(config, store=None):
- """
- Return a directory service based on the config. If you want to go through
- AMP to talk to one of these as a client, instantiate
- txdav.dps.client.DirectoryService
- """
-
- # MOVE2WHO FIXME: this needs to talk to its own separate database. In fact,
- # don't pass store=None if you already have called storeFromConfig()
- # within this process. Pass the existing store in here.
- pool, txnFactory = getDBPool(config)
- if store is None:
- store = storeFromConfig(config, txnFactory, None)
-
- aggregatedServices = []
-
- for serviceKey in ("DirectoryService", "ResourceService"):
- serviceValue = config.get(serviceKey, None)
- directoryType = serviceValue.type.lower()
- params = serviceValue.params
-
- if "xml" in directoryType:
- xmlFile = params.xmlFile
- xmlFile = fullServerPath(config.DataRoot, xmlFile)
- # path = kwds.pop("path", "")
- if not xmlFile or not os.path.exists(xmlFile):
- log.error("Path not found for XML directory: {p}", p=xmlFile)
- fp = FilePath(xmlFile)
- directory = XMLDirectoryService(fp)
-
- elif "opendirectory" in directoryType:
- from twext.who.opendirectory import DirectoryService as ODDirectoryService
- directory = ODDirectoryService()
-
- elif "ldap" in directoryType:
- if params.credentials.dn and params.credentials.password:
- creds = UsernamePassword(params.credentials.dn,
- params.credentials.password)
- else:
- creds = None
- directory = LDAPDirectoryService(
- params.uri,
- params.rdnSchema.base,
- creds=creds
- )
-
- else:
- log.error("Invalid DirectoryType: {dt}", dt=directoryType)
- raise DirectoryConfigurationError
-
- # Set the appropriate record types on each service
- types = []
- for recordTypeName in params.recordTypes:
- recordType = {
- "users": RecordType.user,
- "groups": RecordType.group,
- "locations": CalRecordType.location,
- "resources": CalRecordType.resource,
- "addresses": CalRecordType.address,
- }.get(recordTypeName, None)
- if recordType is None:
- log.error("Invalid Record Type: {rt}", rt=recordTypeName)
- raise DirectoryConfigurationError
- if recordType in types:
- log.error("Duplicate Record Type: {rt}", rt=recordTypeName)
- raise DirectoryConfigurationError
- types.append(recordType)
-
- directory.recordType = ConstantsContainer(types)
- aggregatedServices.append(directory)
-
- #
- # Setup the Augment Service
- #
- if config.AugmentService.type:
- augmentClass = namedClass(config.AugmentService.type)
- log.info(
- "Configuring augment service of type: {augmentClass}",
- augmentClass=augmentClass
- )
- try:
- augmentService = augmentClass(**config.AugmentService.params)
- except IOError:
- log.error("Could not start augment service")
- raise
- else:
- augmentService = None
-
- userDirectory = None
- for directory in aggregatedServices:
- if RecordType.user in directory.recordTypes():
- userDirectory = directory
- break
- else:
- log.error("No directory service set up for users")
- raise DirectoryConfigurationError
-
- delegateDirectory = DelegateDirectoryService(
- userDirectory.realmName,
- store
- )
- aggregatedServices.append(delegateDirectory)
-
- aggregateDirectory = AggregateDirectoryService(
- userDirectory.realmName, aggregatedServices
- )
- try:
- augmented = AugmentedDirectoryService(
- aggregateDirectory, store, augmentService
- )
-
- # The delegate directory needs a way to look up user/group records
- # so hand it a reference to the augmented directory.
- # FIXME: is there a better pattern to use here?
- delegateDirectory.setMasterDirectory(augmented)
-
- except Exception as e:
- log.error("Could not create directory service", error=e)
- raise
-
- return augmented
-
-
-
</del><span class="cx"> @implementer(IPlugin, service.IServiceMaker)
</span><span class="cx"> class DirectoryProxyServiceMaker(object):
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavwhodirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/txdav/who/directory.py (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/who/directory.py        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/who/directory.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -28,11 +28,9 @@
</span><span class="cx"> from twext.who.idirectory import RecordType as BaseRecordType
</span><span class="cx"> from twisted.cred.credentials import UsernamePassword
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><del>-from txdav.caldav.datastore.scheduling.cuaddress import normalizeCUAddr
</del><span class="cx"> from txdav.who.idirectory import RecordType as DAVRecordType
</span><span class="cx"> from txweb2.auth.digest import DigestedCredentials
</span><span class="cx">
</span><del>-
</del><span class="cx"> log = Logger()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -42,6 +40,7 @@
</span><span class="cx"> ]
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class CalendarDirectoryServiceMixin(object):
</span><span class="cx">
</span><span class="cx"> guid = "1332A615-4D3A-41FE-B636-FBE25BFB982E"
</span><span class="lines">@@ -59,6 +58,8 @@
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def recordWithCalendarUserAddress(self, address):
</span><ins>+ # FIXME: moved this here to avoid circular import problems
+ from txdav.caldav.datastore.scheduling.cuaddress import normalizeCUAddr
</ins><span class="cx"> address = normalizeCUAddr(address)
</span><span class="cx"> record = None
</span><span class="cx"> if address.startswith("urn:uuid:"):
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavwhotestaccountsaccountsxml"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/accounts.xml (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/accounts.xml        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/accounts.xml        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -18,175 +18,339 @@
</span><span class="cx">
</span><span class="cx"> <!DOCTYPE accounts SYSTEM "accounts.dtd">
</span><span class="cx">
</span><del>-<accounts realm="Test Realm">
- <user>
</del><ins>+<directory realm="Test Realm">
+ <record type="user">
</ins><span class="cx"> <uid>admin</uid>
</span><del>- <guid>admin</guid>
</del><ins>+ <short-name>admin</short-name>
</ins><span class="cx"> <password>admin</password>
</span><del>- <name>Super User</name>
- <first-name>Super</first-name>
- <last-name>User</last-name>
- </user>
- <user>
</del><ins>+ <full-name>Super User</full-name>
+ </record>
+ <record type="user">
</ins><span class="cx"> <uid>apprentice</uid>
</span><del>- <guid>apprentice</guid>
</del><ins>+ <short-name>apprentice</short-name>
</ins><span class="cx"> <password>apprentice</password>
</span><del>- <name>Apprentice Super User</name>
- <first-name>Apprentice</first-name>
- <last-name>Super User</last-name>
- </user>
- <user>
</del><ins>+ <full-name>Apprentice Super User</full-name>
+ </record>
+ <record type="user">
</ins><span class="cx"> <uid>wsanchez</uid>
</span><del>- <guid>wsanchez</guid>
- <email-address>wsanchez@example.com</email-address>
</del><ins>+ <short-name>wsanchez</short-name>
+ <email>wsanchez@example.com</email>
</ins><span class="cx"> <password>test</password>
</span><del>- <name>Wilfredo Sanchez Vega</name>
- <first-name>Wilfredo</first-name>
- <last-name>Sanchez Vega</last-name>
- <auto-schedule-mode><accept-if-free-decline-if-busy /></auto-schedule-mode>
- </user>
- <user>
</del><ins>+ <full-name>Wilfredo Sanchez Vega</full-name>
+ </record>
+ <record type="user">
</ins><span class="cx"> <uid>cdaboo</uid>
</span><del>- <guid>cdaboo</guid>
- <email-address>cdaboo@example.com</email-address>
</del><ins>+ <short-name>cdaboo</short-name>
+ <email>cdaboo@example.com</email>
</ins><span class="cx"> <password>test</password>
</span><del>- <name>Cyrus Daboo</name>
- <first-name>Cyrus</first-name>
- <last-name>Daboo</last-name>
- </user>
- <user>
</del><ins>+ <full-name>cyrus Daboo</full-name>
+ </record>
+ <record type="user">
</ins><span class="cx"> <uid>sagen</uid>
</span><del>- <guid>sagen</guid>
- <email-address>sagen@example.com</email-address>
</del><ins>+ <short-name>sagen</short-name>
+ <email>sagen@example.com</email>
</ins><span class="cx"> <password>test</password>
</span><del>- <name>Morgen Sagen</name>
- <first-name>Morgen</first-name>
- <last-name>Sagen</last-name>
- </user>
- <user>
</del><ins>+ <full-name>Morgen Sagen</full-name>
+ </record>
+ <record type="user">
</ins><span class="cx"> <uid>dre</uid>
</span><del>- <guid>andre</guid>
- <email-address>dre@example.com</email-address>
</del><ins>+ <short-name>andre</short-name>
+ <email>dre@example.com</email>
</ins><span class="cx"> <password>test</password>
</span><del>- <name>Andre LaBranche</name>
- <first-name>Andre</first-name>
- <last-name>LaBranche</last-name>
- </user>
- <user>
</del><ins>+ <full-name>Andre LaBranche</full-name>
+ </record>
+ <record type="user">
</ins><span class="cx"> <uid>glyph</uid>
</span><del>- <guid>glyph</guid>
- <email-address>glyph@example.com</email-address>
</del><ins>+ <short-name>glyph</short-name>
+ <email>glyph@example.com</email>
</ins><span class="cx"> <password>test</password>
</span><del>- <name>Glyph Lefkowitz</name>
- <first-name>Glyph</first-name>
- <last-name>Lefkowitz</last-name>
- </user>
- <user>
</del><ins>+ <full-name>Glyph Lefkowitz</full-name>
+ </record>
+ <record type="user">
</ins><span class="cx"> <uid>i18nuser</uid>
</span><del>- <guid>i18nuser</guid>
- <email-address>i18nuser@example.com</email-address>
</del><ins>+ <short-name>i18nuser</short-name>
+ <email>i18nuser@example.com</email>
</ins><span class="cx"> <password>i18nuser</password>
</span><del>- <name>まだ</name>
- <first-name>ま</first-name>
- <last-name>だ</last-name>
- </user>
</del><ins>+ <full-name>まだ</full-name>
+ </record>
+
+ <!-- twext.who xml doesn't (yet) support repeat
</ins><span class="cx"> <user repeat="101">
</span><span class="cx"> <uid>user%02d</uid>
</span><span class="cx"> <uid>User %02d</uid>
</span><del>- <guid>user%02d</guid>
</del><ins>+ <short-name>user%02d</short-name>
</ins><span class="cx"> <password>user%02d</password>
</span><del>- <name>User %02d</name>
- <first-name>User</first-name>
- <last-name>%02d</last-name>
- <email-address>user%02d@example.com</email-address>
- </user>
</del><ins>+ <full-name>User %02d</full-name>
+ <email>user%02d@example.com</email>
+ </record>
</ins><span class="cx"> <user repeat="10">
</span><span class="cx"> <uid>public%02d</uid>
</span><del>- <guid>public%02d</guid>
</del><ins>+ <short-name>public%02d</short-name>
</ins><span class="cx"> <password>public%02d</password>
</span><del>- <name>Public %02d</name>
- <first-name>Public</first-name>
- <last-name>%02d</last-name>
- </user>
- <group>
</del><ins>+ <full-name>Public %02d</full-name>
+ </record>
+ -->
+ <record type="user">
+ <short-name>user01</short-name>
+ <uid>user01</uid>
+ <password>user01</password>
+ <full-name>User 01</full-name>
+ <email>user01@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user02</short-name>
+ <uid>user02</uid>
+ <password>user02</password>
+ <full-name>User 02</full-name>
+ <email>user02@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user03</short-name>
+ <uid>user03</uid>
+ <password>user03</password>
+ <full-name>User 03</full-name>
+ <email>user03@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user04</short-name>
+ <uid>user04</uid>
+ <password>user04</password>
+ <full-name>User 04</full-name>
+ <email>user04@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user05</short-name>
+ <uid>user05</uid>
+ <password>user05</password>
+ <full-name>User 05</full-name>
+ <email>user05@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user06</short-name>
+ <uid>user06</uid>
+ <password>user06</password>
+ <full-name>User 06</full-name>
+ <email>user06@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user07</short-name>
+ <uid>user07</uid>
+ <password>user07</password>
+ <full-name>User 07</full-name>
+ <email>user07@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user08</short-name>
+ <uid>user08</uid>
+ <password>user08</password>
+ <full-name>User 08</full-name>
+ <email>user08@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user09</short-name>
+ <uid>user09</uid>
+ <password>user09</password>
+ <full-name>User 09</full-name>
+ <email>user09@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user10</short-name>
+ <uid>user10</uid>
+ <password>user10</password>
+ <full-name>User 10</full-name>
+ <email>user10@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user11</short-name>
+ <uid>user11</uid>
+ <password>user11</password>
+ <full-name>User 11</full-name>
+ <email>user11@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user12</short-name>
+ <uid>user12</uid>
+ <password>user12</password>
+ <full-name>User 12</full-name>
+ <email>user12@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user13</short-name>
+ <uid>user13</uid>
+ <password>user13</password>
+ <full-name>User 13</full-name>
+ <email>user13@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user14</short-name>
+ <uid>user14</uid>
+ <password>user14</password>
+ <full-name>User 14</full-name>
+ <email>user14@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user15</short-name>
+ <uid>user15</uid>
+ <password>user15</password>
+ <full-name>User 15</full-name>
+ <email>user15@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user16</short-name>
+ <uid>user16</uid>
+ <password>user16</password>
+ <full-name>User 16</full-name>
+ <email>user16@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user17</short-name>
+ <uid>user17</uid>
+ <password>user17</password>
+ <full-name>User 17</full-name>
+ <email>user17@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user18</short-name>
+ <uid>user18</uid>
+ <password>user18</password>
+ <full-name>User 18</full-name>
+ <email>user18@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user19</short-name>
+ <uid>user19</uid>
+ <password>user19</password>
+ <full-name>User 19</full-name>
+ <email>user19@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user20</short-name>
+ <uid>user20</uid>
+ <password>user20</password>
+ <full-name>User 20</full-name>
+ <email>user20@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user21</short-name>
+ <uid>user21</uid>
+ <password>user21</password>
+ <full-name>User 21</full-name>
+ <email>user21@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user22</short-name>
+ <uid>user22</uid>
+ <password>user22</password>
+ <full-name>User 22</full-name>
+ <email>user22@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user23</short-name>
+ <uid>user23</uid>
+ <password>user23</password>
+ <full-name>User 23</full-name>
+ <email>user23@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user24</short-name>
+ <uid>user24</uid>
+ <password>user24</password>
+ <full-name>User 24</full-name>
+ <email>user24@example.com</email>
+ </record>
+
+ <record type="user">
+ <short-name>user25</short-name>
+ <uid>user25</uid>
+ <password>user25</password>
+ <full-name>User 25</full-name>
+ <email>user25@example.com</email>
+ </record>
+
+ <record type="group">
</ins><span class="cx"> <uid>group01</uid>
</span><del>- <guid>group01</guid>
</del><ins>+ <short-name>group01</short-name>
</ins><span class="cx"> <password>group01</password>
</span><del>- <name>Group 01</name>
- <email-address>group01@example.com</email-address>
- <members>
- <member type="users">user01</member>
- </members>
- </group>
- <group>
</del><ins>+ <full-name>Group 01</full-name>
+ <member-uid type="users">user01</member-uid>
+ </record>
+ <record type="group">
</ins><span class="cx"> <uid>group02</uid>
</span><del>- <guid>group02</guid>
</del><ins>+ <short-name>group02</short-name>
</ins><span class="cx"> <password>group02</password>
</span><del>- <name>Group 02</name>
- <email-address>group02@example.com</email-address>
- <members>
- <member type="users">user06</member>
- <member type="users">user07</member>
- </members>
- </group>
- <group>
</del><ins>+ <full-name>Group 02</full-name>
+ <member-uid type="users">user06</member-uid>
+ <member-uid type="users">user07</member-uid>
+ </record>
+ <record type="group">
</ins><span class="cx"> <uid>group03</uid>
</span><del>- <guid>group03</guid>
</del><ins>+ <short-name>group03</short-name>
</ins><span class="cx"> <password>group03</password>
</span><del>- <name>Group 03</name>
- <members>
- <member type="users">user08</member>
- <member type="users">user09</member>
- </members>
- </group>
- <group>
</del><ins>+ <full-name>Group 03</full-name>
+ <member-uid type="users">user08</member-uid>
+ <member-uid type="users">user09</member-uid>
+ </record>
+ <record type="group">
</ins><span class="cx"> <uid>group04</uid>
</span><del>- <guid>group04</guid>
</del><ins>+ <short-name>group04</short-name>
</ins><span class="cx"> <password>group04</password>
</span><del>- <name>Group 04</name>
- <members>
- <member type="groups">group02</member>
- <member type="groups">group03</member>
- <member type="users">user10</member>
- </members>
- </group>
- <group> <!-- delegategroup -->
</del><ins>+ <full-name>Group 04</full-name>
+ <member-uid type="groups">group02</member-uid>
+ <member-uid type="groups">group03</member-uid>
+ <member-uid type="users">user10</member-uid>
+ </record>
+ <record type="group"> <!-- delegategroup -->
</ins><span class="cx"> <uid>group05</uid>
</span><del>- <guid>group05</guid>
</del><ins>+ <short-name>group05</short-name>
</ins><span class="cx"> <password>group05</password>
</span><del>- <name>Group 05</name>
- <members>
- <member type="groups">group06</member>
- <member type="users">user20</member>
- </members>
- </group>
- <group> <!-- delegatesubgroup -->
</del><ins>+ <full-name>Group 05</full-name>
+ <member-uid type="groups">group06</member-uid>
+ <member-uid type="users">user20</member-uid>
+ </record>
+ <record type="group"> <!-- delegatesubgroup -->
</ins><span class="cx"> <uid>group06</uid>
</span><del>- <guid>group06</guid>
</del><ins>+ <short-name>group06</short-name>
</ins><span class="cx"> <password>group06</password>
</span><del>- <name>Group 06</name>
- <members>
- <member type="users">user21</member>
- </members>
- </group>
- <group> <!-- readonlydelegategroup -->
</del><ins>+ <full-name>Group 06</full-name>
+ <member-uid type="users">user21</member-uid>
+ </record>
+ <record type="group"> <!-- readonlydelegategroup -->
</ins><span class="cx"> <uid>group07</uid>
</span><del>- <guid>group07</guid>
</del><ins>+ <short-name>group07</short-name>
</ins><span class="cx"> <password>group07</password>
</span><del>- <name>Group 07</name>
- <members>
- <member type="users">user22</member>
- <member type="users">user23</member>
- <member type="users">user24</member>
- </members>
- </group>
- <group>
</del><ins>+ <full-name>Group 07</full-name>
+ <member-uid type="users">user22</member-uid>
+ <member-uid type="users">user23</member-uid>
+ <member-uid type="users">user24</member-uid>
+ </record>
+ <record type="group">
</ins><span class="cx"> <uid>disabledgroup</uid>
</span><del>- <guid>disabledgroup</guid>
</del><ins>+ <short-name>disabledgroup</short-name>
</ins><span class="cx"> <password>disabledgroup</password>
</span><del>- <name>Disabled Group</name>
- <members>
- <member type="users">user01</member>
- </members>
- </group>
-</accounts>
</del><ins>+ <full-name>Disabled Group</full-name>
+ <member-uid type="users">user01</member-uid>
+ </record>
+</directory>
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavwhotestaccountsaugmentsxml"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/augments.xml (0 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/augments.xml         (rev 0)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/augments.xml        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -0,0 +1,185 @@
</span><ins>+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE augments SYSTEM "augments.dtd">
+
+<augments>
+ <record>
+ <uid>Default</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ </record>
+ <record repeat="10">
+ <uid>location%02d</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ </record>
+ <record repeat="4">
+ <uid>resource%02d</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ </record>
+ <record>
+ <uid>resource05</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>none</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>resource06</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>accept-always</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>resource07</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>decline-always</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>resource08</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>accept-if-free</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>resource09</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>decline-if-busy</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>resource10</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>automatic</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>resource11</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>decline-always</auto-schedule-mode>
+ <auto-accept-group>group01</auto-accept-group>
+ </record>
+ <record repeat="10">
+ <uid>group%02d</uid>
+ <enable>true</enable>
+ </record>
+ <record>
+ <uid>disabledgroup</uid>
+ <enable>false</enable>
+ </record>
+ <record>
+ <uid>delegatedroom</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>false</enable-addressbook>
+ <auto-schedule>false</auto-schedule>
+ </record>
+ <record>
+ <uid>03DFF660-8BCC-4198-8588-DD77F776F518</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>true</auto-schedule>
+ </record>
+ <record>
+ <uid>80689D41-DAF8-4189-909C-DB017B271892</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>default</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>C38BEE7A-36EE-478C-9DCB-CBF4612AFE65</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>default</auto-schedule-mode>
+ <auto-accept-group>group01</auto-accept-group>
+ </record>
+ <record>
+ <uid>CCE95217-A57B-481A-AC3D-FEC9AB6CE3A9</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>true</auto-schedule>
+ </record>
+ <record>
+ <uid>0CE0BF31-5F9E-4801-A489-8C70CF287F5F</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>true</auto-schedule>
+ </record>
+ <record>
+ <uid>6F9EE33B-78F6-481B-9289-3D0812FF0D64</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>false</auto-schedule>
+ <auto-schedule-mode>default</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>76E7ECA6-08BC-4AE7-930D-F2E7453993A5</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>false</auto-schedule>
+ <auto-schedule-mode>default</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>63A2F949-2D8D-4C8D-B8A5-DCF2A94610F3</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>false</auto-schedule>
+ <auto-schedule-mode>default</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>06E3BDCB-9C19-485A-B14E-F146A80ADDC6</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>default</auto-schedule-mode>
+ </record>
+ <record>
+ <uid>4D66A20A-1437-437D-8069-2F14E8322234</uid>
+ <enable>true</enable>
+ <enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
+ <enable-login>true</enable-login>
+ <auto-schedule>true</auto-schedule>
+ <auto-schedule-mode>default</auto-schedule-mode>
+ </record>
+</augments>
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavwhotestaccountsresourcesxml"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/resources.xml (12896 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/resources.xml        2014-03-13 19:14:42 UTC (rev 12896)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/accounts/resources.xml        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -1,34 +1,273 @@
</span><del>-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-Copyright (c) 2006-2014 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 "accounts.dtd">
-
-<accounts realm="Test Realm">
- <location repeat="10">
- <uid>location%02d</uid>
- <guid>location%02d</guid>
- <password>location%02d</password>
- <name>Room %02d</name>
- </location>
- <resource repeat="10">
- <uid>resource%02d</uid>
- <guid>resource%02d</guid>
- <password>resource%02d</password>
- <name>Resource %02d</name>
- </resource>
-</accounts>
</del><ins>+<directory realm="Test Realm">
+ <record type="location">
+ <short-name>fantastic</short-name>
+ <uid>4D66A20A-1437-437D-8069-2F14E8322234</uid>
+ <full-name>Fantastic Conference Room</full-name>
+ <extras>
+ <associatedAddress>63A2F949-2D8D-4C8D-B8A5-DCF2A94610F3</associatedAddress>
+ </extras>
+ </record>
+ <record type="location">
+ <short-name>jupiter</short-name>
+ <uid>jupiter</uid>
+ <full-name>Jupiter Conference Room, Building 2, 1st Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>uranus</short-name>
+ <uid>uranus</uid>
+ <full-name>Uranus Conference Room, Building 3, 1st Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>morgensroom</short-name>
+ <uid>03DFF660-8BCC-4198-8588-DD77F776F518</uid>
+ <full-name>Morgen's Room</full-name>
+ </record>
+ <record type="location">
+ <short-name>mercury</short-name>
+ <uid>mercury</uid>
+ <full-name>Mercury Conference Room, Building 1, 2nd Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>location09</short-name>
+ <uid>location09</uid>
+ <full-name>Room 09</full-name>
+ </record>
+ <record type="location">
+ <short-name>location08</short-name>
+ <uid>location08</uid>
+ <full-name>Room 08</full-name>
+ </record>
+ <record type="location">
+ <short-name>location07</short-name>
+ <uid>location07</uid>
+ <full-name>Room 07</full-name>
+ </record>
+ <record type="location">
+ <short-name>location06</short-name>
+ <uid>location06</uid>
+ <full-name>Room 06</full-name>
+ </record>
+ <record type="location">
+ <short-name>location05</short-name>
+ <uid>location05</uid>
+ <full-name>Room 05</full-name>
+ </record>
+ <record type="location">
+ <short-name>location04</short-name>
+ <uid>location04</uid>
+ <full-name>Room 04</full-name>
+ </record>
+ <record type="location">
+ <short-name>location03</short-name>
+ <uid>location03</uid>
+ <full-name>Room 03</full-name>
+ </record>
+ <record type="location">
+ <short-name>location02</short-name>
+ <uid>location02</uid>
+ <full-name>Room 02</full-name>
+ </record>
+ <record type="location">
+ <short-name>location01</short-name>
+ <uid>location01</uid>
+ <full-name>Room 01</full-name>
+ </record>
+ <record type="location">
+ <short-name>delegatedroom</short-name>
+ <uid>delegatedroom</uid>
+ <full-name>Delegated Conference Room</full-name>
+ </record>
+ <record type="location">
+ <short-name>mars</short-name>
+ <uid>redplanet</uid>
+ <full-name>Mars Conference Room, Building 1, 1st Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>sharissroom</short-name>
+ <uid>80689D41-DAF8-4189-909C-DB017B271892</uid>
+ <full-name>Shari's Room</full-name>
+ <extras>
+ <associatedAddress>6F9EE33B-78F6-481B-9289-3D0812FF0D64</associatedAddress>
+ </extras>
+ </record>
+ <record type="location">
+ <short-name>pluto</short-name>
+ <uid>pluto</uid>
+ <full-name>Pluto Conference Room, Building 2, 1st Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>saturn</short-name>
+ <uid>saturn</uid>
+ <full-name>Saturn Conference Room, Building 2, 1st Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>location10</short-name>
+ <uid>location10</uid>
+ <full-name>Room 10</full-name>
+ </record>
+ <record type="location">
+ <short-name>pretend</short-name>
+ <uid>06E3BDCB-9C19-485A-B14E-F146A80ADDC6</uid>
+ <full-name>Pretend Conference Room</full-name>
+ <extras>
+ <associatedAddress>76E7ECA6-08BC-4AE7-930D-F2E7453993A5</associatedAddress>
+ </extras>
+ </record>
+ <record type="location">
+ <short-name>neptune</short-name>
+ <uid>neptune</uid>
+ <full-name>Neptune Conference Room, Building 2, 1st Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>Earth</short-name>
+ <uid>Earth</uid>
+ <full-name>Earth Conference Room, Building 1, 1st Floor</full-name>
+ </record>
+ <record type="location">
+ <short-name>venus</short-name>
+ <uid>venus</uid>
+ <full-name>Venus Conference Room, Building 1, 2nd Floor</full-name>
+ </record>
+ <record type="resource">
+ <short-name>sharisotherresource</short-name>
+ <uid>CCE95217-A57B-481A-AC3D-FEC9AB6CE3A9</uid>
+ <full-name>Shari's Other Resource</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource15</short-name>
+ <uid>resource15</uid>
+ <full-name>Resource 15</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource14</short-name>
+ <uid>resource14</uid>
+ <full-name>Resource 14</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource17</short-name>
+ <uid>resource17</uid>
+ <full-name>Resource 17</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource16</short-name>
+ <uid>resource16</uid>
+ <full-name>Resource 16</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource11</short-name>
+ <uid>resource11</uid>
+ <full-name>Resource 11</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource10</short-name>
+ <uid>resource10</uid>
+ <full-name>Resource 10</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource13</short-name>
+ <uid>resource13</uid>
+ <full-name>Resource 13</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource12</short-name>
+ <uid>resource12</uid>
+ <full-name>Resource 12</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource19</short-name>
+ <uid>resource19</uid>
+ <full-name>Resource 19</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource18</short-name>
+ <uid>resource18</uid>
+ <full-name>Resource 18</full-name>
+ </record>
+ <record type="resource">
+ <short-name>sharisresource</short-name>
+ <uid>C38BEE7A-36EE-478C-9DCB-CBF4612AFE65</uid>
+ <full-name>Shari's Resource</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource20</short-name>
+ <uid>resource20</uid>
+ <full-name>Resource 20</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource06</short-name>
+ <uid>resource06</uid>
+ <full-name>Resource 06</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource07</short-name>
+ <uid>resource07</uid>
+ <full-name>Resource 07</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource04</short-name>
+ <uid>resource04</uid>
+ <full-name>Resource 04</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource05</short-name>
+ <uid>resource05</uid>
+ <full-name>Resource 05</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource02</short-name>
+ <uid>resource02</uid>
+ <full-name>Resource 02</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource03</short-name>
+ <uid>resource03</uid>
+ <full-name>Resource 03</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource01</short-name>
+ <uid>resource01</uid>
+ <full-name>Resource 01</full-name>
+ </record>
+ <record type="resource">
+ <short-name>sharisotherresource1</short-name>
+ <uid>0CE0BF31-5F9E-4801-A489-8C70CF287F5F</uid>
+ <full-name>Shari's Other Resource1</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource08</short-name>
+ <uid>resource08</uid>
+ <full-name>Resource 08</full-name>
+ </record>
+ <record type="resource">
+ <short-name>resource09</short-name>
+ <uid>resource09</uid>
+ <full-name>Resource 09</full-name>
+ </record>
+ <record type="address">
+ <short-name>testaddress1</short-name>
+ <uid>6F9EE33B-78F6-481B-9289-3D0812FF0D64</uid>
+ <full-name>Test Address One</full-name>
+ <extras>
+ <streetAddress>20300 Stevens Creek Blvd, Cupertino, CA 95014</streetAddress>
+ <geo>37.322281,-122.028345</geo>
+ </extras>
+ </record>
+ <record type="address">
+ <short-name>il2</short-name>
+ <uid>63A2F949-2D8D-4C8D-B8A5-DCF2A94610F3</uid>
+ <full-name>IL2</full-name>
+ <extras>
+ <streetAddress>2 Infinite Loop, Cupertino, CA 95014</streetAddress>
+ <geo>37.332633,-122.030502</geo>
+ </extras>
+ </record>
+ <record type="address">
+ <short-name>il1</short-name>
+ <uid>76E7ECA6-08BC-4AE7-930D-F2E7453993A5</uid>
+ <full-name>IL1</full-name>
+ <extras>
+ <streetAddress>1 Infinite Loop, Cupertino, CA 95014</streetAddress>
+ <geo>37.331741,-122.030333</geo>
+ </extras>
+ </record>
+</directory>
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavwhotesttest_utilpy"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/test_util.py (0 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/test_util.py         (rev 0)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/who/test/test_util.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+##
+# Copyright (c) 2013 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.
+##
+
+"""
+txdav.who.util tests
+"""
+
+import os
+
+from txdav.who.util import directoryFromConfig
+from twisted.trial.unittest import TestCase
+from twistedcaldav.config import ConfigDict
+from twisted.python.filepath import FilePath
+from txdav.who.augment import AugmentedDirectoryService
+from twext.who.aggregate import DirectoryService as AggregateDirectoryService
+
+
+class StubStore(object):
+ pass
+
+
+
+class UtilTest(TestCase):
+
+ def setUp(self):
+ sourceDir = FilePath(__file__).parent().child("accounts")
+ self.serverRoot = os.path.abspath(self.mktemp())
+ os.mkdir(self.serverRoot)
+ self.dataRoot = os.path.join(self.serverRoot, "data")
+ if not os.path.exists(self.dataRoot):
+ os.makedirs(self.dataRoot)
+ destDir = FilePath(self.dataRoot)
+
+ accounts = destDir.child("accounts.xml")
+ sourceAccounts = sourceDir.child("accounts.xml")
+ accounts.setContent(sourceAccounts.getContent())
+
+ resources = destDir.child("resources.xml")
+ sourceResources = sourceDir.child("resources.xml")
+ resources.setContent(sourceResources.getContent())
+
+ augments = destDir.child("augments.xml")
+ sourceAugments = sourceDir.child("augments.xml")
+ augments.setContent(sourceAugments.getContent())
+
+
+ def test_directoryFromConfig(self):
+
+ config = ConfigDict(
+ {
+ "DataRoot": self.dataRoot,
+ "DirectoryService": {
+ "Enabled": True,
+ "type": "XML",
+ "params": {
+ "xmlFile": "accounts.xml",
+ "recordTypes": ["users", "groups"],
+ },
+ },
+ "ResourceService": {
+ "Enabled": True,
+ "type": "XML",
+ "params": {
+ "xmlFile": "resources.xml",
+ "recordTypes": ["locations", "resources"],
+ },
+ },
+ "AugmentService": {
+ "Enabled": True,
+ # FIXME: This still uses an actual class name:
+ "type": "twistedcaldav.directory.augment.AugmentXMLDB",
+ "params": {
+ "xmlFiles": ["augments.xml"],
+ },
+ },
+ }
+ )
+
+ store = StubStore()
+ service = directoryFromConfig(config, store=store)
+ self.assertTrue(isinstance(service, AugmentedDirectoryService))
+ self.assertTrue(isinstance(service._directory, AggregateDirectoryService))
+ self.assertEquals(len(service._directory.services), 3)
</ins></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who2txdavwhoutilpy"></a>
<div class="addfile"><h4>Added: CalendarServer/branches/users/sagen/move2who-2/txdav/who/util.py (0 => 12897)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-2/txdav/who/util.py         (rev 0)
+++ CalendarServer/branches/users/sagen/move2who-2/txdav/who/util.py        2014-03-13 20:33:25 UTC (rev 12897)
</span><span class="lines">@@ -0,0 +1,162 @@
</span><ins>+##
+# Copyright (c) 2006-2014 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 twext.python.log import Logger
+from twisted.cred.credentials import UsernamePassword
+from twext.who.aggregate import DirectoryService as AggregateDirectoryService
+from txdav.who.augment import AugmentedDirectoryService
+
+from calendarserver.tap.util import getDBPool, storeFromConfig
+from twext.who.idirectory import RecordType, DirectoryConfigurationError
+from twext.who.ldap import DirectoryService as LDAPDirectoryService
+from twext.who.util import ConstantsContainer
+from twisted.python.filepath import FilePath
+from twisted.python.reflect import namedClass
+from twistedcaldav.config import fullServerPath
+from txdav.who.delegates import DirectoryService as DelegateDirectoryService
+from txdav.who.idirectory import RecordType as CalRecordType
+from txdav.who.xml import DirectoryService as XMLDirectoryService
+
+log = Logger()
+
+
+def directoryFromConfig(config, store=None):
+ """
+ Return a directory service based on the config. If you want to go through
+ AMP to talk to one of these as a client, instantiate
+ txdav.dps.client.DirectoryService
+ """
+
+ # MOVE2WHO FIXME: this needs to talk to its own separate database. In fact,
+ # don't pass store=None if you already have called storeFromConfig()
+ # within this process. Pass the existing store in here.
+ if store is None:
+ pool, txnFactory = getDBPool(config)
+ store = storeFromConfig(config, txnFactory, None)
+
+ aggregatedServices = []
+
+
+ for serviceKey in ("DirectoryService", "ResourceService"):
+ serviceValue = config.get(serviceKey, None)
+
+ if not serviceValue.Enabled:
+ continue
+
+ directoryType = serviceValue.type.lower()
+ params = serviceValue.params
+
+ if "xml" in directoryType:
+ xmlFile = params.xmlFile
+ xmlFile = fullServerPath(config.DataRoot, xmlFile)
+ if not xmlFile or not os.path.exists(xmlFile):
+ log.error("Path not found for XML directory: {p}", p=xmlFile)
+ fp = FilePath(xmlFile)
+ directory = XMLDirectoryService(fp)
+
+ elif "opendirectory" in directoryType:
+ from twext.who.opendirectory import DirectoryService as ODDirectoryService
+ directory = ODDirectoryService()
+
+ elif "ldap" in directoryType:
+ if params.credentials.dn and params.credentials.password:
+ creds = UsernamePassword(params.credentials.dn,
+ params.credentials.password)
+ else:
+ creds = None
+ directory = LDAPDirectoryService(
+ params.uri,
+ params.rdnSchema.base,
+ creds=creds
+ )
+
+ else:
+ log.error("Invalid DirectoryType: {dt}", dt=directoryType)
+ raise DirectoryConfigurationError
+
+ # Set the appropriate record types on each service
+ types = []
+ for recordTypeName in params.recordTypes:
+ recordType = {
+ "users": RecordType.user,
+ "groups": RecordType.group,
+ "locations": CalRecordType.location,
+ "resources": CalRecordType.resource,
+ "addresses": CalRecordType.address,
+ }.get(recordTypeName, None)
+ if recordType is None:
+ log.error("Invalid Record Type: {rt}", rt=recordTypeName)
+ raise DirectoryConfigurationError
+ if recordType in types:
+ log.error("Duplicate Record Type: {rt}", rt=recordTypeName)
+ raise DirectoryConfigurationError
+ types.append(recordType)
+
+ directory.recordType = ConstantsContainer(types)
+ aggregatedServices.append(directory)
+
+ #
+ # Setup the Augment Service
+ #
+ if config.AugmentService.type:
+ augmentClass = namedClass(config.AugmentService.type)
+ log.info(
+ "Configuring augment service of type: {augmentClass}",
+ augmentClass=augmentClass
+ )
+ try:
+ augmentService = augmentClass(**config.AugmentService.params)
+ except IOError:
+ log.error("Could not start augment service")
+ raise
+ else:
+ augmentService = None
+
+ userDirectory = None
+ for directory in aggregatedServices:
+ if RecordType.user in directory.recordTypes():
+ userDirectory = directory
+ break
+ else:
+ log.error("No directory service set up for users")
+ raise DirectoryConfigurationError
+
+ delegateDirectory = DelegateDirectoryService(
+ userDirectory.realmName,
+ store
+ )
+ aggregatedServices.append(delegateDirectory)
+
+ aggregateDirectory = AggregateDirectoryService(
+ userDirectory.realmName, aggregatedServices
+ )
+ try:
+ augmented = AugmentedDirectoryService(
+ aggregateDirectory, store, augmentService
+ )
+
+ # The delegate directory needs a way to look up user/group records
+ # so hand it a reference to the augmented directory.
+ # FIXME: is there a better pattern to use here?
+ delegateDirectory.setMasterDirectory(augmented)
+
+ except Exception as e:
+ log.error("Could not create directory service", error=e)
+ raise
+
+ return augmented
</ins></span></pre>
</div>
</div>
</body>
</html>