[CalendarServer-changes] [12849] CalendarServer/branches/users/sagen/move2who
source_changes at macosforge.org
source_changes at macosforge.org
Fri Mar 7 14:20:50 PST 2014
Revision: 12849
http://trac.calendarserver.org//changeset/12849
Author: sagen at apple.com
Date: 2014-03-07 14:20:50 -0800 (Fri, 07 Mar 2014)
Log Message:
-----------
Allow single-process configurations (like Single and Utility) to bypass the client/server/amp business, and just use an augmented directory service directly.
Modified Paths:
--------------
CalendarServer/branches/users/sagen/move2who/calendarserver/tap/caldav.py
CalendarServer/branches/users/sagen/move2who/calendarserver/tap/test/test_util.py
CalendarServer/branches/users/sagen/move2who/calendarserver/tap/util.py
CalendarServer/branches/users/sagen/move2who/calendarserver/tools/calverify.py
CalendarServer/branches/users/sagen/move2who/calendarserver/tools/principals.py
CalendarServer/branches/users/sagen/move2who/calendarserver/tools/test/test_principals.py
CalendarServer/branches/users/sagen/move2who/calendarserver/tools/util.py
CalendarServer/branches/users/sagen/move2who/twistedcaldav/test/util.py
CalendarServer/branches/users/sagen/move2who/twistedcaldav/upgrade.py
CalendarServer/branches/users/sagen/move2who/txdav/caldav/datastore/test/test_attachments.py
CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py
CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py
CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py
CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py
CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py
CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py
Added Paths:
-----------
CalendarServer/branches/users/sagen/move2who/txdav/who/directory.py
Modified: CalendarServer/branches/users/sagen/move2who/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/calendarserver/tap/caldav.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/calendarserver/tap/caldav.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -86,7 +86,7 @@
from txdav.common.datastore.work.revision_cleanup import (
scheduleFirstFindMinRevision
)
-from txdav.dps.server import DirectoryProxyServiceMaker
+from txdav.dps.server import directoryFromConfig
from txdav.dps.client import DirectoryService as DirectoryProxyClientService
from txdav.who.groups import GroupCacher as NewGroupCacher
@@ -927,10 +927,10 @@
CalDAV and CardDAV requests.
"""
pool, txnFactory = getDBPool(config)
- store = storeFromConfig(config, txnFactory)
+ directory = DirectoryProxyClientService("FIXME")
+ store = storeFromConfig(config, txnFactory, directory)
logObserver = AMPCommonAccessLoggingObserver()
result = self.requestProcessingService(options, store, logObserver)
- directory = store.directoryService()
if pool is not None:
pool.setServiceParent(result)
@@ -1011,7 +1011,7 @@
namespace=config.GroupCaching.MemcachedPool,
useExternalProxies=config.GroupCaching.UseExternalProxies,
)
- newGroupCacher = NewGroupCacher(DirectoryProxyClientService(None))
+ newGroupCacher = NewGroupCacher(directory)
else:
groupCacher = None
newGroupCacher = None
@@ -1312,6 +1312,13 @@
if store is None:
raise StoreNotAvailable()
+ # Create a Directory Proxy "Server" service and hand it to the
+ # store.
+ # FIXME: right now the store passed *to* the directory is the
+ # calendar/contacts data store, but for a multi-server deployment
+ # it will need its own separate store.
+ store.setDirectoryService(directoryFromConfig(config, store=store))
+
result = self.requestProcessingService(options, store, logObserver)
# Optionally set up push notifications
@@ -1357,9 +1364,7 @@
namespace=config.GroupCaching.MemcachedPool,
useExternalProxies=config.GroupCaching.UseExternalProxies
)
- newGroupCacher = NewGroupCacher(
- DirectoryProxyClientService(None)
- )
+ newGroupCacher = NewGroupCacher(directory)
else:
groupCacher = None
newGroupCacher = None
@@ -1393,13 +1398,6 @@
"manhole_tap could not be imported"
)
- # Optionally enable Directory Proxy
- if config.DirectoryProxy.Enabled:
- dps = DirectoryProxyServiceMaker().makeService(
- None, store=store
- )
- dps.setServiceParent(result)
-
def decorateTransaction(txn):
txn._pushDistributor = pushDistributor
txn._rootResource = result.rootResource
@@ -1445,7 +1443,7 @@
Popen(memcachedArgv)
return self.storageService(
- slaveSvcCreator, logObserver, uid=uid, gid=gid
+ slaveSvcCreator, logObserver, uid=uid, gid=gid, directory=None
)
@@ -1458,10 +1456,17 @@
"""
def toolServiceCreator(pool, store, ignored, storageService):
+ # Create a Directory Proxy "Server" service and hand it to the
+ # store
+ # FIXME: right now the store passed *to* the directory is the
+ # calendar/contacts data store, but for a multi-server deployment
+ # it will need its own separate store.
+ store.setDirectoryService(directoryFromConfig(config, store=store))
return config.UtilityServiceClass(store)
uid, gid = getSystemIDs(config.UserName, config.GroupName)
- return self.storageService(toolServiceCreator, None, uid=uid, gid=gid)
+ return self.storageService(toolServiceCreator, None, uid=uid, gid=gid,
+ directory=None)
def makeService_Agent(self, options):
@@ -1509,7 +1514,7 @@
def storageService(
- self, createMainService, logObserver, uid=None, gid=None
+ self, createMainService, logObserver, uid=None, gid=None, directory=None
):
"""
If necessary, create a service to be started used for storage; for
@@ -1535,6 +1540,9 @@
running as root (also the gid to chown Attachments to).
@type gid: C{int}
+ @param directory: The directory service to use.
+ @type directory: L{IStoreDirectoryService} or None
+
@return: the appropriate a service to start.
@rtype: L{IService}
"""
@@ -1549,7 +1557,7 @@
maxConnections=config.MaxDBConnectionsPerPool
)
cp.setServiceParent(ms)
- store = storeFromConfig(config, cp.connection)
+ store = storeFromConfig(config, cp.connection, directory)
pps = PreProcessingService(
createMainService, cp, store, logObserver, storageService
@@ -1674,7 +1682,7 @@
"Unknown database type {}".format(config.DBType)
)
else:
- store = storeFromConfig(config, None)
+ store = storeFromConfig(config, None, directory)
return createMainService(None, store, logObserver, None)
@@ -1941,7 +1949,7 @@
namespace=config.GroupCaching.MemcachedPool,
useExternalProxies=config.GroupCaching.UseExternalProxies
)
- newGroupCacher = NewGroupCacher(DirectoryProxyClientService(None))
+ newGroupCacher = NewGroupCacher(directory)
else:
groupCacher = None
newGroupCacher = None
@@ -1957,7 +1965,10 @@
return multi
- ssvc = self.storageService(spawnerSvcCreator, None, uid, gid)
+ ssvc = self.storageService(
+ spawnerSvcCreator, None, uid, gid,
+ directory=DirectoryProxyClientService("FIXME")
+ )
ssvc.setServiceParent(s)
return s
Modified: CalendarServer/branches/users/sagen/move2who/calendarserver/tap/test/test_util.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/calendarserver/tap/test/test_util.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/calendarserver/tap/test/test_util.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -14,13 +14,14 @@
# limitations under the License.
##
-from calendarserver.tap.util import directoryFromConfig, MemoryLimitService, Stepper
+from calendarserver.tap.util import MemoryLimitService, Stepper
from twistedcaldav.util import computeProcessCount
from twistedcaldav.test.util import TestCase
from twistedcaldav.config import config
from twistedcaldav.directory.augment import AugmentXMLDB
from twisted.internet.task import Clock
from twisted.internet.defer import succeed, inlineCallbacks
+from txdav.dps.server import directoryFromConfig
class ProcessCountTestCase(TestCase):
Modified: CalendarServer/branches/users/sagen/move2who/calendarserver/tap/util.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/calendarserver/tap/util.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/calendarserver/tap/util.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -223,7 +223,7 @@
-def storeFromConfig(config, txnFactory, directoryService=None):
+def storeFromConfig(config, txnFactory, directoryService):
"""
Produce an L{IDataStore} from the given configuration, transaction factory,
and notifier factory.
@@ -241,9 +241,6 @@
if config.EnableResponseCache and config.Memcached.Pools.Default.ClientEnabled:
notifierFactories["cache"] = CacheStoreNotifierFactory()
- if directoryService is None:
- directoryService = directoryFromConfig(config)
-
quota = config.UserQuota
if quota == 0:
quota = None
@@ -286,14 +283,11 @@
-def directoryFromConfig(config):
+def REMOVEMEdirectoryFromConfig(config):
"""
Create an L{AggregateDirectoryService} from the given configuration.
"""
- # MOVE2WHO
- return DirectoryProxyClientService("XYZZY")
-
#
# Setup the Augment Service
#
@@ -470,7 +464,6 @@
directory = newStore.directoryService()
principalCollection = principalResourceClass("/principals/", directory)
-
#
# Setup the ProxyDB Service
#
Modified: CalendarServer/branches/users/sagen/move2who/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/calendarserver/tools/calverify.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/calendarserver/tools/calverify.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -431,7 +431,7 @@
configuration, creating one first if necessary.
"""
if self._directory is None:
- self._directory = getDirectory(self.config) #directoryFromConfig(self.config)
+ self._directory = getDirectory(self.config)
return self._directory
Modified: CalendarServer/branches/users/sagen/move2who/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/calendarserver/tools/principals.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/calendarserver/tools/principals.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -119,6 +119,7 @@
if self.function is not None:
yield self.function(self.store, *self.params)
+
attrMap = {
'GeneratedUID': {'attr': 'guid', },
'RealName': {'attr': 'fullName', },
@@ -142,7 +143,6 @@
}
- at inlineCallbacks
def main():
try:
(optargs, args) = getopt(
@@ -191,6 +191,10 @@
verbose = False
for opt, arg in optargs:
+
+ # Args come in as encoded bytes
+ arg = arg.decode("utf-8")
+
if opt in ("-h", "--help"):
usage()
@@ -234,20 +238,9 @@
proxyType = "write"
else:
raise AssertionError("Unknown proxy type")
-
- try:
- yield recordForPrincipalID(arg, checkOnly=True)
- except ValueError, e:
- abort(e)
-
principalActions.append((action_addProxy, proxyType, arg))
elif opt in ("", "--remove-proxy"):
- try:
- yield recordForPrincipalID(arg, checkOnly=True)
- except ValueError, e:
- abort(e)
-
principalActions.append((action_removeProxy, arg))
# elif opt in ("", "--set-auto-schedule"):
@@ -359,21 +352,19 @@
params = (searchPrincipals,)
else:
- #
- # Do a quick sanity check that arguments look like principal
- # identifiers.
- #
if not args:
usage("No principals specified.")
- for arg in args:
- try:
- yield recordForPrincipalID(arg, checkOnly=True)
- except ValueError, e:
- abort(e)
+ # We don't have a directory yet
+ # for arg in args:
+ # try:
+ # yield recordForPrincipalID(arg, checkOnly=True)
+ # except ValueError, e:
+ # abort(e)
+ unicodeArgs = [a.decode("utf-8") for a in args]
function = runPrincipalActions
- params = (args, principalActions)
+ params = (unicodeArgs, principalActions)
PrincipalService.function = function
PrincipalService.params = params
@@ -411,9 +402,7 @@
for principalID in principalIDs:
# Resolve the given principal IDs to records
try:
- record = yield recordForPrincipalID(
- principalID, directory=directory
- )
+ record = yield recordForPrincipalID(directory, principalID)
except ValueError:
record = None
@@ -545,7 +534,7 @@
directory = store.directoryService()
readWrite = (proxyType == "write")
for proxyID in proxyIDs:
- proxyRecord = yield recordForPrincipalID(proxyID, directory=directory)
+ proxyRecord = yield recordForPrincipalID(directory, proxyID)
if proxyRecord is None:
print("Invalid principal ID: %s" % (proxyID,))
else:
Modified: CalendarServer/branches/users/sagen/move2who/calendarserver/tools/test/test_principals.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/calendarserver/tools/test/test_principals.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/calendarserver/tools/test/test_principals.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -17,22 +17,23 @@
import os
import sys
+from calendarserver.tools.principals import (
+ parseCreationArgs, matchStrings,
+ updateRecord, principalForPrincipalID, getProxies, setProxies
+)
from twext.python.filepath import CachingFilePath as FilePath
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
-
from twistedcaldav.config import config
+from twistedcaldav.directory import calendaruserproxy
from twistedcaldav.directory.directory import DirectoryError
-from twistedcaldav.directory import calendaruserproxy
+from twistedcaldav.test.util import (
+ TestCase, CapturingProcessProtocol, ErrorOutput
+)
+from txdav.dps.server import directoryFromConfig
-from twistedcaldav.test.util import TestCase, CapturingProcessProtocol, \
- ErrorOutput
-from calendarserver.tap.util import directoryFromConfig
-from calendarserver.tools.principals import (parseCreationArgs, matchStrings,
- updateRecord, principalForPrincipalID, getProxies, setProxies)
-
class ManagePrincipalsTestCase(TestCase):
def setUp(self):
Modified: CalendarServer/branches/users/sagen/move2who/calendarserver/tools/util.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/calendarserver/tools/util.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/calendarserver/tools/util.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -396,14 +396,8 @@
@inlineCallbacks
-def recordForPrincipalID(principalID, checkOnly=False, directory=None):
+def recordForPrincipalID(directory, principalID, checkOnly=False):
- # Allow a directory parameter to be passed in, but default to config.directory
- # But config.directory isn't set right away, so only use it when we're doing more
- # than checking.
- if not checkOnly and not directory:
- directory = config.directory
-
if principalID.startswith("/"):
segments = principalID.strip("/").split("/")
if (len(segments) == 3 and
Modified: CalendarServer/branches/users/sagen/move2who/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/twistedcaldav/test/util.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/twistedcaldav/test/util.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -50,11 +50,12 @@
from calendarserver.provision.root import RootResource
from twext.python.log import Logger
-from txdav.caldav.datastore.test.util import buildCalendarStore
-from calendarserver.tap.util import getRootResource, directoryFromConfig
+from calendarserver.tap.util import getRootResource
from txweb2.dav.test.util import SimpleRequest
from twistedcaldav.directory.util import transactionFromRequest
from twistedcaldav.directory.directory import DirectoryService
+from txdav.caldav.datastore.test.util import buildCalendarStore
+from txdav.dps.server import directoryFromConfig
log = Logger()
Modified: CalendarServer/branches/users/sagen/move2who/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/twistedcaldav/upgrade.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/twistedcaldav/upgrade.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -60,7 +60,7 @@
from twisted.protocols.amp import AMP, Command, String, Boolean
-from calendarserver.tap.util import getRootResource, FakeRequest, directoryFromConfig
+from calendarserver.tap.util import getRootResource, FakeRequest
from calendarserver.tools.util import getDirectory
from txdav.caldav.datastore.scheduling.imip.mailgateway import migrateTokensToStore
@@ -1032,7 +1032,7 @@
def stepWithResult(self, result):
if self.doPostImport:
- directory = directoryFromConfig(self.config)
+ directory = self.store.directoryService()
# Load proxy assignments from XML if specified
if self.config.ProxyLoadFromFile:
Modified: CalendarServer/branches/users/sagen/move2who/txdav/caldav/datastore/test/test_attachments.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/caldav/datastore/test/test_attachments.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/txdav/caldav/datastore/test/test_attachments.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -14,7 +14,7 @@
# limitations under the License.
##
-from calendarserver.tap.util import directoryFromConfig
+from txdav.dps.server import directoryFromConfig
from pycalendar.datetime import DateTime
from pycalendar.value import Value
Modified: CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/txdav/common/datastore/sql.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -211,6 +211,10 @@
return self._directoryService
+ def setDirectoryService(self, directoryService):
+ self._directoryService = directoryService
+
+
def callWithNewTransactions(self, callback):
"""
Registers a method to be called whenever a new transaction is
Modified: CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/txdav/dps/client.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -38,6 +38,9 @@
MembersCommand, GroupsCommand, SetMembersCommand,
VerifyPlaintextPasswordCommand, VerifyHTTPDigestCommand
)
+from txdav.who.directory import (
+ CalendarDirectoryRecordMixin, CalendarDirectoryServiceMixin
+)
import txdav.who.delegates
import txdav.who.idirectory
from txweb2.auth.digest import DigestedCredentials
@@ -59,7 +62,7 @@
## component.normalizeCalendarUserAddresses
@implementer(IDirectoryService, IStoreDirectoryService)
-class DirectoryService(BaseDirectoryService):
+class DirectoryService(BaseDirectoryService, CalendarDirectoryServiceMixin):
"""
Client side of directory proxy
"""
@@ -83,16 +86,7 @@
def getGroups(self, guids=None):
return succeed(set())
- # Must maintain the hack for a bit longer:
- def setPrincipalCollection(self, principalCollection):
- """
- Set the principal service that the directory relies on for doing proxy tests.
- @param principalService: the principal service.
- @type principalService: L{DirectoryProvisioningResource}
- """
- self.principalCollection = principalCollection
-
guid = "1332A615-4D3A-41FE-B636-FBE25BFB982E"
# END MOVE2WHO
@@ -293,8 +287,9 @@
return self.recordType.lookupByName(oldName[:-1])
+
@implementer(ICalendarStoreDirectoryRecord)
-class DirectoryRecord(BaseDirectoryRecord):
+class DirectoryRecord(BaseDirectoryRecord, CalendarDirectoryRecordMixin):
@inlineCallbacks
@@ -384,132 +379,8 @@
)
- @property
- def calendarUserAddresses(self):
- if not self.hasCalendars:
- return frozenset()
- try:
- cuas = set(
- ["mailto:%s" % (emailAddress,)
- for emailAddress in self.emailAddresses]
- )
- except AttributeError:
- cuas = set()
- try:
- if self.guid:
- if isinstance(self.guid, uuid.UUID):
- guid = unicode(self.guid).upper()
- else:
- guid = self.guid
- cuas.add("urn:uuid:{guid}".format(guid=guid))
- except AttributeError:
- # No guid
- pass
- cuas.add("/principals/__uids__/{uid}/".format(uid=self.uid))
- for shortName in self.shortNames:
- cuas.add("/principals/{rt}/{sn}/".format(
- rt=self.recordType.name + "s", sn=shortName)
- )
- return frozenset(cuas)
-
-
- def getCUType(self):
- # Mapping from directory record.recordType to RFC2445 CUTYPE values
- self._cuTypes = {
- self.service.recordType.user: 'INDIVIDUAL',
- self.service.recordType.group: 'GROUP',
- self.service.recordType.resource: 'RESOURCE',
- self.service.recordType.location: 'ROOM',
- }
-
- return self._cuTypes.get(self.recordType, "UNKNOWN")
-
-
- @property
- def displayName(self):
- return self.fullNames[0]
-
-
- def cacheToken(self):
- """
- Generate a token that can be uniquely used to identify the state of this record for use
- in a cache.
- """
- return hash((
- self.__class__.__name__,
- self.service.realmName,
- self.recordType.name,
- self.shortNames,
- self.guid,
- self.hasCalendars,
- ))
-
-
- def canonicalCalendarUserAddress(self):
- """
- Return a CUA for this record, preferring in this order:
- urn:uuid: form
- mailto: form
- first in calendarUserAddresses list
- """
-
- cua = ""
- for candidate in self.calendarUserAddresses:
- # Pick the first one, but urn:uuid: and mailto: can override
- if not cua:
- cua = candidate
- # But always immediately choose the urn:uuid: form
- if candidate.startswith("urn:uuid:"):
- cua = candidate
- break
- # Prefer mailto: if no urn:uuid:
- elif candidate.startswith("mailto:"):
- cua = candidate
- return cua
-
-
- def enabledAsOrganizer(self):
- # MOVE2WHO FIXME TO LOOK AT CONFIG
- if self.recordType == self.service.recordType.user:
- return True
- elif self.recordType == DirectoryService.recordType_groups:
- return False # config.Scheduling.Options.AllowGroupAsOrganizer
- elif self.recordType == DirectoryService.recordType_locations:
- return False # config.Scheduling.Options.AllowLocationAsOrganizer
- elif self.recordType == DirectoryService.recordType_resources:
- return False # config.Scheduling.Options.AllowResourceAsOrganizer
- else:
- return False
-
-
- #MOVE2WHO
- def thisServer(self):
- return True
-
-
- def isLoginEnabled(self):
- return self.loginAllowed
-
-
- #MOVE2WHO
- def calendarsEnabled(self):
- # In the old world, this *also* looked at config:
- # return config.EnableCalDAV and self.enabledForCalendaring
- return self.hasCalendars
-
-
- def getAutoScheduleMode(self, organizer):
- # MOVE2WHO Fix this to take organizer into account:
- return self.autoScheduleMode
-
-
- def canAutoSchedule(self, organizer=None):
- # MOVE2WHO Fix this:
- return True
-
-
# For scheduling/freebusy
# FIXME: doesn't this need to happen in the DPS?
@inlineCallbacks
Modified: CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/txdav/dps/server.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -446,6 +446,89 @@
+def directoryFromConfig(config, store=None):
+ """
+ Return a directory service based on the config
+ """
+ directoryType = config.DirectoryProxy.DirectoryType
+ args = config.DirectoryProxy.Arguments
+ kwds = config.DirectoryProxy.Keywords
+
+ # FIXME: this needs to talk to its own separate database
+ pool, txnFactory = getDBPool(config)
+ if store is None:
+ store = storeFromConfig(config, txnFactory, None)
+
+ if directoryType == "OD":
+ from twext.who.opendirectory import DirectoryService as ODDirectoryService
+ primaryDirectory = ODDirectoryService(*args, **kwds)
+
+ elif directoryType == "LDAP":
+ authDN = kwds.pop("authDN", "")
+ password = kwds.pop("password", "")
+ if authDN and password:
+ creds = UsernamePassword(authDN, password)
+ else:
+ creds = None
+ kwds["credentials"] = creds
+ debug = kwds.pop("debug", "")
+ primaryDirectory = LDAPDirectoryService(
+ *args, _debug=debug, **kwds
+ )
+
+ elif directoryType == "XML":
+ path = kwds.pop("path", "")
+ if not path or not os.path.exists(path):
+ log.error("Path not found for XML directory: {p}", p=path)
+ fp = FilePath(path)
+ primaryDirectory = XMLDirectoryService(fp, *args, **kwds)
+
+ else:
+ log.error("Invalid DirectoryType: {dt}", dt=directoryType)
+
+ #
+ # 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
+
+ delegateDirectory = DelegateDirectoryService(
+ primaryDirectory.realmName,
+ store
+ )
+
+ aggregateDirectory = AggregateDirectoryService(
+ primaryDirectory.realmName,
+ (primaryDirectory, delegateDirectory)
+ )
+ 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
+
+
@implementer(IPlugin, service.IServiceMaker)
class DirectoryProxyServiceMaker(object):
@@ -454,7 +537,7 @@
options = DirectoryProxyOptions
- def makeService(self, options, store=None):
+ def makeService(self, options):
"""
Return a service
"""
@@ -465,82 +548,20 @@
else:
setproctitle("CalendarServer Directory Proxy Service")
- directoryType = config.DirectoryProxy.DirectoryType
- args = config.DirectoryProxy.Arguments
- kwds = config.DirectoryProxy.Keywords
+ try:
+ print("XZZZY AAA")
+ directory = directoryFromConfig(config)
+ print("XZZZY BBB")
+ except Exception as e:
+ log.error("Failed to create directory service", error=e)
+ raise
- # FIXME: this needs to talk to its own separate database
- if store is None:
- pool, txnFactory = getDBPool(config)
- store = storeFromConfig(config, txnFactory)
+ log.info("Created directory service")
+ print("XZZZY CCCC")
- if directoryType == "OD":
- from twext.who.opendirectory import DirectoryService as ODDirectoryService
- primaryDirectory = ODDirectoryService(*args, **kwds)
-
- elif directoryType == "LDAP":
- authDN = kwds.pop("authDN", "")
- password = kwds.pop("password", "")
- if authDN and password:
- creds = UsernamePassword(authDN, password)
- else:
- creds = None
- kwds["credentials"] = creds
- debug = kwds.pop("debug", "")
- primaryDirectory = LDAPDirectoryService(
- *args, _debug=debug, **kwds
- )
-
- elif directoryType == "XML":
- path = kwds.pop("path", "")
- if not path or not os.path.exists(path):
- log.error("Path not found for XML directory: {p}", p=path)
- fp = FilePath(path)
- primaryDirectory = XMLDirectoryService(fp, *args, **kwds)
-
- else:
- log.error("Invalid DirectoryType: {dt}", dt=directoryType)
-
- desc = "unix:{path}:mode=660".format(
- path=config.DirectoryProxy.SocketPath
+ return strPortsService(
+ "unix:{path}:mode=660".format(
+ path=config.DirectoryProxy.SocketPath
+ ),
+ DirectoryProxyAMPFactory(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
-
- delegateDirectory = DelegateDirectoryService(
- primaryDirectory.realmName,
- store
- )
-
- aggregateDirectory = AggregateDirectoryService(
- primaryDirectory.realmName,
- (primaryDirectory, delegateDirectory)
- )
- 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 strPortsService(desc, DirectoryProxyAMPFactory(augmented))
Modified: CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/augment.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -23,6 +23,9 @@
from twext.who.directory import DirectoryRecord
from twext.who.directory import DirectoryService as BaseDirectoryService
from twext.who.util import ConstantsContainer
+from txdav.who.directory import (
+ CalendarDirectoryRecordMixin, CalendarDirectoryServiceMixin
+)
from txdav.who.idirectory import AutoScheduleMode, FieldName
from txdav.who.idirectory import RecordType as CalRecordType
from txdav.who.delegates import RecordType as DelegateRecordType
@@ -33,7 +36,7 @@
log = Logger()
-class AugmentedDirectoryRecord(DirectoryRecord):
+class AugmentedDirectoryRecord(DirectoryRecord, CalendarDirectoryRecordMixin):
def __init__(self, service, baseRecord, augmentedFields):
DirectoryRecord.__init__(self, service, augmentedFields)
@@ -64,7 +67,8 @@
@implementer(IDirectoryService)
-class AugmentedDirectoryService(BaseDirectoryService):
+class AugmentedDirectoryService(BaseDirectoryService,
+ CalendarDirectoryServiceMixin):
fieldName = ConstantsContainer((
BaseDirectoryService.fieldName,
Modified: CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/delegates.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -67,6 +67,7 @@
this record.
"""
parentUID, proxyType = self.uid.split("#")
+
txn = self.service._store.newTransaction()
if self.recordType in (
@@ -103,7 +104,6 @@
@param memberRecords: The new members of the group
@type memberRecords: iterable of L{iDirectoryRecord}s
"""
-
if self.recordType not in (
RecordType.readDelegateGroup, RecordType.writeDelegateGroup
):
Added: CalendarServer/branches/users/sagen/move2who/txdav/who/directory.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/directory.py (rev 0)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/directory.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -0,0 +1,170 @@
+##
+# 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.
+##
+
+"""
+Calendar/Contacts specific methods for DirectoryRecord
+"""
+
+
+import uuid
+
+
+__all__ = [
+ "CalendarDirectoryRecordMixin",
+ "CalendarDirectoryServiceMixin",
+]
+
+
+class CalendarDirectoryServiceMixin(object):
+
+ # Must maintain the hack for a bit longer:
+ def setPrincipalCollection(self, principalCollection):
+ """
+ Set the principal service that the directory relies on for doing proxy tests.
+
+ @param principalService: the principal service.
+ @type principalService: L{DirectoryProvisioningResource}
+ """
+ self.principalCollection = principalCollection
+
+
+class CalendarDirectoryRecordMixin(object):
+
+
+ @property
+ def calendarUserAddresses(self):
+ if not self.hasCalendars:
+ return frozenset()
+
+ try:
+ cuas = set(
+ ["mailto:%s" % (emailAddress,)
+ for emailAddress in self.emailAddresses]
+ )
+ except AttributeError:
+ cuas = set()
+
+ try:
+ if self.guid:
+ if isinstance(self.guid, uuid.UUID):
+ guid = unicode(self.guid).upper()
+ else:
+ guid = self.guid
+ cuas.add("urn:uuid:{guid}".format(guid=guid))
+ except AttributeError:
+ # No guid
+ pass
+ cuas.add("/principals/__uids__/{uid}/".format(uid=self.uid))
+ for shortName in self.shortNames:
+ cuas.add("/principals/{rt}/{sn}/".format(
+ rt=self.recordType.name + "s", sn=shortName)
+ )
+ return frozenset(cuas)
+
+
+ def getCUType(self):
+ # Mapping from directory record.recordType to RFC2445 CUTYPE values
+ self._cuTypes = {
+ self.service.recordType.user: 'INDIVIDUAL',
+ self.service.recordType.group: 'GROUP',
+ self.service.recordType.resource: 'RESOURCE',
+ self.service.recordType.location: 'ROOM',
+ }
+
+ return self._cuTypes.get(self.recordType, "UNKNOWN")
+
+
+ @property
+ def displayName(self):
+ return self.fullNames[0]
+
+
+ def cacheToken(self):
+ """
+ Generate a token that can be uniquely used to identify the state of this record for use
+ in a cache.
+ """
+ return hash((
+ self.__class__.__name__,
+ self.service.realmName,
+ self.recordType.name,
+ self.shortNames,
+ self.guid,
+ self.hasCalendars,
+ ))
+
+
+ def canonicalCalendarUserAddress(self):
+ """
+ Return a CUA for this record, preferring in this order:
+ urn:uuid: form
+ mailto: form
+ first in calendarUserAddresses list
+ """
+
+ cua = ""
+ for candidate in self.calendarUserAddresses:
+ # Pick the first one, but urn:uuid: and mailto: can override
+ if not cua:
+ cua = candidate
+ # But always immediately choose the urn:uuid: form
+ if candidate.startswith("urn:uuid:"):
+ cua = candidate
+ break
+ # Prefer mailto: if no urn:uuid:
+ elif candidate.startswith("mailto:"):
+ cua = candidate
+ return cua
+
+
+ def enabledAsOrganizer(self):
+ # MOVE2WHO FIXME TO LOOK AT CONFIG
+ if self.recordType == self.service.recordType.user:
+ return True
+ elif self.recordType == self.service.recordType.group:
+ return False # config.Scheduling.Options.AllowGroupAsOrganizer
+ elif self.recordType == self.service.recordType.location:
+ return False # config.Scheduling.Options.AllowLocationAsOrganizer
+ elif self.recordType == self.service.recordType.resource:
+ return False # config.Scheduling.Options.AllowResourceAsOrganizer
+ else:
+ return False
+
+
+ #MOVE2WHO
+ def thisServer(self):
+ return True
+
+
+ def isLoginEnabled(self):
+ return self.loginAllowed
+
+
+ #MOVE2WHO
+ def calendarsEnabled(self):
+ # In the old world, this *also* looked at config:
+ # return config.EnableCalDAV and self.enabledForCalendaring
+ return self.hasCalendars
+
+
+ def getAutoScheduleMode(self, organizer):
+ # MOVE2WHO Fix this to take organizer into account:
+ return self.autoScheduleMode
+
+
+ def canAutoSchedule(self, organizer=None):
+ # MOVE2WHO Fix this:
+ return True
Modified: CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py 2014-03-07 21:46:24 UTC (rev 12848)
+++ CalendarServer/branches/users/sagen/move2who/txdav/who/groups.py 2014-03-07 22:20:50 UTC (rev 12849)
@@ -131,7 +131,6 @@
@inlineCallbacks
def doWork(self):
- print("XYZZY IN GRW doWork", )
# Delete all other work items for this group
yield Delete(
From=self.table, Where=(self.table.GROUP_GUID == self.groupGuid)
@@ -142,7 +141,7 @@
try:
yield newGroupCacher.refreshGroup(
- self.transaction, self.groupGuid
+ self.transaction, self.groupGuid.decode("utf-8")
)
except Exception, e:
log.error(
@@ -471,4 +470,6 @@
).on(txn)
attendeeGroupUIDs = set([row[0] for row in rows])
+ # FIXME: is this a good place to clear out unreferenced groups?
+
returnValue(delegatedUIDs.union(attendeeGroupUIDs))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140307/3a2f77d6/attachment-0001.html>
More information about the calendarserver-changes
mailing list