[CalendarServer-changes] [12982] CalendarServer/branches/users/sagen/move2who-4

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 19 20:28:55 PDT 2014


Revision: 12982
          http://trac.calendarserver.org//changeset/12982
Author:   sagen at apple.com
Date:     2014-03-19 20:28:55 -0700 (Wed, 19 Mar 2014)
Log Message:
-----------
csmp supports record updates, including autoschedule and autoacceptgroup

Modified Paths:
--------------
    CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py
    CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py

Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py	2014-03-20 01:36:19 UTC (rev 12981)
+++ CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py	2014-03-20 03:28:55 UTC (rev 12982)
@@ -17,30 +17,36 @@
 ##
 from __future__ import print_function
 
-import sys
-import os
-import operator
 from getopt import getopt, GetoptError
+import operator
+import os
+import sys
 from uuid import UUID
 
+from calendarserver.tools.cmdline import utilityMain, WorkerService
+from calendarserver.tools.util import (
+    recordForPrincipalID, prettyRecord
+)
+from twext.who.directory import DirectoryRecord
+from twext.who.idirectory import RecordType, InvalidDirectoryRecordError
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
-from txdav.xml import element as davxml
+from twistedcaldav.config import config
 from txdav.who.delegates import addDelegate, removeDelegate
+from txdav.who.idirectory import AutoScheduleMode
 
 
-from twistedcaldav.config import config
-from txdav.who.groups import schedulePolledGroupCachingUpdate
+allowedAutoScheduleModes = {
+    "default": None,
+    "none": AutoScheduleMode.none,
+    "accept-always": AutoScheduleMode.accept,
+    "decline-always": AutoScheduleMode.decline,
+    "accept-if-free": AutoScheduleMode.acceptIfFree,
+    "decline-if-busy": AutoScheduleMode.declineIfBusy,
+    "automatic": AutoScheduleMode.acceptIfFreeDeclineIfBusy,
+}
 
-from calendarserver.tools.util import (
-    booleanArgument, proxySubprincipal,
-    recordForPrincipalID, prettyPrincipal, prettyRecord, ProxyError
-)
-from twistedcaldav.directory.augment import allowedAutoScheduleModes
 
-from calendarserver.tools.cmdline import utilityMain, WorkerService
-
-
 def usage(e=None):
     if e:
         print(e)
@@ -74,8 +80,6 @@
     print("  --add-read-proxy=principal: add a read-only proxy")
     print("  --add-write-proxy=principal: add a read-write proxy")
     print("  --remove-proxy=principal: remove a proxy")
-    print("  --set-auto-schedule={true|false}: set auto-accept state")
-    print("  --get-auto-schedule: read auto-schedule state")
     print("  --set-auto-schedule-mode={default|none|accept-always|decline-always|accept-if-free|decline-if-busy|automatic}: set auto-schedule mode")
     print("  --get-auto-schedule-mode: read auto-schedule mode")
     print("  --set-auto-accept-group=principal: set auto-accept-group")
@@ -95,7 +99,6 @@
         sys.exit(0)
 
 
