[CalendarServer-changes] [12992] CalendarServer/branches/users/sagen/move2who-4
source_changes at macosforge.org
source_changes at macosforge.org
Mon Mar 24 12:36:49 PDT 2014
Revision: 12992
http://trac.calendarserver.org//changeset/12992
Author: sagen at apple.com
Date: 2014-03-24 12:36:48 -0700 (Mon, 24 Mar 2014)
Log Message:
-----------
Get gateway working
Modified Paths:
--------------
CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/gateway.py
CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/gateway/caldavd.plist
CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_gateway.py
CalendarServer/branches/users/sagen/move2who-4/requirements/py_develop.txt
Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/gateway.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/gateway.py 2014-03-22 02:56:09 UTC (rev 12991)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/gateway.py 2014-03-24 19:36:48 UTC (rev 12992)
@@ -30,17 +30,19 @@
)
from calendarserver.tools.purge import WorkerService, PurgeOldEventsService, DEFAULT_BATCH_SIZE, DEFAULT_RETAIN_DAYS
from calendarserver.tools.util import (
- principalForPrincipalID, proxySubprincipal, addProxy, removeProxy,
- ProxyError, ProxyWarning, autoDisableMemcached
+ recordForPrincipalID, autoDisableMemcached
)
from pycalendar.datetime import DateTime
from twext.who.directory import DirectoryRecord
-from twisted.internet.defer import inlineCallbacks, succeed
+from twisted.internet.defer import inlineCallbacks, succeed, returnValue
from twistedcaldav.config import config, ConfigDict
-from txdav.xml import element as davxml
from txdav.who.idirectory import RecordType as CalRecordType
from twext.who.idirectory import FieldName
+from twisted.python.constants import Names, NamedConstant
+from txdav.who.delegates import (
+ addDelegate, removeDelegate, RecordType as DelegateRecordType
+)
attrMap = {
@@ -227,23 +229,50 @@
def command_getLocationList(self, command):
return self.respondWithRecordsOfTypes(self.dir, command, ["locations"])
-
@inlineCallbacks
- def command_createLocation(self, command):
+ def _saveRecord(self, typeName, recordType, command, oldFields=None):
+ """
+ Save a record using the values in the command plist, starting with
+ any fields in the optional oldFields.
- fields = {
- FieldName.recordType: CalRecordType.location
- }
+ @param typeName: one of "locations", "resources", "addresses"; used
+ to return the appropriate list of records afterwards.
+ @param recordType: the type of record to save
+ @param command: the command containing values
+ @type command: C{dict}
+ @param oldFields: the optional fields to start with, which will be
+ overridden by values from command
+ @type oldFiles: C{dict}
+ """
+
+ if oldFields is None:
+ fields = {
+ FieldName.recordType: recordType
+ }
+ create = True
+ else:
+ fields = oldFields.copy()
+ create = False
+
for key, info in attrMap.iteritems():
if key in command:
attrName = info['attr']
field = self.dir.fieldName.lookupByName(attrName)
valueType = self.dir.fieldName.valueType(field)
value = command[key]
- if self.dir.fieldName.isMultiValue(field) and not isinstance(value, list):
+
+ # For backwards compatibility, convert to a list if needed
+ if (
+ self.dir.fieldName.isMultiValue(field) and
+ not isinstance(value, list)
+ ):
value = [value]
+
if valueType == int:
value = int(value)
+ elif issubclass(valueType, Names):
+ if value is not None:
+ value = valueType.lookupByName(value)
else:
if isinstance(value, list):
newList = []
@@ -259,9 +288,8 @@
fields[field] = value
record = DirectoryRecord(self.dir, fields)
- yield self.dir.updateRecords([record], create=True)
+ yield self.dir.updateRecords([record], create=create)
-
readProxies = command.get("ReadProxies", None)
if readProxies:
proxyRecords = []
@@ -282,15 +310,62 @@
yield setProxies(record, readProxies, writeProxies)
- yield self.respondWithRecordsOfTypes(self.dir, command, ["locations"])
+ yield self.respondWithRecordsOfTypes(self.dir, command, [typeName])
+ def command_createLocation(self, command):
+ return self._saveRecord("locations", CalRecordType.location, command)
+
+
+ def command_createResource(self, command):
+ return self._saveRecord("resources", CalRecordType.resource, command)
+
+
+ def command_createAddress(self, command):
+ return self._saveRecord("addresses", CalRecordType.address, command)
+
+
@inlineCallbacks
+ def command_setLocationAttributes(self, command):
+ uid = command['GeneratedUID']
+ record = yield self.dir.recordWithUID(uid)
+ yield self._saveRecord(
+ "locations",
+ CalRecordType.location,
+ command,
+ oldFields=record.fields
+ )
+
+ @inlineCallbacks
+ def command_setResourceAttributes(self, command):
+ uid = command['GeneratedUID']
+ record = yield self.dir.recordWithUID(uid)
+ yield self._saveRecord(
+ "resources",
+ CalRecordType.resource,
+ command,
+ oldFields=record.fields
+ )
+
+
+ @inlineCallbacks
+ def command_setAddressAttributes(self, command):
+ uid = command['GeneratedUID']
+ record = yield self.dir.recordWithUID(uid)
+ yield self._saveRecord(
+ "addresses",
+ CalRecordType.address,
+ command,
+ oldFields=record.fields
+ )
+
+
+ @inlineCallbacks
def command_getLocationAttributes(self, command):
uid = command['GeneratedUID']
record = yield self.dir.recordWithUID(uid)
if record is None:
- self.respondWithError("Location not found: %s" % (uid,))
+ self.respondWithError("Principal not found: %s" % (uid,))
return
recordDict = recordToDict(record)
# recordDict['AutoSchedule'] = principal.getAutoSchedule()
@@ -305,117 +380,95 @@
self.respond(command, recordDict)
command_getResourceAttributes = command_getLocationAttributes
+ command_getAddressAttributes = command_getLocationAttributes
- @inlineCallbacks
- def command_setLocationAttributes(self, command):
- # Set autoSchedule prior to the updateRecord so that the right
- # value ends up in memcached
- principal = principalForPrincipalID(command['GeneratedUID'],
- directory=self.dir)
- (yield principal.setAutoSchedule(command.get('AutoSchedule', False)))
- (yield principal.setAutoAcceptGroup(command.get('AutoAcceptGroup', "")))
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
- try:
- record = (yield updateRecord(False, self.dir, "locations", **kwargs))
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
- readProxies = command.get("ReadProxies", None)
- writeProxies = command.get("WriteProxies", None)
- principal = principalForPrincipalID(record.guid, directory=self.dir)
- (yield setProxies(self.store, principal, readProxies, writeProxies, directory=self.dir))
+ # @inlineCallbacks
+ # def _setAttributes(self, )
+ # # Set autoSchedule prior to the updateRecord so that the right
+ # # value ends up in memcached
+ # principal = principalForPrincipalID(command['GeneratedUID'],
+ # directory=self.dir)
+ # (yield principal.setAutoSchedule(command.get('AutoSchedule', False)))
+ # (yield principal.setAutoAcceptGroup(command.get('AutoAcceptGroup', "")))
- yield self.command_getLocationAttributes(command)
+ # kwargs = {}
+ # for key, info in attrMap.iteritems():
+ # if key in command:
+ # kwargs[info['attr']] = command[key]
+ # try:
+ # record = (yield updateRecord(False, self.dir, "locations", **kwargs))
+ # except DirectoryError, e:
+ # self.respondWithError(str(e))
+ # return
+ # readProxies = command.get("ReadProxies", None)
+ # writeProxies = command.get("WriteProxies", None)
+ # principal = principalForPrincipalID(record.guid, directory=self.dir)
+ # (yield setProxies(self.store, principal, readProxies, writeProxies, directory=self.dir))
- def command_deleteLocation(self, command):
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
- try:
- self.dir.destroyRecord("locations", **kwargs)
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
- self.respondWithRecordsOfTypes(self.dir, command, ["locations"])
+ # yield self.command_getLocationAttributes(command)
+
# Resources
def command_getResourceList(self, command):
self.respondWithRecordsOfTypes(self.dir, command, ["resources"])
- @inlineCallbacks
- def command_createResource(self, command):
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
+ # @inlineCallbacks
+ # def command_createResource(self, command):
+ # kwargs = {}
+ # for key, info in attrMap.iteritems():
+ # if key in command:
+ # kwargs[info['attr']] = command[key]
- try:
- record = (yield updateRecord(True, self.dir, "resources", **kwargs))
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
+ # try:
+ # record = (yield updateRecord(True, self.dir, "resources", **kwargs))
+ # except DirectoryError, e:
+ # self.respondWithError(str(e))
+ # return
- readProxies = command.get("ReadProxies", None)
- writeProxies = command.get("WriteProxies", None)
- principal = principalForPrincipalID(record.guid, directory=self.dir)
- (yield setProxies(self.store, principal, readProxies, writeProxies, directory=self.dir))
+ # readProxies = command.get("ReadProxies", None)
+ # writeProxies = command.get("WriteProxies", None)
+ # principal = principalForPrincipalID(record.guid, directory=self.dir)
+ # (yield setProxies(self.store, principal, readProxies, writeProxies, directory=self.dir))
- self.respondWithRecordsOfTypes(self.dir, command, ["resources"])
+ # self.respondWithRecordsOfTypes(self.dir, command, ["resources"])
- @inlineCallbacks
- def command_setResourceAttributes(self, command):
+ # @inlineCallbacks
+ # def command_setResourceAttributes(self, command):
- # Set autoSchedule prior to the updateRecord so that the right
- # value ends up in memcached
- principal = principalForPrincipalID(command['GeneratedUID'],
- directory=self.dir)
- (yield principal.setAutoSchedule(command.get('AutoSchedule', False)))
- (yield principal.setAutoAcceptGroup(command.get('AutoAcceptGroup', "")))
+ # # Set autoSchedule prior to the updateRecord so that the right
+ # # value ends up in memcached
+ # principal = principalForPrincipalID(command['GeneratedUID'],
+ # directory=self.dir)
+ # (yield principal.setAutoSchedule(command.get('AutoSchedule', False)))
+ # (yield principal.setAutoAcceptGroup(command.get('AutoAcceptGroup', "")))
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
- try:
- record = (yield updateRecord(False, self.dir, "resources", **kwargs))
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
+ # kwargs = {}
+ # for key, info in attrMap.iteritems():
+ # if key in command:
+ # kwargs[info['attr']] = command[key]
+ # try:
+ # record = (yield updateRecord(False, self.dir, "resources", **kwargs))
+ # except DirectoryError, e:
+ # self.respondWithError(str(e))
+ # return
- readProxies = command.get("ReadProxies", None)
- writeProxies = command.get("WriteProxies", None)
- principal = principalForPrincipalID(record.guid, directory=self.dir)
- (yield setProxies(self.store, principal, readProxies, writeProxies, directory=self.dir))
+ # readProxies = command.get("ReadProxies", None)
+ # writeProxies = command.get("WriteProxies", None)
+ # principal = principalForPrincipalID(record.guid, directory=self.dir)
+ # (yield setProxies(self.store, principal, readProxies, writeProxies, directory=self.dir))
- yield self.command_getResourceAttributes(command)
+ # yield self.command_getResourceAttributes(command)
- def command_deleteResource(self, command):
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
- try:
- self.dir.destroyRecord("resources", **kwargs)
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
- self.respondWithRecordsOfTypes(self.dir, command, ["resources"])
-
-
# deferred
def command_getLocationAndResourceList(self, command):
return self.respondWithRecordsOfTypes(self.dir, command, ["locations", "resources"])
@@ -424,62 +477,60 @@
# Addresses
def command_getAddressList(self, command):
- self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
+ return self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
- @inlineCallbacks
- def command_createAddress(self, command):
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
+ # @inlineCallbacks
+ # def command_createAddress(self, command):
+ # kwargs = {}
+ # for key, info in attrMap.iteritems():
+ # if key in command:
+ # kwargs[info['attr']] = command[key]
- try:
- yield updateRecord(True, self.dir, "addresses", **kwargs)
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
+ # try:
+ # yield updateRecord(True, self.dir, "addresses", **kwargs)
+ # except DirectoryError, e:
+ # self.respondWithError(str(e))
+ # return
- self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
+ # self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
- def command_getAddressAttributes(self, command):
- guid = command['GeneratedUID']
- record = self.dir.recordWithGUID(guid)
- if record is None:
- self.respondWithError("Principal not found: %s" % (guid,))
- return
- recordDict = recordToDict(record)
- self.respond(command, recordDict)
- return succeed(None)
+ # @inlineCallbacks
+ # def command_setAddressAttributes(self, command):
+ # kwargs = {}
+ # for key, info in attrMap.iteritems():
+ # if key in command:
+ # kwargs[info['attr']] = command[key]
+ # try:
+ # yield updateRecord(False, self.dir, "addresses", **kwargs)
+ # except DirectoryError, e:
+ # self.respondWithError(str(e))
+ # return
+
+ # yield self.command_getAddressAttributes(command)
+
+
+
@inlineCallbacks
- def command_setAddressAttributes(self, command):
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
- try:
- yield updateRecord(False, self.dir, "addresses", **kwargs)
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
+ def _delete(self, typeName, command):
+ uid = command['GeneratedUID']
+ yield self.dir.removeRecords([uid])
+ self.respondWithRecordsOfTypes(self.dir, command, [typeName])
- yield self.command_getAddressAttributes(command)
+ def command_deleteLocation(self, command):
+ return self._delete("locations", command)
+
+ def command_deleteResource(self, command):
+ return self._delete("resources", command)
+
+
def command_deleteAddress(self, command):
- kwargs = {}
- for key, info in attrMap.iteritems():
- if key in command:
- kwargs[info['attr']] = command[key]
- try:
- self.dir.destroyRecord("addresses", **kwargs)
- except DirectoryError, e:
- self.respondWithError(str(e))
- return
- self.respondWithRecordsOfTypes(self.dir, command, ["addresses"])
+ return self._delete("addresses", command)
# Config
@@ -530,106 +581,144 @@
# Proxies
- @inlineCallbacks
def command_listWriteProxies(self, command):
- principal = principalForPrincipalID(command['Principal'], directory=self.dir)
- if principal is None:
- self.respondWithError("Principal not found: %s" % (command['Principal'],))
- return
- (yield self.respondWithProxies(self.dir, command, principal, "write"))
+ return self._listProxies(command, "write")
+ def command_listReadProxies(self, command):
+ return self._listProxies(command, "read")
+
@inlineCallbacks
- def command_addWriteProxy(self, command):
- principal = principalForPrincipalID(command['Principal'],
- directory=self.dir)
- if principal is None:
+ def _listProxies(self, command, proxyType):
+ record = yield recordForPrincipalID(self.dir, command['Principal'])
+ if record is None:
self.respondWithError("Principal not found: %s" % (command['Principal'],))
- return
+ returnValue(None)
+ yield self.respondWithProxies(command, record, proxyType)
- proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
- if proxy is None:
- self.respondWithError("Proxy not found: %s" % (command['Proxy'],))
- return
- try:
- (yield addProxy(self.root, self.dir, self.store, principal, "write", proxy))
- except ProxyError, e:
- self.respondWithError(str(e))
- return
- except ProxyWarning, e:
- pass
- (yield self.respondWithProxies(self.dir, command, principal, "write"))
+ def command_addReadProxy(self, command):
+ return self._addProxy(command, "read")
+
+ def command_addWriteProxy(self, command):
+ return self._addProxy(command, "write")
+
+
@inlineCallbacks
- def command_removeWriteProxy(self, command):
- principal = principalForPrincipalID(command['Principal'], directory=self.dir)
- if principal is None:
+ def _addProxy(self, command, proxyType):
+ record = yield recordForPrincipalID(self.dir, command['Principal'])
+ if record is None:
self.respondWithError("Principal not found: %s" % (command['Principal'],))
- return
- proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
- if proxy is None:
+ returnValue(None)
+
+ proxyRecord = yield recordForPrincipalID(self.dir, command['Proxy'])
+ if proxyRecord is None:
self.respondWithError("Proxy not found: %s" % (command['Proxy'],))
- return
- try:
- (yield removeProxy(self.root, self.dir, self.store, principal, proxy, proxyTypes=("write",)))
- except ProxyError, e:
- self.respondWithError(str(e))
- return
- except ProxyWarning, e:
- pass
- (yield self.respondWithProxies(self.dir, command, principal, "write"))
+ returnValue(None)
+ txn = self.store.newTransaction()
+ yield addDelegate(txn, record, proxyRecord, (proxyType == "write"))
+ yield txn.commit()
+ yield self.respondWithProxies(command, record, proxyType)
- @inlineCallbacks
- def command_listReadProxies(self, command):
- principal = principalForPrincipalID(command['Principal'], directory=self.dir)
- if principal is None:
- self.respondWithError("Principal not found: %s" % (command['Principal'],))
- return
- (yield self.respondWithProxies(self.dir, command, principal, "read"))
+ def command_removeReadProxy(self, command):
+ return self._removeProxy(command, "read")
- @inlineCallbacks
- def command_addReadProxy(self, command):
- principal = principalForPrincipalID(command['Principal'], directory=self.dir)
- if principal is None:
- self.respondWithError("Principal not found: %s" % (command['Principal'],))
- return
- proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
- if proxy is None:
- self.respondWithError("Proxy not found: %s" % (command['Proxy'],))
- return
- try:
- (yield addProxy(self.root, self.dir, self.store, principal, "read", proxy))
- except ProxyError, e:
- self.respondWithError(str(e))
- return
- except ProxyWarning, e:
- pass
- (yield self.respondWithProxies(self.dir, command, principal, "read"))
+ def command_removeWriteProxy(self, command):
+ return self._removeProxy(command, "write")
+
@inlineCallbacks
- def command_removeReadProxy(self, command):
- principal = principalForPrincipalID(command['Principal'], directory=self.dir)
- if principal is None:
+ def _removeProxy(self, command, proxyType):
+ record = yield recordForPrincipalID(self.dir, command['Principal'])
+ if record is None:
self.respondWithError("Principal not found: %s" % (command['Principal'],))
- return
- proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
- if proxy is None:
+ returnValue(None)
+
+ proxyRecord = yield recordForPrincipalID(self.dir, command['Proxy'])
+ if proxyRecord is None:
self.respondWithError("Proxy not found: %s" % (command['Proxy'],))
- return
- try:
- (yield removeProxy(self.root, self.dir, self.store, principal, proxy, proxyTypes=("read",)))
- except ProxyError, e:
- self.respondWithError(str(e))
- return
- except ProxyWarning, e:
- pass
- (yield self.respondWithProxies(self.dir, command, principal, "read"))
+ returnValue(None)
+ txn = self.store.newTransaction()
+ yield removeDelegate(txn, record, proxyRecord, (proxyType == "write"))
+ yield txn.commit()
+ yield self.respondWithProxies(command, record, proxyType)
+
+
+ # @inlineCallbacks
+ # def command_removeWriteProxy(self, command):
+ # principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ # if principal is None:
+ # self.respondWithError("Principal not found: %s" % (command['Principal'],))
+ # return
+ # proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
+ # if proxy is None:
+ # self.respondWithError("Proxy not found: %s" % (command['Proxy'],))
+ # return
+ # try:
+ # (yield removeProxy(self.root, self.dir, self.store, principal, proxy, proxyTypes=("write",)))
+ # except ProxyError, e:
+ # self.respondWithError(str(e))
+ # return
+ # except ProxyWarning, e:
+ # pass
+ # (yield self.respondWithProxies(self.dir, command, principal, "write"))
+
+
+ # @inlineCallbacks
+ # def command_listReadProxies(self, command):
+ # principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ # if principal is None:
+ # self.respondWithError("Principal not found: %s" % (command['Principal'],))
+ # return
+ # (yield self.respondWithProxies(self.dir, command, principal, "read"))
+
+
+ # @inlineCallbacks
+ # def command_addReadProxy(self, command):
+ # principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ # if principal is None:
+ # self.respondWithError("Principal not found: %s" % (command['Principal'],))
+ # return
+ # proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
+ # if proxy is None:
+ # self.respondWithError("Proxy not found: %s" % (command['Proxy'],))
+ # return
+ # try:
+ # (yield addProxy(self.root, self.dir, self.store, principal, "read", proxy))
+ # except ProxyError, e:
+ # self.respondWithError(str(e))
+ # return
+ # except ProxyWarning, e:
+ # pass
+ # (yield self.respondWithProxies(self.dir, command, principal, "read"))
+
+
+ # @inlineCallbacks
+ # def command_removeReadProxy(self, command):
+ # principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ # if principal is None:
+ # self.respondWithError("Principal not found: %s" % (command['Principal'],))
+ # return
+ # proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
+ # if proxy is None:
+ # self.respondWithError("Proxy not found: %s" % (command['Proxy'],))
+ # return
+ # try:
+ # (yield removeProxy(self.root, self.dir, self.store, principal, proxy, proxyTypes=("read",)))
+ # except ProxyError, e:
+ # self.respondWithError(str(e))
+ # return
+ # except ProxyWarning, e:
+ # pass
+ # (yield self.respondWithProxies(self.dir, command, principal, "read"))
+
+
@inlineCallbacks
def command_purgeOldEvents(self, command):
"""
@@ -644,22 +733,22 @@
cutoff.setDateOnly(False)
cutoff.offsetDay(-retainDays)
eventCount = (yield PurgeOldEventsService.purgeOldEvents(self.store, cutoff, DEFAULT_BATCH_SIZE))
- self.respond(command, {'EventsRemoved' : eventCount, "RetainDays" : retainDays})
+ self.respond(command, {'EventsRemoved': eventCount, "RetainDays": retainDays})
@inlineCallbacks
- def respondWithProxies(self, directory, command, principal, proxyType):
+ def respondWithProxies(self, command, record, proxyType):
proxies = []
- subPrincipal = proxySubprincipal(principal, proxyType)
- if subPrincipal is not None:
- membersProperty = (yield subPrincipal.readProperty(davxml.GroupMemberSet, None))
- if membersProperty.children:
- for member in membersProperty.children:
- proxyPrincipal = principalForPrincipalID(str(member), directory=directory)
- proxies.append(proxyPrincipal.record.guid)
+ recordType = {
+ "read": DelegateRecordType.readDelegateGroup,
+ "write": DelegateRecordType.writeDelegateGroup,
+ }[proxyType]
+ proxyGroup = yield self.dir.recordWithShortName(recordType, record.uid)
+ for member in (yield proxyGroup.members()):
+ proxies.append(member.uid)
self.respond(command, {
- 'Principal' : principal.record.guid, 'Proxies' : proxies
+ 'Principal': record.uid, 'Proxies': proxies
})
@@ -675,11 +764,11 @@
def respond(self, command, result):
- self.output.write(writePlistToString({'command' : command['command'], 'result' : result}))
+ self.output.write(writePlistToString({'command': command['command'], 'result': result}))
def respondWithError(self, msg, status=1):
- self.output.write(writePlistToString({'error' : msg, }))
+ self.output.write(writePlistToString({'error': msg, }))
@@ -690,8 +779,14 @@
value = record.fields[record.service.fieldName.lookupByName(info['attr'])]
if value is None:
continue
- elif isinstance(value, str):
+ # For backwards compatibility, present fullName/RealName as single
+ # value even though twext.who now has it as multiValue
+ if key == "RealName":
+ value = value[0]
+ if isinstance(value, str):
value = value.decode("utf-8")
+ elif isinstance(value, NamedConstant):
+ value = value.name
recordDict[key] = value
except KeyError:
pass
@@ -700,7 +795,7 @@
def respondWithError(msg, status=1):
- sys.stdout.write(writePlistToString({'error' : msg, }))
+ sys.stdout.write(writePlistToString({'error': msg, }))
Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/gateway/caldavd.plist
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/gateway/caldavd.plist 2014-03-22 02:56:09 UTC (rev 12991)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/gateway/caldavd.plist 2014-03-24 19:36:48 UTC (rev 12992)
@@ -34,6 +34,14 @@
<key>ServerHostName</key>
<string></string> <!-- The hostname clients use when connecting -->
+ <!-- Enable Calendars -->
+ <key>EnableCalDAV</key>
+ <true/>
+
+ <!-- Enable AddressBooks -->
+ <key>EnableCardDAV</key>
+ <true/>
+
<!-- HTTP port [0 = disable HTTP] -->
<key>HTTPPort</key>
<integer>8008</integer>
@@ -482,6 +490,31 @@
<key>Services</key>
<dict>
+
+ <key>APNS</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ <key>EnableStaggering</key>
+ <true/>
+ <key>StaggerSeconds</key>
+ <integer>5</integer>
+ <key>CalDAV</key>
+ <dict>
+ <key>CertificatePath</key>
+ <string>/example/calendar.cer</string>
+ <key>PrivateKeyPath</key>
+ <string>/example/calendar.pem</string>
+ </dict>
+ <key>CardDAV</key>
+ <dict>
+ <key>CertificatePath</key>
+ <string>/example/contacts.cer</string>
+ <key>PrivateKeyPath</key>
+ <string>/example/contacts.pem</string>
+ </dict>
+ </dict>
+
<key>SimpleLineNotifier</key>
<dict>
<!-- Simple line notification service (for testing) -->
@@ -756,5 +789,12 @@
</dict>
+ <key>Includes</key>
+ <array>
+ <string>%(WritablePlist)s</string>
+ </array>
+ <key>WritableConfigFile</key>
+ <string>%(WritablePlist)s</string>
+
</dict>
</plist>
Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_gateway.py 2014-03-22 02:56:09 UTC (rev 12991)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/test/test_gateway.py 2014-03-24 19:36:48 UTC (rev 12992)
@@ -29,6 +29,7 @@
import plistlib
from twistedcaldav.memcacheclient import ClientFactory
from twistedcaldav import memcacher
+from txdav.who.idirectory import AutoScheduleMode
class RunCommandTestCase(StoreTestCase):
@@ -183,6 +184,12 @@
class GatewayTestCase(RunCommandTestCase):
+ def _flush(self):
+ # Flush both XML directories
+ self.directory._directory.services[0].flush()
+ self.directory._directory.services[1].flush()
+
+
@inlineCallbacks
def test_getLocationAndResourceList(self):
results = yield self.runCommand(command_getLocationAndResourceList)
@@ -198,14 +205,18 @@
@inlineCallbacks
def test_getLocationAttributes(self):
yield self.runCommand(command_createLocation)
+
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
+
results = yield self.runCommand(command_getLocationAttributes)
- self.assertEquals(results["result"]["Capacity"], "40")
- self.assertEquals(results["result"]["Description"], "Test Description")
+ # self.assertEquals(results["result"]["Capacity"], "40")
+ # self.assertEquals(results["result"]["Description"], "Test Description")
self.assertEquals(results["result"]["RecordName"], ["createdlocation01"])
self.assertEquals(results["result"]["RealName"],
"Created Location 01 %s %s" % (unichr(208), u"\ud83d\udca3"))
- self.assertEquals(results["result"]["Comment"], "Test Comment")
- self.assertEquals(results["result"]["AutoSchedule"], True)
+ # self.assertEquals(results["result"]["Comment"], "Test Comment")
+ self.assertEquals(results["result"]["AutoScheduleMode"], u"acceptIfFree")
self.assertEquals(results["result"]["AutoAcceptGroup"], "E5A6142C-4189-4E9E-90B0-9CD0268B314B")
self.assertEquals(set(results["result"]["ReadProxies"]), set(['user03', 'user04']))
self.assertEquals(set(results["result"]["WriteProxies"]), set(['user05', 'user06']))
@@ -220,9 +231,13 @@
@inlineCallbacks
def test_getResourceAttributes(self):
yield self.runCommand(command_createResource)
+
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
+
results = yield self.runCommand(command_getResourceAttributes)
- self.assertEquals(results["result"]["Comment"], "Test Comment")
- self.assertEquals(results["result"]["Type"], "Computer")
+ # self.assertEquals(results["result"]["Comment"], "Test Comment")
+ # self.assertEquals(results["result"]["Type"], "Computer")
self.assertEquals(set(results["result"]["ReadProxies"]), set(['user03', 'user04']))
self.assertEquals(set(results["result"]["WriteProxies"]), set(['user05', 'user06']))
@@ -234,17 +249,19 @@
self.assertEquals(record, None)
yield self.runCommand(command_createAddress)
- # directory.flushCaches()
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
record = yield self.directory.recordWithUID("C701069D-9CA1-4925-A1A9-5CD94767B74B")
- self.assertEquals(record.fullName.decode("utf-8"),
- "Created Address 01 %s %s" % (unichr(208), u"\ud83d\udca3"))
+ self.assertEquals(
+ record.displayName,
+ "Created Address 01 %s %s" % (unichr(208), u"\ud83d\udca3")
+ )
- self.assertNotEquals(record, None)
- self.assertEquals(record.extras["abbreviatedName"], "Addr1")
- self.assertEquals(record.extras["streetAddress"], "1 Infinite Loop\nCupertino, 95014\nCA")
- self.assertEquals(record.extras["geo"], "geo:37.331,-122.030")
+ self.assertEquals(record.abbreviatedName, "Addr1")
+ self.assertEquals(record.streetAddress, "1 Infinite Loop\nCupertino, 95014\nCA")
+ self.assertEquals(record.geographicLocation, "geo:37.331,-122.030")
results = yield self.runCommand(command_getAddressList)
self.assertEquals(len(results["result"]), 1)
@@ -257,7 +274,7 @@
results = yield self.runCommand(command_getAddressAttributes)
self.assertEquals(results["result"]["RealName"], u'Updated Address')
self.assertEquals(results["result"]["StreetAddress"], u'Updated Street Address')
- self.assertEquals(results["result"]["Geo"], u'Updated Geo')
+ self.assertEquals(results["result"]["GeographicLocation"], u'Updated Geo')
results = yield self.runCommand(command_deleteAddress)
@@ -272,13 +289,9 @@
self.assertEquals(record, None)
yield self.runCommand(command_createLocation)
- # directory.flushCaches()
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
- # This appears to be necessary in order for record.autoSchedule to
- # reflect the change prior to the directory record expiration
- # augmentService = directory.serviceForRecordType(directory.recordType_locations).augmentService
- # augmentService.refresh()
-
record = yield self.directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
self.assertEquals(record.fullNames[0],
u"Created Location 01 %s %s" % (unichr(208), u"\ud83d\udca3"))
@@ -296,28 +309,24 @@
@inlineCallbacks
def test_setLocationAttributes(self):
- directory = getDirectory()
yield self.runCommand(command_createLocation)
yield self.runCommand(command_setLocationAttributes)
- directory.flushCaches()
- # This appears to be necessary in order for record.autoSchedule to
- # reflect the change
- augmentService = directory.serviceForRecordType(directory.recordType_locations).augmentService
- augmentService.refresh()
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
- record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
+ record = yield self.directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
- self.assertEquals(record.extras["comment"], "Updated Test Comment")
- self.assertEquals(record.extras["floor"], "Second")
- self.assertEquals(record.extras["capacity"], "41")
- self.assertEquals(record.extras["streetAddress"], "2 Infinite Loop\nCupertino, 95014\nCA")
- self.assertEquals(record.autoSchedule, True)
+ # self.assertEquals(record.extras["comment"], "Updated Test Comment")
+ self.assertEquals(record.floor, "Second")
+ # self.assertEquals(record.extras["capacity"], "41")
+ self.assertEquals(record.streetAddress, "2 Infinite Loop\nCupertino, 95014\nCA")
+ self.assertEquals(record.autoScheduleMode, AutoScheduleMode.acceptIfFree)
self.assertEquals(record.autoAcceptGroup, "F5A6142C-4189-4E9E-90B0-9CD0268B314B")
results = yield self.runCommand(command_getLocationAttributes)
- self.assertEquals(results["result"]["AutoSchedule"], True)
+ self.assertEquals(results["result"]["AutoScheduleMode"], "acceptIfFree")
self.assertEquals(results["result"]["AutoAcceptGroup"], "F5A6142C-4189-4E9E-90B0-9CD0268B314B")
self.assertEquals(set(results["result"]["ReadProxies"]), set(['user03']))
self.assertEquals(set(results["result"]["WriteProxies"]), set(['user05', 'user06', 'user07']))
@@ -325,59 +334,62 @@
@inlineCallbacks
def test_destroyLocation(self):
- directory = getDirectory()
- record = directory.recordWithUID("location01")
+ record = yield self.directory.recordWithUID("location01")
self.assertNotEquals(record, None)
yield self.runCommand(command_deleteLocation)
- directory.flushCaches()
- record = directory.recordWithUID("location01")
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
+
+ record = yield self.directory.recordWithUID("location01")
self.assertEquals(record, None)
@inlineCallbacks
def test_createResource(self):
- directory = getDirectory()
- record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ record = yield self.directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
self.assertEquals(record, None)
yield self.runCommand(command_createResource)
- directory.flushCaches()
- record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
+
+ record = yield self.directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
self.assertNotEquals(record, None)
@inlineCallbacks
def test_setResourceAttributes(self):
- directory = getDirectory()
yield self.runCommand(command_createResource)
- directory.flushCaches()
- record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
- self.assertEquals(record.fullName, "Laptop 1")
+ record = yield self.directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record.displayName, "Laptop 1")
yield self.runCommand(command_setResourceAttributes)
- directory.flushCaches()
- record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
- self.assertEquals(record.fullName, "Updated Laptop 1")
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
+ record = yield self.directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record.displayName, "Updated Laptop 1")
+
@inlineCallbacks
def test_destroyResource(self):
- directory = getDirectory()
- record = directory.recordWithUID("resource01")
+ record = yield self.directory.recordWithUID("resource01")
self.assertNotEquals(record, None)
yield self.runCommand(command_deleteResource)
- directory.flushCaches()
- record = directory.recordWithUID("resource01")
+ # Tell the resources services to flush its cache and re-read XML
+ self._flush()
+
+ record = yield self.directory.recordWithUID("resource01")
self.assertEquals(record, None)
@@ -408,9 +420,10 @@
"""
Verify readConfig returns with only the writable keys
"""
- results = yield self.runCommand(command_readConfig,
- script="calendarserver_config")
-
+ results = yield self.runCommand(
+ command_readConfig,
+ script="calendarserver_config"
+ )
self.assertEquals(results["result"]["RedirectHTTPToHTTPS"], False)
self.assertEquals(results["result"]["EnableSearchAddressBook"], False)
self.assertEquals(results["result"]["EnableCalDAV"], True)
@@ -430,8 +443,10 @@
"""
Verify writeConfig updates the writable plist file only
"""
- results = yield self.runCommand(command_writeConfig,
- script="calendarserver_config")
+ results = yield self.runCommand(
+ command_writeConfig,
+ script="calendarserver_config"
+ )
self.assertEquals(results["result"]["EnableCalDAV"], False)
self.assertEquals(results["result"]["EnableCardDAV"], False)
@@ -453,9 +468,9 @@
<key>command</key>
<string>addReadProxy</string>
<key>Principal</key>
- <string>locations:location01</string>
+ <string>location01</string>
<key>Proxy</key>
- <string>users:user03</string>
+ <string>user03</string>
</dict>
</plist>
"""
@@ -467,9 +482,9 @@
<key>command</key>
<string>addWriteProxy</string>
<key>Principal</key>
- <string>locations:location01</string>
+ <string>location01</string>
<key>Proxy</key>
- <string>users:user01</string>
+ <string>user01</string>
</dict>
</plist>
"""
@@ -492,7 +507,7 @@
</array>
<key>StreetAddress</key>
<string>1 Infinite Loop\nCupertino, 95014\nCA</string>
- <key>Geo</key>
+ <key>GeographicLocation</key>
<string>geo:37.331,-122.030</string>
</dict>
</plist>
@@ -505,10 +520,8 @@
<dict>
<key>command</key>
<string>createLocation</string>
- <!--
<key>AutoScheduleMode</key>
- <string></string>
- -->
+ <string>acceptIfFree</string>
<key>AutoAcceptGroup</key>
<string>E5A6142C-4189-4E9E-90B0-9CD0268B314B</string>
<key>GeneratedUID</key>
@@ -552,31 +565,33 @@
<dict>
<key>command</key>
<string>createResource</string>
- <key>AutoSchedule</key>
- <true/>
+ <key>AutoScheduleMode</key>
+ <string>declineIfBusy</string>
<key>GeneratedUID</key>
<string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
<key>RealName</key>
<string>Laptop 1</string>
+ <!--
<key>Comment</key>
<string>Test Comment</string>
<key>Description</key>
<string>Test Description</string>
<key>Type</key>
<string>Computer</string>
+ -->
<key>RecordName</key>
<array>
<string>laptop1</string>
</array>
<key>ReadProxies</key>
<array>
- <string>users:user03</string>
- <string>users:user04</string>
+ <string>user03</string>
+ <string>user04</string>
</array>
<key>WriteProxies</key>
<array>
- <string>users:user05</string>
- <string>users:user06</string>
+ <string>user05</string>
+ <string>user06</string>
</array>
</dict>
</plist>
@@ -691,9 +706,9 @@
<key>command</key>
<string>removeReadProxy</string>
<key>Principal</key>
- <string>locations:location01</string>
+ <string>location01</string>
<key>Proxy</key>
- <string>users:user03</string>
+ <string>user03</string>
</dict>
</plist>
"""
@@ -705,9 +720,9 @@
<key>command</key>
<string>removeWriteProxy</string>
<key>Principal</key>
- <string>locations:location01</string>
+ <string>location01</string>
<key>Proxy</key>
- <string>users:user01</string>
+ <string>user01</string>
</dict>
</plist>
"""
@@ -736,19 +751,21 @@
<string>Updated Test Description</string>
<key>Floor</key>
<string>Second</string>
+ <!--
<key>Capacity</key>
<string>41</string>
+ -->
<key>StreetAddress</key>
<string>2 Infinite Loop\nCupertino, 95014\nCA</string>
<key>ReadProxies</key>
<array>
- <string>users:user03</string>
+ <string>user03</string>
</array>
<key>WriteProxies</key>
<array>
- <string>users:user05</string>
- <string>users:user06</string>
- <string>users:user07</string>
+ <string>user05</string>
+ <string>user06</string>
+ <string>user07</string>
</array>
</dict>
</plist>
@@ -790,7 +807,7 @@
<string>Updated Address</string>
<key>StreetAddress</key>
<string>Updated Street Address</string>
- <key>Geo</key>
+ <key>GeographicLocation</key>
<string>Updated Geo</string>
</dict>
@@ -804,8 +821,8 @@
<dict>
<key>command</key>
<string>setResourceAttributes</string>
- <key>AutoSchedule</key>
- <false/>
+ <key>AutoScheduleMode</key>
+ <string>acceptIfFree</string>
<key>GeneratedUID</key>
<string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
<key>RealName</key>
Modified: CalendarServer/branches/users/sagen/move2who-4/requirements/py_develop.txt
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/requirements/py_develop.txt 2014-03-22 02:56:09 UTC (rev 12991)
+++ CalendarServer/branches/users/sagen/move2who-4/requirements/py_develop.txt 2014-03-24 19:36:48 UTC (rev 12992)
@@ -5,6 +5,7 @@
pyflakes
docutils>=0.11
mockldap>=0.1.4
+q
-e svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVClientLibrary/trunk#egg=CalDAVClientLibrary
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140324/d9f76878/attachment-0001.html>
More information about the calendarserver-changes
mailing list