[CalendarServer-changes] [4479] CalendarServer/branches/users/cdaboo/partition-4464
source_changes at macosforge.org
source_changes at macosforge.org
Mon Aug 3 14:09:12 PDT 2009
Revision: 4479
http://trac.macosforge.org/projects/calendarserver/changeset/4479
Author: cdaboo at apple.com
Date: 2009-08-03 14:09:08 -0700 (Mon, 03 Aug 2009)
Log Message:
-----------
Main partitioning support working with XMLFile accounts.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml
CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd
CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/idirectory.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/addressmapping.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/cuaddress.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischedule.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischeduleservers.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/scheduler.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/utils.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/static.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/stdconfig.py
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_config.py
Added Paths:
-----------
CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions-test.plist
CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions.plist
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/partitions.py
Removed Paths:
-------------
CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectoryschema.py
Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts-test.xml 2009-08-03 21:09:08 UTC (rev 4479)
@@ -44,6 +44,7 @@
<first-name>User</first-name>
<last-name>%02d</last-name>
<email-address>user%02d at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:user%02d at example.com</cuaddr>
</user>
<user repeat="10">
@@ -53,6 +54,7 @@
<name>Public %02d</name>
<first-name>Public</first-name>
<last-name>%02d</last-name>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:public%02d at example.com</cuaddr>
</user>
<location repeat="10">
@@ -60,6 +62,7 @@
<guid>location%02d</guid>
<password>location%02d</password>
<name>Room %02d</name>
+ <enable-calendar>true</enable-calendar>
<auto-schedule/>
</location>
<resource repeat="10">
@@ -67,6 +70,7 @@
<guid>resource%02d</guid>
<password>resource%02d</password>
<name>Resource %02d</name>
+ <enable-calendar>true</enable-calendar>
<auto-schedule/>
<proxies>
<member type="users">user01</member>
@@ -119,10 +123,10 @@
<uid>disabledgroup</uid>
<guid>disabledgroup</guid>
<password>disabledgroup</password>
+ <enable>false</enable>
<name>Disabled Group</name>
<members>
<member type="users">user01</member>
</members>
- <disable-calendar/>
</group>
</accounts>
Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.dtd 2009-08-03 21:09:08 UTC (rev 4479)
@@ -17,16 +17,16 @@
<!ELEMENT accounts (user*, group*, resource*, location*) >
<!ATTLIST accounts realm CDATA "">
- <!ELEMENT user (uid+, guid, password, name, first-name?, last-name?, email-address*, cuaddr*, disable-calendar?)>
+ <!ELEMENT user (uid+, guid, password, enable?, hosted-at, name, first-name?, last-name?, email-address*, enable-calendar?, cuaddr*)>
<!ATTLIST user repeat CDATA "1">
- <!ELEMENT group (uid+, guid, password, name, members, cuaddr*, disable-calendar?)>
+ <!ELEMENT group (uid+, guid, password, enable?, hosted-at, name, members, enable-calendar?, cuaddr*)>
<!ATTLIST group repeat CDATA "1">
- <!ELEMENT resource (uid+, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
+ <!ELEMENT resource (uid+, guid, password, enable?, hosted-at, name, enable-calendar?, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
<!ATTLIST resource repeat CDATA "1">
- <!ELEMENT location (uid+, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
+ <!ELEMENT location (uid+, guid, password, enable?, hosted-at, name, enable-calendar?, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
<!ATTLIST location repeat CDATA "1">
<!ELEMENT member (#PCDATA)>
@@ -35,11 +35,16 @@
<!ELEMENT uid (#PCDATA)>
<!ELEMENT guid (#PCDATA)>
<!ELEMENT password (#PCDATA)>
+ <!ELEMENT enable (#PCDATA)>
+ <!ELEMENT hosted-at (#PCDATA)>
<!ELEMENT name (#PCDATA)>
+ <!ELEMENT first-name (#PCDATA)>
+ <!ELEMENT last-name (#PCDATA)>
+ <!ELEMENT email-address (#PCDATA)>
+ <!ELEMENT members (member*)>
+ <!ELEMENT enable-calendar (#PCDATA)>
<!ELEMENT cuaddr (#PCDATA)>
- <!ELEMENT members (member*)>
- <!ELEMENT auto-schedule EMPTY>
- <!ELEMENT disable-calendar EMPTY>
+ <!ELEMENT auto-schedule (#PCDATA)>
<!ELEMENT proxies (member*)>
<!ELEMENT read-only-proxies (member*)>
>
Modified: CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/auth/accounts.xml 2009-08-03 21:09:08 UTC (rev 4479)
@@ -28,6 +28,7 @@
<uid>test</uid>
<password>test</password>
<name>Test User</name>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:testuser at example.com</cuaddr>
</user>
<group>
@@ -42,7 +43,8 @@
<uid>mercury</uid>
<password>mercury</password>
<name>Mecury Conference Room, Building 1, 2nd Floor</name>
- <auto-schedule/>
+ <enable-calendar>true</enable-calendar>
+ <auto-schedule>true</auto-schedule>
<proxies>
<member type="users">test</member>
</proxies>
Added: CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions-test.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions-test.plist (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions-test.plist 2009-08-03 21:09:08 UTC (rev 4479)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Copyright (c) 2009 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>partitions</key>
+ <array>
+ <dict>
+ <key>uid</key>
+ <string>00001</string>
+ <key>url</key>
+ <string>http://localhost:8008</string>
+ </dict>
+ <dict>
+ <key>uid</key>
+ <string>00002</string>
+ <key>url</key>
+ <string>http://localhost:8108</string>
+ </dict>
+ </array>
+</dict>
+</plist>
Added: CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions.plist (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/conf/partitions.plist 2009-08-03 21:09:08 UTC (rev 4479)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Copyright (c) 2009 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>partitions</key>
+ <array>
+ <!--
+ <dict>
+ <key>uid</key>
+ <string>00001</string>
+ <key>url</key>
+ <string>http://localhost:8008</string>
+ </dict>
+ -->
+ </array>
+</dict>
+</plist>
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/apache.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -153,6 +153,7 @@
service = service,
recordType = recordType,
guid = None,
+ enabled = True,
shortNames = (shortName,),
)
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/appleopendirectory.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -24,12 +24,7 @@
]
import sys
-from uuid import UUID
-from twext.python.plistlib import readPlistFromString
-
-from xml.parsers.expat import ExpatError
-
import opendirectory
import dsattributes
import dsquery
@@ -616,8 +611,8 @@
firstName = recordFirstName,
lastName = recordLastName,
emailAddresses = recordEmailAddresses,
- calendarUserAddresses = calendarUserAddresses,
enabledForCalendaring = enabledForCalendaring,
+ calendarUserAddresses = calendarUserAddresses,
memberGUIDs = memberGUIDs,
)
if enabledForCalendaring:
@@ -647,73 +642,6 @@
self.recordCacheForType(recordType).addRecord(record, indexType, origIndexKey)
- def _parseResourceInfo(self, plist, guid, recordType, shortname):
- """
- Parse OD ResourceInfo attribute and extract information that the server needs.
-
- @param plist: the plist that is the attribute value.
- @type plist: str
- @param guid: the directory GUID of the record being parsed.
- @type guid: str
- @param shortname: the record shortname of the record being parsed.
- @type shortname: str
- @return: a C{tuple} of C{bool} for auto-accept, C{str} for proxy GUID, C{str} for read-only proxy GUID.
- """
- try:
- plist = readPlistFromString(plist)
- wpframework = plist.get("com.apple.WhitePagesFramework", {})
- autoaccept = wpframework.get("AutoAcceptsInvitation", False)
- proxy = wpframework.get("CalendaringDelegate", None)
- read_only_proxy = wpframework.get("ReadOnlyCalendaringDelegate", None)
- except (ExpatError, AttributeError), e:
- self.log_error(
- "Failed to parse ResourceInfo attribute of record (%s)%s (guid=%s): %s\n%s" %
- (recordType, shortname, guid, e, plist,)
- )
- raise ValueError("Invalid ResourceInfo")
-
- return (autoaccept, proxy, read_only_proxy,)
-
- def getResourceInfo(self):
- """
- Resource information including proxy assignments for resource and
- locations, as well as auto-schedule settings, used to live in the
- directory. This method fetches old resource info for migration
- purposes.
- """
- attrs = [
- dsattributes.kDS1AttrGeneratedUID,
- dsattributes.kDSNAttrResourceInfo,
- ]
-
- for recordType in (dsattributes.kDSStdRecordTypePlaces, dsattributes.kDSStdRecordTypeResources):
- try:
- self.log_debug("opendirectory.listAllRecordsWithAttributes_list(%r,%r,%r)" % (
- self.directory,
- recordType,
- attrs,
- ))
- results = opendirectory.listAllRecordsWithAttributes_list(
- self.directory,
- recordType,
- attrs,
- )
- except opendirectory.ODError, ex:
- self.log_error("OpenDirectory (node=%s) error: %s" % (self.realmName, str(ex)))
- raise
-
- for (recordShortName, value) in results:
- recordGUID = value.get(dsattributes.kDS1AttrGeneratedUID)
- resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
- if resourceInfo is not None:
- try:
- autoSchedule, proxy, readOnlyProxy = self._parseResourceInfo(resourceInfo,
- recordGUID, recordType, recordShortName)
- except ValueError:
- continue
- yield recordGUID, autoSchedule, proxy, readOnlyProxy
-
-
def isAvailable(self):
"""
Returns True if all configured directory nodes are accessible, False otherwise
@@ -765,8 +693,8 @@
def __init__(
self, service, recordType, guid, nodeName, shortNames, authIDs,
fullName, firstName, lastName, emailAddresses,
- calendarUserAddresses,
enabledForCalendaring,
+ calendarUserAddresses,
memberGUIDs,
):
super(OpenDirectoryRecord, self).__init__(
@@ -779,8 +707,8 @@
firstName = firstName,
lastName = lastName,
emailAddresses = emailAddresses,
- calendarUserAddresses = calendarUserAddresses,
enabledForCalendaring = enabledForCalendaring,
+ calendarUserAddresses = calendarUserAddresses,
)
self.nodeName = nodeName
self._memberGUIDs = tuple(memberGUIDs)
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/cachingdirectory.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -333,23 +333,28 @@
class CachingDirectoryRecord(DirectoryRecord):
def __init__(
- self, service, recordType, guid, shortNames=(), authIDs=set(),
+ self, service, recordType, guid,
+ enabled=False, hostedAt="",
+ shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
+ enabledForCalendaring=None,
calendarUserAddresses=set(),
- enabledForCalendaring=None, uid=None,
+ uid=None,
):
super(CachingDirectoryRecord, self).__init__(
service = service,
recordType = recordType,
guid = guid,
+ enabled = enabled,
+ hostedAt = hostedAt,
shortNames = shortNames,
authIDs = authIDs,
fullName = fullName,
firstName = firstName,
lastName = lastName,
emailAddresses = emailAddresses,
+ enabledForCalendaring = enabledForCalendaring,
calendarUserAddresses = calendarUserAddresses,
- enabledForCalendaring = enabledForCalendaring,
uid = uid,
)
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/directory.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -14,6 +14,7 @@
# limitations under the License.
##
+
"""
Generic directory service classes.
"""
@@ -37,9 +38,11 @@
from twisted.web2.dav.auth import IPrincipalCredentials
from twisted.internet.defer import succeed
+from twistedcaldav.config import config
from twistedcaldav.log import LoggingMixIn
from twistedcaldav.directory.idirectory import IDirectoryService, IDirectoryRecord
from twistedcaldav.directory.util import uuidFromName
+from twistedcaldav.partitions import partitions
from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
class DirectoryService(LoggingMixIn):
@@ -282,21 +285,24 @@
implements(IDirectoryRecord)
def __repr__(self):
- return "<%s[%s@%s(%s)] %s(%s) %r>" % (
+ return "<%s[%s@%s(%s)] %s(%s) %r @ %s>" % (
self.__class__.__name__,
self.recordType,
self.service.guid,
self.service.realmName,
self.guid,
",".join(self.shortNames),
- self.fullName
+ self.fullName,
+ self.hostedAt,
)
def __init__(
- self, service, recordType, guid, shortNames=(), authIDs=set(), fullName=None,
+ self, service, recordType, guid,
+ enabled=False, hostedAt="",
+ shortNames=(), authIDs=set(), fullName=None,
firstName=None, lastName=None, emailAddresses=set(),
+ enabledForCalendaring=False,
calendarUserAddresses=set(),
- enabledForCalendaring=None,
uid=None,
):
assert service.realmName is not None
@@ -309,12 +315,6 @@
if uid is None:
uid = guid
- if enabledForCalendaring is None:
- if recordType == service.recordType_groups:
- enabledForCalendaring = False
- else:
- enabledForCalendaring = True
-
if enabledForCalendaring and recordType == service.recordType_groups:
raise AssertionError("Groups may not be enabled for calendaring")
@@ -328,6 +328,8 @@
self.recordType = recordType
self.guid = guid
self.uid = uid
+ self.enabled = enabled
+ self.hostedAt = hostedAt
self.shortNames = shortNames
self.authIDs = authIDs
self.fullName = fullName
@@ -350,7 +352,7 @@
def __hash__(self):
h = hash(self.__class__)
for attr in ("service", "recordType", "shortNames", "guid",
- "enabledForCalendaring"):
+ "enabled", "enabledForCalendaring"):
h = (h + hash(getattr(self, attr))) & sys.maxint
return h
@@ -382,6 +384,12 @@
return key
return None
+ def locallyHosted(self):
+ return not self.hostedAt or not config.EnablePartitions or self.hostedAt == config.ServerPartitionID
+
+ def hostedURL(self):
+ return partitions.getPartitionURL(self.hostedAt)
+
class DirectoryError(RuntimeError):
"""
Generic directory error.
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/idirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/idirectory.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/idirectory.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -94,14 +94,16 @@
recordType = Attribute("The type of this record.")
guid = Attribute("The GUID of this record.")
uid = Attribute("The UID of this record.")
+ enabled = Attribute("Determines whether this record should be provisioned as a principal.")
+ hostedAt = Attribute("Identifies the server that actually hosts data for the record.")
shortNames = Attribute("The names for this record.")
authIDs = Attribute("Alternative security identities for this record.")
fullName = Attribute("The full name of this record.")
firstName = Attribute("The first name of this record.")
lastName = Attribute("The last name of this record.")
emailAddress = Attribute("The email address of this record.")
+ enabledForCalendaring = Attribute("Determines whether this record should be provisioned with a calendar home.")
calendarUserAddresses = Attribute("A set of calendar user addresses for this record.")
- enabledForCalendaring = Attribute("Determines whether this record should be provisioned with a calendar home.")
def members():
"""
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/principal.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -61,6 +61,7 @@
from twistedcaldav import caldavxml, customxml
from twistedcaldav.customxml import calendarserver_namespace
from twistedcaldav.directory.wiki import getWikiACL
+from twistedcaldav.partitions import partitions
from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
log = Logger()
@@ -184,7 +185,7 @@
raise NotImplementedError("Subclass must implement principalForUID()")
def principalForRecord(self, record):
- if record is None:
+ if record is None or not record.enabled:
return None
return self.principalForUID(record.uid)
@@ -326,7 +327,7 @@
else:
# Next try looking it up in the directory
record = self.directory.recordWithCalendarUserAddress(address)
- if record is not None:
+ if record is not None and record.enabled:
return self.principalForRecord(record)
log.debug("No principal for calendar user address: %r" % (address,))
@@ -402,8 +403,9 @@
def _recordShortnameExpand():
for record in self.directory.listRecords(self.recordType):
- for shortName in record.shortNames:
- yield shortName
+ if record.enabled:
+ for shortName in record.shortNames:
+ yield shortName
return _recordShortnameExpand()
else:
@@ -463,7 +465,7 @@
record = self.directory.recordWithUID(primaryUID)
- if record is None:
+ if record is None or not record.enabled:
log.err("No principal found for UID: %s" % (name,))
return None
@@ -751,6 +753,11 @@
def principalUID(self):
return self.record.uid
+ def locallyHosted(self):
+ return self.record.locallyHosted()
+
+ def hostedURL(self):
+ return self.record.hostedURL()
##
# Extra resource info
@@ -888,11 +895,8 @@
return succeed(inbox)
def calendarHomeURLs(self):
- home = self.calendarHome()
- if home is None:
- return ()
- else:
- return (home.url(),)
+ homeURL = self._homeChildURL(None)
+ return (homeURL,) if homeURL else ()
def scheduleInboxURL(self):
return self._homeChildURL("inbox/")
@@ -911,7 +915,13 @@
if home is None:
return None
else:
- return joinURL(home.url(), name)
+ url = home.url()
+ if name:
+ url = joinURL(url, name)
+ if not self.locallyHosted():
+ url = joinURL(self.hostedURL(), url)
+
+ return url
def calendarHome(self):
# FIXME: self.record.service.calendarHomesCollection smells like a hack
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/accounts.xml 2009-08-03 21:09:08 UTC (rev 4479)
@@ -16,65 +16,77 @@
limitations under the License.
-->
-<!DOCTYPE accounts SYSTEM "../../../conf/accounts.dtd">
+<!DOCTYPE accounts SYSTEM "../../../conf/auth/accounts.dtd">
<accounts realm="Test">
<user>
<uid>admin</uid>
<guid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</guid>
<password>nimda</password>
+ <enable>true</enable>
<name>Administrators</name>
</user>
<user>
<uid>wsanchez</uid>
<guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
<password>zehcnasw</password>
+ <enable>true</enable>
<name>Wilfredo Sanchez</name>
<email-address>wsanchez at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:wsanchez at example.com</cuaddr>
</user>
<user>
<uid>cdaboo</uid>
<guid>5A985493-EE2C-4665-94CF-4DFEA3A89500</guid>
<password>oobadc</password>
+ <enable>true</enable>
<name>Cyrus Daboo</name>
<email-address>cdaboo at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:cdaboo at example.com</cuaddr>
</user>
<user>
<uid>lecroy</uid>
<guid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</guid>
<password>yorcel</password>
+ <enable>true</enable>
<name>Chris Lecroy</name>
<email-address>lecroy at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:lecroy at example.com</cuaddr>
</user>
<user>
<uid>dreid</uid>
<guid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
<password>dierd</password>
+ <enable>true</enable>
<name>David Reid</name>
<email-address>dreid at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:dreid at example.com</cuaddr>
</user>
<user>
<uid>nocalendar</uid>
<guid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</guid>
<password>radnelacon</password>
+ <enable>true</enable>
<name>No Calendar</name>
<email-address>nocalendar at example.com</email-address>
- <disable-calendar/>
</user>
<user repeat="2">
<uid>user%02d</uid>
<guid>user%02d</guid>
<password>%02duser</password>
+ <enable>true</enable>
<name>User %02d</name>
+ <enable-calendar>true</enable-calendar>
</user>
<group>
<uid>managers</uid>
<guid>9FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
<password>managers</password>
+ <enable>true</enable>
<name>Managers</name>
<members>
<member type="users">lecroy</member>
@@ -84,6 +96,7 @@
<uid>admin</uid>
<guid>admin</guid>
<password>admin</password>
+ <enable>true</enable>
<name>Administrators</name>
<members>
<member type="groups">managers</member>
@@ -93,6 +106,7 @@
<uid>grunts</uid>
<guid>grunts</guid>
<password>grunts</password>
+ <enable>true</enable>
<name>We do all the work</name>
<members>
<member>wsanchez</member>
@@ -104,6 +118,7 @@
<uid>right_coast</uid>
<guid>right_coast</guid>
<password>right_coast</password>
+ <enable>true</enable>
<name>East Coast</name>
<members>
<member>cdaboo</member>
@@ -113,6 +128,7 @@
<uid>left_coast</uid>
<guid>left_coast</guid>
<password>left_coast</password>
+ <enable>true</enable>
<name>West Coast</name>
<members>
<member>wsanchez</member>
@@ -124,6 +140,7 @@
<uid>both_coasts</uid>
<guid>both_coasts</guid>
<password>both_coasts</password>
+ <enable>true</enable>
<name>Both Coasts</name>
<members>
<member type="groups">right_coast</member>
@@ -134,6 +151,7 @@
<uid>recursive1_coasts</uid>
<guid>recursive1_coasts</guid>
<password>recursive1_coasts</password>
+ <enable>true</enable>
<name>Recursive1 Coasts</name>
<members>
<member type="groups">recursive2_coasts</member>
@@ -144,6 +162,7 @@
<uid>recursive2_coasts</uid>
<guid>recursive2_coasts</guid>
<password>recursive2_coasts</password>
+ <enable>true</enable>
<name>Recursive2 Coasts</name>
<members>
<member type="groups">recursive1_coasts</member>
@@ -154,19 +173,21 @@
<uid>non_calendar_group</uid>
<guid>non_calendar_group</guid>
<password>non_calendar_group</password>
+ <enable>true</enable>
<name>Non-calendar group</name>
<members>
<member>cdaboo</member>
<member>lecroy</member>
</members>
- <disable-calendar/>
</group>
<location>
<uid>mercury</uid>
<guid>mercury</guid>
<password>mercury</password>
+ <enable>true</enable>
<name>Mecury Seven</name>
<email-address>mercury at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:mercury at example.com</cuaddr>
<proxies>
<member type="groups">left_coast</member>
@@ -176,10 +197,12 @@
<uid>gemini</uid>
<guid>gemini</guid>
<password>gemini</password>
+ <enable>true</enable>
<name>Gemini Twelve</name>
<email-address>gemini at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:gemini at example.com</cuaddr>
- <auto-schedule/>
+ <auto-schedule>true</auto-schedule>
<proxies>
<member>wsanchez</member>
</proxies>
@@ -188,8 +211,10 @@
<uid>apollo</uid>
<guid>apollo</guid>
<password>apollo</password>
+ <enable>true</enable>
<name>Apollo Eleven</name>
<email-address>apollo at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:apollo at example.com</cuaddr>
<proxies>
<member type="groups">both_coasts</member>
@@ -199,8 +224,10 @@
<uid>orion</uid>
<guid>orion</guid>
<password>orion</password>
+ <enable>true</enable>
<name>Orion</name>
<email-address>orion at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:orion at example.com</cuaddr>
<proxies>
<member type="groups">recursive1_coasts</member>
@@ -210,24 +237,30 @@
<uid>transporter</uid>
<guid>transporter</guid>
<password>transporter</password>
+ <enable>true</enable>
<name>Mass Transporter</name>
<email-address>transporter at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:transporter at example.com</cuaddr>
</resource>
<resource>
<uid>ftlcpu</uid>
<guid>ftlcpu</guid>
<password>ftlcpu</password>
+ <enable>true</enable>
<name>Faster-Than-Light Microprocessor</name>
<email-address>ftlcpu at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:ftlcpu at example.com</cuaddr>
</resource>
<resource>
<uid>non_calendar_proxy</uid>
<guid>non_calendar_proxy</guid>
<password>non_calendar_proxy</password>
+ <enable>true</enable>
<name>Non-calendar proxy</name>
<email-address>non_calendar_proxy at example.com</email-address>
+ <enable-calendar>true</enable-calendar>
<cuaddr>mailto:non_calendar_proxy at example.com</cuaddr>
<proxies>
<member type="groups">non_calendar_group</member>
Deleted: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectoryschema.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_opendirectoryschema.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -1,147 +0,0 @@
-##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-try:
- from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
-except ImportError:
- pass
-else:
- from twistedcaldav.test.util import TestCase
-
- class ODResourceInfoParse (TestCase):
-
- plist_good_false = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <dict>
- <key>AutoAcceptsInvitation</key>
- <false/>
- <key>Label</key>
- <string>Location</string>
- <key>CalendaringDelegate</key>
- <string>1234-GUID-5678</string>
- <key>ReadOnlyCalendaringDelegate</key>
- <string>1234-GUID-5679</string>
- </dict>
-</dict>
-</plist>
-"""
-
- plist_good_true = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <dict>
- <key>AutoAcceptsInvitation</key>
- <true/>
- <key>Label</key>
- <string>Location</string>
- <key>CalendaringDelegate</key>
- <string></string>
- <key>ReadOnlyCalendaringDelegate</key>
- <string></string>
- </dict>
-</dict>
-</plist>
-"""
-
- plist_good_missing = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <dict>
- <key>Label</key>
- <string>Location</string>
- </dict>
-</dict>
-</plist>
-"""
-
- plist_bad = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <string>bogus</string>
-</dict>
-</plist>
-"""
-
- plist_wrong = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.YellowPagesFramework</key>
- <dict>
- <key>AutoAcceptsInvitation</key>
- <true/>
- <key>Label</key>
- <string>Location</string>
- <key>CalendaringDelegate</key>
- <string>1234-GUID-5678</string>
- <key>ReadOnlyCalendaringDelegate</key>
- <string>1234-GUID-5679</string>
- </dict>
-</dict>
-</plist>
-"""
-
- plist_invalid = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <string>bogus</string>
- <string>another bogon</string>
-</dict>
-</plist>
-"""
-
- plist_invalid_xml = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.WhitePagesFramework</key>
- <string>R&D</string>
-</dict>
-</plist>
-"""
-
- test_bool = (
- (plist_good_false, False, "1234-GUID-5678", "1234-GUID-5679", None),
- (plist_good_true, True, "", "", None),
- (plist_good_missing, False, None, None, None),
- (plist_wrong, False, None, None, None),
- (plist_bad, False, None, None, ValueError),
- (plist_invalid, False, None, None, ValueError),
- (plist_invalid_xml, False, None, None, ValueError),
- )
-
- def test_plists(self):
- service = OpenDirectoryService({'node' : "/Search"}, dosetup=False)
-
- for item in ODResourceInfoParse.test_bool:
- if item[4] is None:
- item1, item2, item3 = service._parseResourceInfo(item[0], "guid", "locations", "name")
- self.assertEqual(item1, item[1])
- self.assertEqual(item2, item[2])
- self.assertEqual(item3, item[3])
- else:
- self.assertRaises(item[4], service._parseResourceInfo, item[0], "guid", "locations", "name")
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_principal.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -193,7 +193,7 @@
"""
for provisioningResource, recordType, recordResource, record in self._allRecords():
principal = provisioningResource.principalForRecord(record)
- self.failIf(principal is None)
+ self.failIf(principal is None, msg=str(record))
self.assertEquals(record, principal.record)
def test_principalForCalendarUserAddress(self):
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_proxyprincipalmembers.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -423,7 +423,7 @@
delRec = self.directoryService.recordWithShortName(
DirectoryService.recordType_users, "dreid")
for cache in self.directoryService._recordCaches.itervalues():
- cache.removeRecord(delRec)
+ cache.removeRecord(delRec)
del self.directoryService._accounts()[
DirectoryService.recordType_users]["dreid"]
@@ -479,7 +479,7 @@
delRec = self.directoryService.recordWithShortName(
DirectoryService.recordType_users, "dreid")
for cache in self.directoryService._recordCaches.itervalues():
- cache.removeRecord(delRec)
+ cache.removeRecord(delRec)
del self.directoryService._accounts()[
DirectoryService.recordType_users]["dreid"]
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/test/test_xmlfile.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -110,6 +110,7 @@
<uid>admin</uid>
<guid>admin</guid>
<password>nimda</password>
+ <enable>true</enable>
<name>Super User</name>
</user>
</accounts>
@@ -142,8 +143,10 @@
<uid>my office</uid>
<guid>myoffice</guid>
<password>nimda</password>
+ <enable>true</enable>
<name>Super User</name>
- <auto-schedule/>
+ <enable-calendar>true</enable-calendar>
+ <auto-schedule>true</auto-schedule>
</location>
</accounts>
"""
@@ -176,13 +179,14 @@
<group>
<uid>enabled</uid>
<password>enabled</password>
+ <enable>true</enable>
<name>Enabled</name>
</group>
<group>
<uid>disabled</uid>
<password>disabled</password>
+ <enable>true</enable>
<name>Disabled</name>
- <disable-calendar/>
</group>
</accounts>
"""
@@ -218,14 +222,18 @@
<uid>test</uid>
<guid>test</guid>
<password>nimda</password>
+ <enable>true</enable>
<name>Test</name>
+ <enable-calendar>true</enable-calendar>
</user>
<location>
<uid>my office</uid>
<guid>myoffice</guid>
<password>nimda</password>
+ <enable>true</enable>
<name>Super User</name>
- <auto-schedule/>
+ <enable-calendar>true</enable-calendar>
+ <auto-schedule>true</auto-schedule>
<proxies>
<member>test</member>
</proxies>
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlaccountsparser.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -44,15 +44,17 @@
ELEMENT_SHORTNAME = "uid"
ELEMENT_GUID = "guid"
ELEMENT_PASSWORD = "password"
+ELEMENT_ENABLE = "enable"
+ELEMENT_HOSTEDAT = "hosted-at"
ELEMENT_NAME = "name"
ELEMENT_FIRST_NAME = "first-name"
ELEMENT_LAST_NAME = "last-name"
ELEMENT_EMAIL_ADDRESS = "email-address"
ELEMENT_MEMBERS = "members"
ELEMENT_MEMBER = "member"
+ELEMENT_ENABLECALENDAR = "enable-calendar"
ELEMENT_CUADDR = "cuaddr"
ELEMENT_AUTOSCHEDULE = "auto-schedule"
-ELEMENT_DISABLECALENDAR = "disable-calendar"
ELEMENT_PROXIES = "proxies"
ELEMENT_READ_ONLY_PROXIES = "read-only-proxies"
@@ -60,6 +62,9 @@
ATTRIBUTE_REPEAT = "repeat"
ATTRIBUTE_RECORDTYPE = "type"
+VALUE_TRUE = "true"
+VALUE_FALSE = "false"
+
RECORD_TYPES = {
ELEMENT_USER : DirectoryService.recordType_users,
ELEMENT_GROUP : DirectoryService.recordType_groups,
@@ -204,6 +209,8 @@
self.shortNames = []
self.guid = None
self.password = None
+ self.enabled = True
+ self.hostedAt = ""
self.fullName = None
self.firstName = None
self.lastName = None
@@ -212,10 +219,7 @@
self.groups = set()
self.calendarUserAddresses = set()
self.autoSchedule = False
- if recordType == DirectoryService.recordType_groups:
- self.enabledForCalendaring = False
- else:
- self.enabledForCalendaring = True
+ self.enabledForCalendaring = False
self.proxies = set()
self.proxyFor = set()
self.readOnlyProxies = set()
@@ -270,6 +274,8 @@
result.shortNames = shortNames
result.guid = guid
result.password = password
+ result.enabled = self.enabled
+ result.hostedAt = self.hostedAt
result.fullName = fullName
result.firstName = firstName
result.lastName = lastName
@@ -295,6 +301,12 @@
self.guid = child.firstChild.data.encode("utf-8")
if len(self.guid) < 4:
self.guid += "?" * (4 - len(self.guid))
+ elif child_name == ELEMENT_ENABLE:
+ if child.firstChild is not None:
+ self.enabled = (child.firstChild.data.encode("utf-8") == VALUE_TRUE)
+ elif child_name == ELEMENT_HOSTEDAT:
+ if child.firstChild is not None:
+ self.hostedAt = child.firstChild.data.encode("utf-8")
elif child_name == ELEMENT_PASSWORD:
if child.firstChild is not None:
self.password = child.firstChild.data.encode("utf-8")
@@ -312,17 +324,15 @@
self.emailAddresses.add(child.firstChild.data.encode("utf-8").lower())
elif child_name == ELEMENT_MEMBERS:
self._parseMembers(child, self.members)
+ elif child_name == ELEMENT_ENABLECALENDAR:
+ if child.firstChild is not None:
+ self.enabledForCalendaring = (child.firstChild.data.encode("utf-8") == VALUE_TRUE)
elif child_name == ELEMENT_CUADDR:
if child.firstChild is not None:
self.calendarUserAddresses.add(child.firstChild.data.encode("utf-8"))
elif child_name == ELEMENT_AUTOSCHEDULE:
- self.autoSchedule = True
- elif child_name == ELEMENT_DISABLECALENDAR:
- # FIXME: Not sure I see why this restriction is needed. --wsanchez
- ## Only Users or Groups
- #if self.recordType != DirectoryService.recordType_users:
- # raise ValueError("<disable-calendar> element only allowed for Users: %s" % (child_name,))
- self.enabledForCalendaring = False
+ if child.firstChild is not None:
+ self.autoSchedule = (child.firstChild.data.encode("utf-8") == VALUE_TRUE)
elif child_name == ELEMENT_PROXIES:
self._parseMembers(child, self.proxies)
elif child_name == ELEMENT_READ_ONLY_PROXIES:
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/directory/xmlfile.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -186,13 +186,15 @@
service = service,
recordType = recordType,
guid = xmlPrincipal.guid,
+ enabled = xmlPrincipal.enabled,
+ hostedAt = xmlPrincipal.hostedAt,
shortNames = shortNames,
fullName = xmlPrincipal.fullName,
firstName = xmlPrincipal.firstName,
lastName = xmlPrincipal.lastName,
emailAddresses = xmlPrincipal.emailAddresses,
+ enabledForCalendaring = xmlPrincipal.enabledForCalendaring,
calendarUserAddresses = xmlPrincipal.calendarUserAddresses,
- enabledForCalendaring = xmlPrincipal.enabledForCalendaring,
)
self.password = xmlPrincipal.password
@@ -208,9 +210,10 @@
yield self.service.recordWithShortName(DirectoryService.recordType_groups, shortName)
def verifyCredentials(self, credentials):
- if isinstance(credentials, UsernamePassword):
- return credentials.password == self.password
- if isinstance(credentials, DigestedCredentials):
- return credentials.checkPassword(self.password)
+ if self.enabled:
+ if isinstance(credentials, UsernamePassword):
+ return credentials.password == self.password
+ if isinstance(credentials, DigestedCredentials):
+ return credentials.checkPassword(self.password)
return super(XMLDirectoryRecord, self).verifyCredentials(credentials)
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/log.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -166,7 +166,7 @@
Clears all log levels to the default.
"""
logLevelsByNamespace.clear()
- logLevelsByNamespace[None] = "info" # Default log level
+ logLevelsByNamespace[None] = "warn" # Default log level
logLevelsByNamespace = {}
clearLogLevels()
Added: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/partitions.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/partitions.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/partitions.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -0,0 +1,56 @@
+##
+# Copyright (c) 2009 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twistedcaldav.log import Logger
+from twext.python.plistlib import readPlist
+
+"""
+Collection of classes for managing partition information for a group of servers.
+"""
+
+log = Logger()
+
+class Partitions(object):
+
+ def __init__(self):
+
+ self.clear()
+
+ def clear(self):
+ self.partitions = {}
+ self.ownUID = ""
+
+ def readConfig(self, plistpath):
+ try:
+ dataDict = readPlist(plistpath)
+ except (IOError, OSError):
+ log.error("Configuration file does not exist or is inaccessible: %s" % (self._configFileName,))
+ return
+
+ for partition in dataDict.get("partitions", ()):
+ uid = partition.get("uid", None)
+ url = partition.get("url", None)
+ if uid and url:
+ self.partitions[uid] = url
+
+ def setSelfPartition(self, uid):
+ self.ownUID = uid
+
+ def getPartitionURL(self, uid):
+ # When the UID matches this server return an empty string
+ return self.partitions.get(uid, None) if uid != self.ownUID else ""
+
+partitions = Partitions()
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/addressmapping.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/addressmapping.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/addressmapping.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -22,7 +22,8 @@
from twistedcaldav.scheduling.imip import ScheduleViaIMip
from twistedcaldav.scheduling.ischedule import ScheduleViaISchedule
from twistedcaldav.scheduling.cuaddress import LocalCalendarUser,\
- RemoteCalendarUser, EmailCalendarUser, InvalidCalendarUser
+ RemoteCalendarUser, EmailCalendarUser, InvalidCalendarUser,\
+ PartitionedCalendarUser
from twisted.internet.defer import inlineCallbacks, returnValue
__all__ = [
@@ -49,17 +50,14 @@
@inlineCallbacks
def getCalendarUser(self, cuaddr, principal):
- # If we have a principal always treat the user as local
+ # If we have a principal always treat the user as local or partitioned
if principal:
- returnValue(LocalCalendarUser(cuaddr, principal))
+ returnValue(LocalCalendarUser(cuaddr, principal) if principal.locallyHosted() else PartitionedCalendarUser(cuaddr, principal))
# Get the type
cuaddr_type = (yield self.getCalendarUserServiceType(cuaddr))
if cuaddr_type == DeliveryService.serviceType_caldav:
- if principal:
- returnValue(LocalCalendarUser(cuaddr, principal))
- else:
- returnValue(InvalidCalendarUser(cuaddr))
+ returnValue(InvalidCalendarUser(cuaddr))
elif cuaddr_type == DeliveryService.serviceType_ischedule:
returnValue(RemoteCalendarUser(cuaddr))
elif cuaddr_type == DeliveryService.serviceType_imip:
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/cuaddress.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/cuaddress.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/cuaddress.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -43,6 +43,15 @@
def __str__(self):
return "Local calendar user: %s" % (self.cuaddr,)
+class PartitionedCalendarUser(CalendarUser):
+ def __init__(self, cuaddr, principal):
+ self.cuaddr = cuaddr
+ self.principal = principal
+ self.serviceType = DeliveryService.serviceType_ischedule
+
+ def __str__(self):
+ return "Partitioned calendar user: %s" % (self.cuaddr,)
+
class RemoteCalendarUser(CalendarUser):
def __init__(self, cuaddr):
self.cuaddr = cuaddr
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischedule.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischedule.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischedule.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -24,7 +24,7 @@
from twisted.web2 import responsecode
from twisted.web2.client.http import ClientRequest
from twisted.web2.client.http import HTTPClientProtocol
-from twisted.web2.dav.util import davXMLFromStream
+from twisted.web2.dav.util import davXMLFromStream, joinURL
from twisted.web2.http import HTTPError
from twisted.web2.http_headers import Headers
from twisted.web2.http_headers import MimeType
@@ -36,9 +36,12 @@
from twistedcaldav.config import config
from twistedcaldav.log import Logger
from twistedcaldav.scheduling.delivery import DeliveryService
-from twistedcaldav.scheduling.ischeduleservers import IScheduleServers
+from twistedcaldav.scheduling.ischeduleservers import IScheduleServers,\
+ IScheduleServerRecord
from twistedcaldav.scheduling.itip import iTIPRequestStatus
from twistedcaldav.util import utf8String
+from twistedcaldav.scheduling.cuaddress import RemoteCalendarUser,\
+ PartitionedCalendarUser
import OpenSSL
@@ -76,8 +79,13 @@
groups = {}
servermgr = IScheduleServers()
for recipient in self.recipients:
- # Map the recipient's domain to a server
- server = servermgr.mapDomain(recipient.domain)
+ if isinstance(recipient, RemoteCalendarUser):
+ # Map the recipient's domain to a server
+ server = servermgr.mapDomain(recipient.domain)
+ elif isinstance(recipient, PartitionedCalendarUser):
+ server = self._getServerForPartitionedUser(recipient)
+ else:
+ assert False, "Incorrect calendar user address class"
if not server:
# Cannot do server-to-server for this recipient.
err = HTTPError(ErrorResponse(responsecode.NOT_FOUND, (caldav_namespace, "recipient-allowed")))
@@ -109,6 +117,18 @@
return DeferredList(deferreds)
+ def _getServerForPartitionedUser(self, recipient):
+
+ if not hasattr(self, "partitionedServers"):
+ self.partitionedServers = {}
+
+ partition = recipient.principal.hostedURL()
+ if partition not in self.partitionedServers:
+ self.partitionedServers[partition] = IScheduleServerRecord(uri=joinURL(partition, "/ischedule"))
+ self.partitionedServers[partition].unNormalizeAddresses = False
+
+ return self.partitionedServers[partition]
+
class IScheduleRequest(object):
def __init__(self, scheduler, server, recipients, responses):
@@ -166,7 +186,7 @@
)
def _prepareData(self):
- if self.scheduler.method == "PUT":
+ if self.server.unNormalizeAddresses and self.scheduler.method == "PUT":
def lookupFunction(cuaddr):
principal = self.scheduler.resource.principalForCalendarUserAddress(cuaddr)
if principal is None:
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischeduleservers.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischeduleservers.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/ischeduleservers.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -123,7 +123,7 @@
"""
Contains server-to-server details.
"""
- def __init__(self):
+ def __init__(self, uri=None):
"""
@param recordType: record type for directory entry.
"""
@@ -133,6 +133,11 @@
self.allow_to = True
self.domains = []
self.client_hosts = []
+ self.unNormalizeAddresses = True
+
+ if uri:
+ self.uri = uri
+ self._parseDetails()
def parseXML(self, node):
for child in node._get_childNodes():
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/scheduler.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/scheduler.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/scheduler.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -36,7 +36,8 @@
from twistedcaldav.scheduling import addressmapping
from twistedcaldav.scheduling.caldav import ScheduleViaCalDAV
from twistedcaldav.scheduling.cuaddress import InvalidCalendarUser,\
- LocalCalendarUser, RemoteCalendarUser, EmailCalendarUser
+ LocalCalendarUser, RemoteCalendarUser, EmailCalendarUser,\
+ PartitionedCalendarUser
from twistedcaldav.scheduling.imip import ScheduleViaIMip
from twistedcaldav.scheduling.ischedule import ScheduleViaISchedule
from twistedcaldav.scheduling.ischeduleservers import IScheduleServers
@@ -45,6 +46,7 @@
import itertools
import re
import socket
+import urlparse
"""
CalDAV/Server-to-Server scheduling behavior.
@@ -244,7 +246,7 @@
def checkOriginator(self):
raise NotImplementedError
- def checkRecipient(self):
+ def checkRecipients(self):
raise NotImplementedError
def checkOrganizer(self):
@@ -363,6 +365,9 @@
elif isinstance(recipient, LocalCalendarUser):
caldav_recipients.append(recipient)
+ elif isinstance(recipient, PartitionedCalendarUser):
+ remote_recipients.append(recipient)
+
elif isinstance(recipient, RemoteCalendarUser):
remote_recipients.append(recipient)
@@ -490,10 +495,10 @@
inbox = None
inboxURL = principal.scheduleInboxURL()
if inboxURL:
- inbox = (yield self.request.locateResource(inboxURL))
+ inbox = (yield self.request.locateResource(inboxURL)) if principal.locallyHosted() else "dummy"
if inbox:
- results.append(LocalCalendarUser(recipient, principal, inbox, inboxURL))
+ results.append(LocalCalendarUser(recipient, principal, inbox, inboxURL) if principal.locallyHosted() else PartitionedCalendarUser(recipient, principal))
else:
log.err("No schedule inbox for principal: %s" % (principal,))
results.append(InvalidCalendarUser(recipient))
@@ -609,8 +614,53 @@
else:
raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Invalid iTIP message for implicit scheduling"))
-class IScheduleScheduler(Scheduler):
+class RemoteScheduler(Scheduler):
+ def checkOrganizer(self):
+ """
+ Delay ORGANIZER check until we know what their role is.
+ """
+ pass
+
+ @inlineCallbacks
+ def checkRecipients(self):
+ """
+ Check the validity of the Recipient header values. These must all be local as there
+ is no concept of server-to-server relaying.
+ """
+
+ results = []
+ for recipient in self.recipients:
+ # Get the principal resource for this recipient
+ principal = self.resource.principalForCalendarUserAddress(recipient)
+
+ # If no principal we may have a remote recipient but we should check whether
+ # the address is one that ought to be on our server and treat that as a missing
+ # user. Also if server-to-server is not enabled then remote addresses are not allowed.
+ if principal is None:
+ localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(recipient))
+ if localUser:
+ log.err("No principal for calendar user address: %s" % (recipient,))
+ else:
+ log.err("Unknown calendar user address: %s" % (recipient,))
+ results.append(InvalidCalendarUser(recipient))
+ else:
+ # Map recipient to their inbox
+ inbox = None
+ inboxURL = principal.scheduleInboxURL()
+ if inboxURL:
+ inbox = (yield self.request.locateResource(inboxURL)) if principal.locallyHosted() else "dummy"
+
+ if inbox:
+ results.append(LocalCalendarUser(recipient, principal, inbox, inboxURL) if principal.locallyHosted() else PartitionedCalendarUser(recipient, principal))
+ else:
+ log.err("No schedule inbox for principal: %s" % (principal,))
+ results.append(InvalidCalendarUser(recipient))
+
+ self.recipients = results
+
+class IScheduleScheduler(RemoteScheduler):
+
def checkAuthorization(self):
# Must have an unauthenticated user
if self.resource.currentPrincipal(self.request) != davxml.Principal(davxml.Unauthenticated()):
@@ -627,11 +677,21 @@
originatorPrincipal = self.resource.principalForCalendarUserAddress(self.originator)
localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(self.originator))
if originatorPrincipal or localUser:
- log.err("Cannot use originator that is on this server: %s" % (self.originator,))
- raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
+ if originatorPrincipal.locallyHosted():
+ log.err("Cannot use originator that is on this server: %s" % (self.originator,))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
+ else:
+ self.originator = PartitionedCalendarUser(self.originator, originatorPrincipal)
+ #self._validPartitionServer()
else:
self.originator = RemoteCalendarUser(self.originator)
-
+ self._validiScheduleServer()
+
+ def _validiScheduleServer(self):
+ """
+ Check the validity of the iSchedule host.
+ """
+
# We will only accept originator in known domains.
servermgr = IScheduleServers()
server = servermgr.mapDomain(self.originator.domain)
@@ -675,49 +735,38 @@
log.err("Originator not on allowed server: %s" % (self.originator,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
- @inlineCallbacks
- def checkRecipients(self):
+ def _validPartitionServer(self, principal):
"""
- Check the validity of the Recipient header values. These must all be local as there
- is no concept of server-to-server relaying.
+ Check the validity of the partitioned host.
"""
-
- results = []
- for recipient in self.recipients:
- # Get the principal resource for this recipient
- principal = self.resource.principalForCalendarUserAddress(recipient)
-
- # If no principal we may have a remote recipient but we should check whether
- # the address is one that ought to be on our server and treat that as a missing
- # user. Also if server-to-server is not enabled then remote addresses are not allowed.
- if principal is None:
- localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(recipient))
- if localUser:
- log.err("No principal for calendar user address: %s" % (recipient,))
- else:
- log.err("Unknown calendar user address: %s" % (recipient,))
- results.append(InvalidCalendarUser(recipient))
- else:
- # Map recipient to their inbox
- inbox = None
- inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield self.request.locateResource(inboxURL))
- if inbox:
- results.append(LocalCalendarUser(recipient, principal, inbox, inboxURL))
- else:
- log.err("No schedule inbox for principal: %s" % (principal,))
- results.append(InvalidCalendarUser(recipient))
+ # Extract expected host/port
+ expected_uri = principal.hostedURL()
+ expected_uri = urlparse.urlparse(expected_uri)
+
+ # Get the request IP and map to hostname.
+ clientip = self.request.remoteAddr.host
- self.recipients = results
+ # First compare as dotted IP
+ matched = False
+ if clientip == expected_uri.hostname:
+ matched = True
+ else:
+ # Now do hostname lookup
+ try:
+ host, aliases, _ignore_ips = socket.gethostbyaddr(clientip)
+ for hostname in itertools.chain((host,), aliases):
+ # Try host match
+ if hostname == expected_uri.hostname:
+ matched = True
+ break
+ except socket.herror, e:
+ log.debug("iSchedule cannot lookup client ip '%s': %s" % (clientip, str(e),))
+
+ if not matched:
+ log.err("Originator not on allowed server: %s" % (self.originator,))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
- def checkOrganizer(self):
- """
- Delay ORGANIZER check until we know what their role is.
- """
- pass
-
@inlineCallbacks
def checkOrganizerAsOriginator(self):
"""
@@ -729,8 +778,13 @@
if organizer:
organizerPrincipal = self.resource.principalForCalendarUserAddress(organizer)
if organizerPrincipal:
- log.err("Invalid ORGANIZER in calendar data: %s" % (self.calendar,))
- raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "organizer-allowed")))
+ if organizerPrincipal.locallyHosted():
+ log.err("Invalid ORGANIZER in calendar data: %s" % (self.calendar,))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "organizer-allowed")))
+ else:
+ # Check that the origin server is the correct partition
+ self.organizer = PartitionedCalendarUser(organizer, organizerPrincipal)
+ self._validPartitionServer(self.organizer.principal)
else:
localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(organizer))
if localUser:
@@ -761,8 +815,11 @@
# Attendee cannot be local.
attendeePrincipal = self.resource.principalForCalendarUserAddress(attendee)
if attendeePrincipal:
- log.err("Invalid ATTENDEE in calendar data: %s" % (self.calendar,))
- raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "attendee-allowed")))
+ if attendeePrincipal.locallyHosted():
+ log.err("Invalid ATTENDEE in calendar data: %s" % (self.calendar,))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "attendee-allowed")))
+ else:
+ self._validPartitionServer(attendeePrincipal)
else:
localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(attendee))
if localUser:
@@ -817,13 +874,25 @@
pass
-class IMIPScheduler(Scheduler):
+class IMIPScheduler(RemoteScheduler):
def checkAuthorization(self):
pass
- def checkOrganizer(self):
- pass
+ @inlineCallbacks
+ def checkOriginator(self):
+ """
+ Check the validity of the Originator header.
+ """
+
+ # For remote requests we do not allow the originator to be a local user or one within our domain.
+ originatorPrincipal = self.resource.principalForCalendarUserAddress(self.originator)
+ localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(self.originator))
+ if originatorPrincipal or localUser:
+ log.err("Cannot use originator that is on this server: %s" % (self.originator,))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
+ else:
+ self.originator = RemoteCalendarUser(self.originator)
def checkOrganizerAsOriginator(self):
pass
@@ -847,60 +916,7 @@
# TODO: verify this is the right response:
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
- @inlineCallbacks
- def checkOriginator(self):
- """
- Check the validity of the Originator header.
- """
-
- # For remote requests we do not allow the originator to be a local user or one within our domain.
- originatorPrincipal = self.resource.principalForCalendarUserAddress(self.originator)
- localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(self.originator))
- if originatorPrincipal or localUser:
- log.err("Cannot use originator that is on this server: %s" % (self.originator,))
- raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "originator-allowed")))
- else:
- self.originator = RemoteCalendarUser(self.originator)
- @inlineCallbacks
- def checkRecipients(self):
- """
- Check the validity of the Recipient header values. These must all be local as there
- is no concept of server-to-server relaying.
- """
-
- results = []
- for recipient in self.recipients:
- # Get the principal resource for this recipient
- principal = self.resource.principalForCalendarUserAddress(recipient)
-
- # If no principal we may have a remote recipient but we should check whether
- # the address is one that ought to be on our server and treat that as a missing
- # user. Also if server-to-server is not enabled then remote addresses are not allowed.
- if principal is None:
- localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(recipient))
- if localUser:
- log.err("No principal for calendar user address: %s" % (recipient,))
- else:
- log.err("Unknown calendar user address: %s" % (recipient,))
- results.append(InvalidCalendarUser(recipient))
- else:
- # Map recipient to their inbox
- inbox = None
- inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield self.request.locateResource(inboxURL))
-
- if inbox:
- results.append(LocalCalendarUser(recipient, principal, inbox, inboxURL))
- else:
- log.err("No schedule inbox for principal: %s" % (principal,))
- results.append(InvalidCalendarUser(recipient))
-
- self.recipients = results
-
-
-
class ScheduleResponseResponse (Response):
"""
ScheduleResponse L{Response} object.
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/utils.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/utils.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/scheduling/utils.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -23,12 +23,14 @@
Get a copy of the event for a principal.
"""
- result = {}
- result["resource"] = None
- result["resource_name"] = None
- result["calendar_collection"] = None
- result["calendar_collection_uri"] = None
- if principal:
+ result = {
+ "resource": None,
+ "resource_name": None,
+ "calendar_collection": None,
+ "calendar_collection_uri": None,
+ }
+
+ if principal and principal.locallyHosted():
# Get principal's calendar-home
calendar_home = principal.calendarHome()
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/static.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/static.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/static.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -38,6 +38,7 @@
import os
import errno
from urlparse import urlsplit
+import urlparse
from twext.web2.dav.davxml import ErrorResponse
@@ -51,7 +52,8 @@
from twisted.web2.dav.noneprops import NonePropertyStore
from twisted.web2.dav.resource import AccessDeniedError
from twisted.web2.dav.resource import davPrivilegeSet
-from twisted.web2.dav.util import parentForURL, bindMethods
+from twisted.web2.dav.util import parentForURL, bindMethods, joinURL
+from twisted.web2.resource import RedirectResource
from twistedcaldav import caldavxml
from twistedcaldav import customxml
@@ -652,60 +654,78 @@
assert len(name) > 4, "Directory record has an invalid GUID: %r" % (name,)
- childPath = self.fp.child(name[0:2]).child(name[2:4]).child(name)
- child = self.homeResourceClass(childPath.path, self, record)
-
- if not child.exists():
- self.provision()
-
- if not childPath.parent().isdir():
- childPath.parent().makedirs()
-
- for oldPath in (
- # Pre 2.0: All in one directory
- self.fp.child(name),
- # Pre 1.2: In types hierarchy instead of the GUID hierarchy
- self.parent.getChild(record.recordType).fp.child(record.shortNames[0]),
- ):
- if oldPath.exists():
- # The child exists at an old location. Move to new location.
- log.msg("Moving calendar home from old location %r to new location %r." % (oldPath, childPath))
- try:
- oldPath.moveTo(childPath)
- except (OSError, IOError), e:
- log.err("Error moving calendar home %r: %s" % (oldPath, e))
+ if record.locallyHosted():
+ childPath = self.fp.child(name[0:2]).child(name[2:4]).child(name)
+ child = self.homeResourceClass(childPath.path, self, record)
+
+ if not child.exists():
+ self.provision()
+
+ if not childPath.parent().isdir():
+ childPath.parent().makedirs()
+
+ for oldPath in (
+ # Pre 2.0: All in one directory
+ self.fp.child(name),
+ # Pre 1.2: In types hierarchy instead of the GUID hierarchy
+ self.parent.getChild(record.recordType).fp.child(record.shortNames[0]),
+ ):
+ if oldPath.exists():
+ # The child exists at an old location. Move to new location.
+ log.msg("Moving calendar home from old location %r to new location %r." % (oldPath, childPath))
+ try:
+ oldPath.moveTo(childPath)
+ except (OSError, IOError), e:
+ log.err("Error moving calendar home %r: %s" % (oldPath, e))
+ raise HTTPError(StatusResponse(
+ responsecode.INTERNAL_SERVER_ERROR,
+ "Unable to move calendar home."
+ ))
+ child.fp.restat(False)
+ break
+ else:
+ #
+ # NOTE: provisionDefaultCalendars() returns a deferred, which we are ignoring.
+ # The result being that the default calendars will be present at some point
+ # in the future, not necessarily right now, and we don't have a way to wait
+ # on that to finish.
+ #
+ child.provisionDefaultCalendars()
+
+ #
+ # Try to work around the above a little by telling the client that something
+ # when wrong temporarily if the child isn't provisioned right away.
+ #
+ if not child.exists():
raise HTTPError(StatusResponse(
- responsecode.INTERNAL_SERVER_ERROR,
- "Unable to move calendar home."
+ responsecode.SERVICE_UNAVAILABLE,
+ "Provisioning calendar home."
))
- child.fp.restat(False)
- break
- else:
- #
- # NOTE: provisionDefaultCalendars() returns a deferred, which we are ignoring.
- # The result being that the default calendars will be present at some point
- # in the future, not necessarily right now, and we don't have a way to wait
- # on that to finish.
- #
- child.provisionDefaultCalendars()
+
+ assert child.exists()
+
+ else:
+ childPath = self.fp.child(name[0:2]).child(name[2:4]).child(name)
+ child = CalendarHomeRedirectFile(childPath.path, self, record)
- #
- # Try to work around the above a little by telling the client that something
- # when wrong temporarily if the child isn't provisioned right away.
- #
- if not child.exists():
- raise HTTPError(StatusResponse(
- responsecode.SERVICE_UNAVAILABLE,
- "Provisioning calendar home."
- ))
-
- assert child.exists()
-
return child
def createSimilarFile(self, path):
raise HTTPError(responsecode.NOT_FOUND)
+class CalendarHomeRedirectFile(RedirectResource):
+
+ def __init__(self, path, parent, record):
+ self.path = path
+ self.parent = parent
+ self.record = record
+
+ parsedURL = urlparse.urlparse(self.record.hostedURL())
+ super(CalendarHomeRedirectFile, self).__init__(scheme=parsedURL.scheme, host=parsedURL.hostname, port=parsedURL.port)
+
+ def url(self):
+ return joinURL(self.parent.url(), self.record.uid)
+
class CalendarHomeFile (PropfindCacheMixin, AutoProvisioningFileMixIn, DirectoryCalendarHomeResource, CalDAVFile):
"""
Calendar home collection resource.
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/stdconfig.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/stdconfig.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -27,6 +27,7 @@
ConfigProvider, ConfigurationError, config, _mergeData, )
from twistedcaldav.log import (
Logger, clearLogLevels, setLogLevelForNamespace, InvalidLogLevelError, )
+from twistedcaldav.partitions import partitions
from twistedcaldav.util import (
KeychainAccessError, KeychainPasswordNotFound, getPasswordFromKeychain, )
@@ -309,6 +310,13 @@
},
#
+ # Partitioning
+ #
+ "EnablePartitions": False, # Partitioning enabled or not
+ "ServerPartitionID": "", # Unique ID for this server's partition instance.
+ "PartitionConfigFile": "/etc/caldavd/partitions.plist", # File path for partition information
+
+ #
# Performance tuning
#
@@ -533,9 +541,8 @@
try:
if "DefaultLogLevel" in configDict:
level = configDict["DefaultLogLevel"]
- if not level:
- level = "warn"
- setLogLevelForNamespace(None, level)
+ if level:
+ setLogLevelForNamespace(None, level)
if "LogLevels" in configDict:
for namespace in configDict["LogLevels"]:
@@ -628,7 +635,18 @@
# The password doesn't exist in the keychain.
log.info("iMIP %s password not found in keychain" %
(direction,))
-
+
+def _updatePartitions(configDict):
+ #
+ # Partitions
+ #
+
+ if configDict.EnablePartitions:
+ partitions.setSelfPartition(configDict.ServerPartitionID)
+ partitions.readConfig(configDict.PartitionConfigFile)
+ else:
+ partitions.clear()
+
PRE_UPDATE_HOOKS = (
_preUpdateDirectoryService,
)
@@ -641,6 +659,7 @@
_updateLogLevels,
_updateNotifications,
_updateScheduling,
+ _updatePartitions,
)
def _cleanup(configDict, defaultDict):
Modified: CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_config.py 2009-07-25 00:22:04 UTC (rev 4478)
+++ CalendarServer/branches/users/cdaboo/partition-4464/twistedcaldav/test/test_config.py 2009-08-03 21:09:08 UTC (rev 4479)
@@ -228,6 +228,9 @@
"""
Logging module configures properly.
"""
+ config.setDefaults(DEFAULT_CONFIG)
+ config.reload()
+
self.assertEquals(logLevelForNamespace(None), "warn")
self.assertEquals(logLevelForNamespace("some.namespace"), "warn")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090803/6b33edcd/attachment-0001.html>
More information about the calendarserver-changes
mailing list