-
 class PrincipalService(WorkerService):
     """
     Executes principals-related functions in a context which has access to the store
@@ -155,8 +158,6 @@
                 "add-read-proxy=",
                 "add-write-proxy=",
                 "remove-proxy=",
-                "set-auto-schedule=",
-                "get-auto-schedule",
                 "set-auto-schedule-mode=",
                 "get-auto-schedule-mode",
                 "set-auto-accept-group=",
@@ -177,7 +178,7 @@
     # Get configuration
     #
     configFileName = None
-    # addType = None
+    addType = None
     listPrincipalTypes = False
     listPrincipals = None
     searchPrincipals = None
@@ -198,11 +199,11 @@
         elif opt in ("-f", "--config"):
             configFileName = arg
 
-        # elif opt in ("-a", "--add"):
-        #     addType = arg
+        elif opt in ("-a", "--add"):
+            addType = arg
 
-        # elif opt in ("-r", "--remove"):
-        #     principalActions.append((action_removePrincipal,))
+        elif opt in ("-r", "--remove"):
+            principalActions.append((action_removePrincipal,))
 
         elif opt in ("", "--list-principal-types"):
             listPrincipalTypes = True
@@ -237,41 +238,26 @@
         elif opt in ("", "--remove-proxy"):
             principalActions.append((action_removeProxy, arg))
 
-        # elif opt in ("", "--set-auto-schedule"):
-        #     try:
-        #         autoSchedule = booleanArgument(arg)
-        #     except ValueError, e:
-        #         abort(e)
+        elif opt in ("", "--set-auto-schedule-mode"):
+            try:
+                if arg not in allowedAutoScheduleModes:
+                    raise ValueError("Unknown auto-schedule mode: {mode}".format(
+                        mode=arg))
+                autoScheduleMode = allowedAutoScheduleModes[arg]
+            except ValueError, e:
+                abort(e)
 
-        #     principalActions.append((action_setAutoSchedule, autoSchedule))
+            principalActions.append((action_setAutoScheduleMode, autoScheduleMode))
 
-        # elif opt in ("", "--get-auto-schedule"):
-        #     principalActions.append((action_getAutoSchedule,))
+        elif opt in ("", "--get-auto-schedule-mode"):
+            principalActions.append((action_getAutoScheduleMode,))
 
-        # elif opt in ("", "--set-auto-schedule-mode"):
-        #     try:
-        #         if arg not in allowedAutoScheduleModes:
-        #             raise ValueError("Unknown auto-schedule mode: %s" % (arg,))
-        #         autoScheduleMode = arg
-        #     except ValueError, e:
-        #         abort(e)
+        elif opt in ("", "--set-auto-accept-group"):
+            principalActions.append((action_setAutoAcceptGroup, arg))
 
-        #     principalActions.append((action_setAutoScheduleMode, autoScheduleMode))
+        elif opt in ("", "--get-auto-accept-group"):
+            principalActions.append((action_getAutoAcceptGroup,))
 
-        # elif opt in ("", "--get-auto-schedule-mode"):
-        #     principalActions.append((action_getAutoScheduleMode,))
-
-        # elif opt in ("", "--set-auto-accept-group"):
-        #     try:
-        #         yield recordForPrincipalID(arg, checkOnly=True)
-        #     except ValueError, e:
-        #         abort(e)
-
-        #     principalActions.append((action_setAutoAcceptGroup, arg))
-
-        # elif opt in ("", "--get-auto-accept-group"):
-        #     principalActions.append((action_getAutoAcceptGroup,))
-
         # elif opt in ("", "--set-geo"):
         #     principalActions.append((action_setValue, "Geo", arg))
 
@@ -303,28 +289,38 @@
         function = runListPrincipalTypes
         params = ()
 
-    # elif addType:
+    elif addType:
 
-    #     try:
-    #         addType = matchStrings(addType, ["locations", "resources", "addresses"])
-    #     except ValueError, e:
-    #         print(e)
-    #         return
+        try:
+            addType = matchStrings(
+                addType,
+                [
+                    "locations", "resources", "addresses", "users", "groups"
+                ]
+            )
+        except ValueError, e:
+            print(e)
+            return
 
-    #     try:
-    #         fullName, shortName, guid = parseCreationArgs(args)
-    #     except ValueError, e:
-    #         print(e)
-    #         return
+        try:
+            fullName, shortName, uid = parseCreationArgs(args)
+        except ValueError, e:
+            print(e)
+            return
 
-    #     if shortName is not None:
-    #         shortNames = [shortName]
-    #     else:
-    #         shortNames = ()
+        if fullName is not None:
+            fullNames = [fullName]
+        else:
+            fullNames = ()
 
-    #     function = runAddPrincipal
-    #     params = (addType, guid, shortNames, fullName)
+        if shortName is not None:
+            shortNames = [shortName]
+        else:
+            shortNames = ()
 
+        function = runAddPrincipal
+        params = (addType, uid, shortNames, fullNames)
+
     elif listPrincipals:
         try:
             listPrincipals = matchStrings(
@@ -349,13 +345,6 @@
         if not args:
             usage("No principals specified.")
 
-        # We don't have a directory yet
-        # for arg in args:
-        #     try:
-        #         yield recordForPrincipalID(arg, checkOnly=True)
-        #     except ValueError, e:
-        #         abort(e)
-
         unicodeArgs = [a.decode("utf-8") for a in args]
         function = runPrincipalActions
         params = (unicodeArgs, principalActions)
@@ -384,7 +373,7 @@
             printRecordList(records)
         else:
             print("No records of type %s" % (listPrincipals,))
-    except UnknownRecordTypeError, e:
+    except InvalidDirectoryRecordError, e:
         usage(e)
     returnValue(None)
 
@@ -453,28 +442,33 @@
 
 
 
-# @inlineCallbacks
-# def runAddPrincipal(service, store, addType, guid, shortNames, fullName):
-#     directory = store.directoryService()
-#     try:
-#         # FIXME STOP USING GUID
-#         yield updateRecord(
-#             True, directory, addType, guid=guid,
-#             shortNames=shortNames, fullName=fullName
-#         )
-#         print("Added '%s'" % (fullName,))
-#     except DirectoryError, e:
-#         print(e)
+ at inlineCallbacks
+def runAddPrincipal(service, store, addType, uid, shortNames, fullNames):
+    directory = store.directoryService()
+    recordType = directory.oldNameToRecordType(addType)
+    fields = {
+        directory.fieldName.recordType: recordType,
+        directory.fieldName.uid: uid,
+        directory.fieldName.shortNames: shortNames,
+        directory.fieldName.fullNames: fullNames,
+    }
+    record = DirectoryRecord(directory, fields)
+    yield record.service.updateRecords([record], create=True)
 
 
 
-# def action_removePrincipal(store, record):
-#     directory = store.directoryService()
-#     fullName = record.displayName
-#     shortName = record.shortNames[0]
+ at inlineCallbacks
+def action_removePrincipal(store, record):
+    directory = store.directoryService()
+    fullName = record.displayName
+    shortNames = ",".join(record.shortNames)
 
-#     yield directory.destroyRecord(record.recordType, uid=record.uid)
-#     print("Removed '%s' %s %s" % (fullName, shortName, record.uid))
+    yield directory.removeRecords([record.uid])
+    print(
+        "Removed '{full}' {shorts} {uid}".format(
+            full=fullName, shorts=shortNames, uid=record.uid
+        )
+    )
 
 
 
@@ -622,149 +616,122 @@
 
 
 
-# @inlineCallbacks
-# def action_setAutoSchedule(rootResource, directory, store, principal, autoSchedule):
-#     if principal.record.recordType == "groups":
-#         print("Enabling auto-schedule for %s is not allowed." % (principal,))
+def action_getAutoScheduleMode(store, record):
+    print(
+        "Auto-schedule mode for {record} is {mode}".format(
+            record=prettyRecord(record),
+            mode=(
+                record.autoScheduleMode.description if record.autoScheduleMode
+                else "Default"
+            )
+        )
+    )
 
-#     elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-#         print("Enabling auto-schedule for %s is not allowed." % (principal,))
 
-#     else:
-#         print("Setting auto-schedule to %s for %s" % (
-#             {True: "true", False: "false"}[autoSchedule],
-#             prettyPrincipal(principal),
-#         ))
+ at inlineCallbacks
+def action_setAutoScheduleMode(store, record, autoScheduleMode):
+    if record.recordType == RecordType.group:
+        print(
+            "Setting auto-schedule-mode for {record} is not allowed.".format(
+                record=prettyRecord(record)
+            )
+        )
 
-#         (yield updateRecord(False, directory,
-#             principal.record.recordType,
-#             guid=principal.record.guid,
-#             shortNames=principal.record.shortNames,
-#             fullName=principal.record.fullName,
-#             autoSchedule=autoSchedule,
-#             **principal.record.extras
-#         ))
+    elif (
+        record.recordType == RecordType.user and
+        not config.Scheduling.Options.AutoSchedule.AllowUsers
+    ):
+        print(
+            "Setting auto-schedule-mode for {record} is not allowed.".format(
+                record=prettyRecord(record)
+            )
+        )
 
+    else:
+        print(
+            "Setting auto-schedule-mode to {mode} for {record}".format(
+                mode=autoScheduleMode.description,
+                record=prettyRecord(record),
+            )
+        )
 
+        # Get original fields
+        newFields = record.fields.copy()
 
-# def action_getAutoSchedule(rootResource, directory, store, principal):
-#     autoSchedule = principal.getAutoSchedule()
-#     print("Auto-schedule for %s is %s" % (
-#         prettyPrincipal(principal),
-#         {True: "true", False: "false"}[autoSchedule],
-#     ))
+        # Set new values
+        newFields[record.service.fieldName.autoScheduleMode] = autoScheduleMode
 
+        updatedRecord = DirectoryRecord(record.service, newFields)
+        yield record.service.updateRecords([updatedRecord], create=False)
 
 
-# @inlineCallbacks
-# def action_setAutoScheduleMode(rootResource, directory, store, principal, autoScheduleMode):
-#     if principal.record.recordType == "groups":
-#         print("Setting auto-schedule mode for %s is not allowed." % (principal,))
+ at inlineCallbacks
+def action_setAutoAcceptGroup(store, record, autoAcceptGroup):
+    if record.recordType == RecordType.group:
+        print(
+            "Setting auto-accept-group for {record} is not allowed.".format(
+                record=prettyRecord(record)
+            )
+        )
 
-#     elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-#         print("Setting auto-schedule mode for %s is not allowed." % (principal,))
+    elif (
+        record.recordType == RecordType.user and
+        not config.Scheduling.Options.AutoSchedule.AllowUsers
+    ):
+        print(
+            "Setting auto-accept-group for {record} is not allowed.".format(
+                record=prettyRecord(record)
+            )
+        )
 
-#     else:
-#         print("Setting auto-schedule mode to %s for %s" % (
-#             autoScheduleMode,
-#             prettyPrincipal(principal),
-#         ))
+    else:
+        groupRecord = yield recordForPrincipalID(record.service, autoAcceptGroup)
+        if groupRecord is None or groupRecord.recordType != RecordType.group:
+            print("Invalid principal ID: {id}".format(id=autoAcceptGroup))
+        else:
+            print("Setting auto-accept-group to {group} for {record}".format(
+                group=prettyRecord(groupRecord),
+                record=prettyRecord(record),
+            ))
 
-#         (yield updateRecord(False, directory,
-#             principal.record.recordType,
-#             guid=principal.record.guid,
-#             shortNames=principal.record.shortNames,
-#             fullName=principal.record.fullName,
-#             autoScheduleMode=autoScheduleMode,
-#             **principal.record.extras
-#         ))
+            # Get original fields
+            newFields = record.fields.copy()
 
+            # Set new values
+            newFields[record.service.fieldName.autoAcceptGroup] = groupRecord.uid
 
+            updatedRecord = DirectoryRecord(record.service, newFields)
+            yield record.service.updateRecords([updatedRecord], create=False)
 
-# def action_getAutoScheduleMode(rootResource, directory, store, principal):
-#     autoScheduleMode = principal.getAutoScheduleMode()
-#     if not autoScheduleMode:
-#         autoScheduleMode = "automatic"
-#     print("Auto-schedule mode for %s is %s" % (
-#         prettyPrincipal(principal),
-#         autoScheduleMode,
-#     ))
 
 
+ at inlineCallbacks
+def action_getAutoAcceptGroup(store, record):
+    if record.autoAcceptGroup:
+        groupRecord = yield record.service.recordWithUID(
+            record.autoAcceptGroup
+        )
+        if groupRecord is not None:
+            print(
+                "Auto-accept-group for {record} is {group}".format(
+                    record=prettyRecord(record),
+                    group=prettyRecord(groupRecord),
+                )
+            )
+        else:
+            print(
+                "Invalid auto-accept-group assigned: {uid}".format(
+                    uid=record.autoAcceptGroup
+                )
+            )
+    else:
+        print(
+            "No auto-accept-group assigned to {record}".format(
+                record=prettyRecord(record)
+            )
+        )
 
-# @inlineCallbacks
-# def action_setAutoAcceptGroup(rootResource, directory, store, principal, autoAcceptGroup):
-#     if principal.record.recordType == "groups":
-#         print("Setting auto-accept-group for %s is not allowed." % (principal,))
 
-#     elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-#         print("Setting auto-accept-group for %s is not allowed." % (principal,))
-
-#     else:
-#         groupPrincipal = yield principalForPrincipalID(autoAcceptGroup, directory=directory)
-#         if groupPrincipal is None or groupPrincipal.record.recordType != "groups":
-#             print("Invalid principal ID: %s" % (autoAcceptGroup,))
-#         else:
-#             print("Setting auto-accept-group to %s for %s" % (
-#                 prettyPrincipal(groupPrincipal),
-#                 prettyPrincipal(principal),
-#             ))
-
-#             (yield updateRecord(False, directory,
-#                 principal.record.recordType,
-#                 guid=principal.record.guid,
-#                 shortNames=principal.record.shortNames,
-#                 fullName=principal.record.fullName,
-#                 autoAcceptGroup=groupPrincipal.record.guid,
-#                 **principal.record.extras
-#             ))
-
-
-
-# def action_getAutoAcceptGroup(rootResource, directory, store, principal):
-#     autoAcceptGroup = principal.getAutoAcceptGroup()
-#     if autoAcceptGroup:
-#         record = yield directory.recordWithGUID(autoAcceptGroup)
-#         if record is not None:
-#             groupPrincipal = yield directory.principalCollection.principalForUID(record.uid)
-#             if groupPrincipal is not None:
-#                 print("Auto-accept-group for %s is %s" % (
-#                     prettyPrincipal(principal),
-#                     prettyPrincipal(groupPrincipal),
-#                 ))
-#                 return
-#         print("Invalid auto-accept-group assigned: %s" % (autoAcceptGroup,))
-#     else:
-#         print("No auto-accept-group assigned to %s" % (prettyPrincipal(principal),))
-
-
-
-# @inlineCallbacks
-# def action_setValue(rootResource, directory, store, principal, name, value):
-#     print("Setting %s to %s for %s" % (
-#         name, value, prettyPrincipal(principal),
-#     ))
-
-#     principal.record.extras[attrMap[name]["attr"]] = value
-#     (yield updateRecord(False, directory,
-#         principal.record.recordType,
-#         guid=principal.record.guid,
-#         shortNames=principal.record.shortNames,
-#         fullName=principal.record.fullName,
-#         **principal.record.extras
-#     ))
-
-
-
-# def action_getValue(rootResource, directory, store, principal, name):
-#     print("%s for %s is %s" % (
-#         name,
-#         prettyPrincipal(principal),
-#         principal.record.extras[attrMap[name]["attr"]]
-#     ))
-
-
-
 def abort(msg, status=1):
     sys.stdout.write("%s\n" % (msg,))
     try:
@@ -777,32 +744,19 @@
 
 def parseCreationArgs(args):
     """
-    Look at the command line arguments for --add, and figure out which
-    one is the shortName and which one is the guid by attempting to make a
-    UUID object out of them.
+    Look at the command line arguments for --add, and simply assume the first
+    is full name, the second is short name, and the third is uid.  We can make
+    this fancier later.
     """
 
-    fullName = args[0]
-    shortName = None
-    guid = None
-    for arg in args[1:]:
-        if isUUID(arg):
-            if guid is not None:
-                # Both the 2nd and 3rd args are UUIDs.  The first one
-                # should be used for shortName.
-                shortName = guid
-            guid = arg
-        else:
-            shortName = arg
+    fullName = args[0].decode("utf-8")
+    shortName = args[1].decode("utf-8")
+    uid = args[2].decode("utf-8")
 
-    if len(args) == 3 and guid is None:
-        # both shortName and guid were specified but neither was a UUID
-        raise ValueError("Invalid value for guid")
+    return fullName, shortName, uid
 
-    return fullName, shortName, guid
 
 
-
 def isUUID(value):
     try:
         UUID(value)
@@ -835,84 +789,7 @@
 
 
 
- at inlineCallbacks
-def updateRecord(create, directory, recordType, **kwargs):
-    """
-    Create/update a record, including the extra work required to set the
-    autoSchedule bit in the augment record.
 
-    If C{create} is true, the record is created, otherwise update the record
-    matching the guid in kwargs.
-    """
 
-    assignAutoSchedule = False
-    if "autoSchedule" in kwargs:
-        assignAutoSchedule = True
-        autoSchedule = kwargs["autoSchedule"]
-        del kwargs["autoSchedule"]
-    elif create:
-        assignAutoSchedule = True
-        autoSchedule = recordType in ("locations", "resources")
-
-    assignAutoScheduleMode = False
-    if "autoScheduleMode" in kwargs:
-        assignAutoScheduleMode = True
-        autoScheduleMode = kwargs["autoScheduleMode"]
-        del kwargs["autoScheduleMode"]
-    elif create:
-        assignAutoScheduleMode = True
-        autoScheduleMode = None
-
-    assignAutoAcceptGroup = False
-    if "autoAcceptGroup" in kwargs:
-        assignAutoAcceptGroup = True
-        autoAcceptGroup = kwargs["autoAcceptGroup"]
-        del kwargs["autoAcceptGroup"]
-    elif create:
-        assignAutoAcceptGroup = True
-        autoAcceptGroup = None
-
-    for key, value in kwargs.items():
-        if isinstance(value, unicode):
-            kwargs[key] = value.encode("utf-8")
-        elif isinstance(value, list):
-            newValue = [v.encode("utf-8") for v in value]
-            kwargs[key] = newValue
-
-    if create:
-        record = yield directory.createRecord(recordType, **kwargs)
-        kwargs['guid'] = record.guid
-    else:
-        try:
-            record = yield directory.updateRecord(recordType, **kwargs)
-        except NotImplementedError:
-            # Updating of directory information is not supported by underlying
-            # directory implementation, but allow augment information to be
-            # updated
-            record = yield directory.recordWithGUID(kwargs["guid"])
-            pass
-
-    augmentService = directory.serviceForRecordType(recordType).augmentService
-    augmentRecord = (yield augmentService.getAugmentRecord(kwargs['guid'], recordType))
-
-    if assignAutoSchedule:
-        augmentRecord.autoSchedule = autoSchedule
-    if assignAutoScheduleMode:
-        augmentRecord.autoScheduleMode = autoScheduleMode
-    if assignAutoAcceptGroup:
-        augmentRecord.autoAcceptGroup = autoAcceptGroup
-    (yield augmentService.addAugmentRecords([augmentRecord]))
-    try:
-        yield directory.updateRecord(recordType, **kwargs)
-    except NotImplementedError:
-        # Updating of directory information is not supported by underlying
-        # directory implementation, but allow augment information to be
-        # updated
-        pass
-
-    returnValue(record)
-
-
-
 if __name__ == "__main__":
     main()

Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py	2014-03-20 01:36:19 UTC (rev 12981)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py	2014-03-20 03:28:55 UTC (rev 12982)
@@ -824,11 +824,10 @@
         url = joinURL(parent.principalCollectionURL(), self.principalUID()) + slash
         self._url = url
 
-        # MOVE2WHO - hack: just adding an "s" using recordType.name (need a mapping)
         self._alternate_urls = tuple([
             joinURL(
                 parent.parent.principalCollectionURL(),
-                (record.recordType.name + "s"),
+                record.service.recordTypeToOldName(record.recordType),
                 quote(shortName.encode("utf-8"))
             ) + slash
             for shortName in record.shortNames

Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py
===================================================================
--- CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py	2014-03-20 01:36:19 UTC (rev 12981)
+++ CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py	2014-03-20 03:28:55 UTC (rev 12982)
@@ -27,6 +27,7 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 
+from twistedcaldav.directory.augment import AugmentRecord
 from twext.python.log import Logger
 from twext.who.directory import DirectoryRecord
 from twext.who.directory import DirectoryService as BaseDirectoryService
@@ -172,11 +173,77 @@
 
     @inlineCallbacks
     def updateRecords(self, records, create=False):
-        return self._directory.updateRecords(records, create=create)
+        """
+        Pull out the augmented fields from each record, apply those to the
+        augments database, then update the base records.
+        """
 
+        baseRecords = []
+        augmentRecords = []
 
-    @inlineCallbacks
+        for record in records:
+
+            # Split out the base fields from the augment fields
+            baseFields, augmentFields = self._splitFields(record)
+
+            if augmentFields:
+                # Create an AugmentRecord
+                autoScheduleMode = {
+                    AutoScheduleMode.none: "none",
+                    AutoScheduleMode.accept: "accept-always",
+                    AutoScheduleMode.decline: "decline-always",
+                    AutoScheduleMode.acceptIfFree: "accept-if-free",
+                    AutoScheduleMode.declineIfBusy: "decline-if-busy",
+                    AutoScheduleMode.acceptIfFreeDeclineIfBusy: "automatic",
+                }.get(augmentFields.get(FieldName.autoScheduleMode, None), None)
+                augmentRecord = AugmentRecord(
+                    uid=record.uid,
+                    enabledForCalendaring=augmentFields[FieldName.hasCalendars],
+                    enabledForAddressBooks=augmentFields[FieldName.hasContacts],
+                    autoScheduleMode=autoScheduleMode,
+                    enabledForLogin=augmentFields[FieldName.loginAllowed],
+                    autoAcceptGroup=augmentFields[FieldName.autoAcceptGroup],
+                    serverID=augmentFields[FieldName.serviceNodeUID],
+                )
+                augmentRecords.append(augmentRecord)
+
+            # Create new base records:
+            baseRecords.append(DirectoryRecord(self._directory, baseFields))
+
+        # Apply the augment records
+        if augmentRecords:
+            yield self._augmentDB.addAugmentRecords(augmentRecords)
+
+        # Apply the base records
+        if baseRecords:
+            yield self._directory.updateRecords(baseRecords, create=create)
+
+
+    def _splitFields(self, record):
+        """
+        Returns a tuple of two dictionaries; the first contains all the non
+        augment fields, and the second contains all the augment fields.
+        """
+        if record is None:
+            return None
+
+        augmentFields = {}
+        baseFields = record.fields.copy()
+        for field in (
+            FieldName.loginAllowed,
+            FieldName.hasCalendars, FieldName.hasContacts,
+            FieldName.autoScheduleMode, FieldName.autoAcceptGroup,
+            FieldName.serviceNodeUID
+        ):
+            if field in baseFields:
+                augmentFields[field] = baseFields[field]
+                del baseFields[field]
+
+        return (baseFields, augmentFields)
+
+
     def removeRecords(self, uids):
+        self._augmentDB.removeAugmentRecords(uids)
         return self._directory.removeRecords(uids)
 
 
@@ -185,6 +252,7 @@
         fields[field] = value
 
 
+
     @inlineCallbacks
     def _augment(self, record):
         if record is None:
@@ -205,12 +273,12 @@
         # print("Got augment record", augmentRecord)
 
         if augmentRecord:
-            # record.enabled = augmentRecord.enabled
-            # record.serverID = augmentRecord.serverID
+
             self._assignToField(
                 fields, "hasCalendars",
                 augmentRecord.enabledForCalendaring
             )
+
             self._assignToField(
                 fields, "hasContacts",
                 augmentRecord.enabledForAddressBooks
@@ -229,15 +297,22 @@
                 fields, "autoScheduleMode",
                 autoScheduleMode
             )
+
             self._assignToField(
                 fields, "autoAcceptGroup",
-                unicode(augmentRecord.autoAcceptGroup)
+                augmentRecord.autoAcceptGroup.decode("utf-8")
             )
+
             self._assignToField(
                 fields, "loginAllowed",
                 augmentRecord.enabledForLogin
             )
 
+            self._assignToField(
+                fields, "serviceNodeUID",
+                augmentRecord.serverID.decode("utf-8")
+            )
+
             if (
                 (
                     fields.get(
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140319/b6721c82/attachment-0001.html>


More information about the calendarserver-changes mailing list