<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12982] CalendarServer/branches/users/sagen/move2who-4</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12982">12982</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2014-03-19 20:28:55 -0700 (Wed, 19 Mar 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>csmp supports record updates, including autoschedule and autoacceptgroup</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssagenmove2who4calendarservertoolsprincipalspy">CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectoryprincipalpy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4txdavwhoaugmentpy">CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssagenmove2who4calendarservertoolsprincipalspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/calendarserver/tools/principals.py (12981 => 12982)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -17,30 +17,36 @@
</span><span class="cx"> ##
</span><span class="cx"> from __future__ import print_function
</span><span class="cx">
</span><del>-import sys
-import os
-import operator
</del><span class="cx"> from getopt import getopt, GetoptError
</span><ins>+import operator
+import os
+import sys
</ins><span class="cx"> from uuid import UUID
</span><span class="cx">
</span><ins>+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
</ins><span class="cx"> from twisted.internet import reactor
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue, succeed
</span><del>-from txdav.xml import element as davxml
</del><ins>+from twistedcaldav.config import config
</ins><span class="cx"> from txdav.who.delegates import addDelegate, removeDelegate
</span><ins>+from txdav.who.idirectory import AutoScheduleMode
</ins><span class="cx">
</span><span class="cx">
</span><del>-from twistedcaldav.config import config
-from txdav.who.groups import schedulePolledGroupCachingUpdate
</del><ins>+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,
+}
</ins><span class="cx">
</span><del>-from calendarserver.tools.util import (
- booleanArgument, proxySubprincipal,
- recordForPrincipalID, prettyPrincipal, prettyRecord, ProxyError
-)
-from twistedcaldav.directory.augment import allowedAutoScheduleModes
</del><span class="cx">
</span><del>-from calendarserver.tools.cmdline import utilityMain, WorkerService
-
-
</del><span class="cx"> def usage(e=None):
</span><span class="cx"> if e:
</span><span class="cx"> print(e)
</span><span class="lines">@@ -74,8 +80,6 @@
</span><span class="cx"> print(" --add-read-proxy=principal: add a read-only proxy")
</span><span class="cx"> print(" --add-write-proxy=principal: add a read-write proxy")
</span><span class="cx"> print(" --remove-proxy=principal: remove a proxy")
</span><del>- print(" --set-auto-schedule={true|false}: set auto-accept state")
- print(" --get-auto-schedule: read auto-schedule state")
</del><span class="cx"> print(" --set-auto-schedule-mode={default|none|accept-always|decline-always|accept-if-free|decline-if-busy|automatic}: set auto-schedule mode")
</span><span class="cx"> print(" --get-auto-schedule-mode: read auto-schedule mode")
</span><span class="cx"> print(" --set-auto-accept-group=principal: set auto-accept-group")
</span><span class="lines">@@ -95,7 +99,6 @@
</span><span class="cx"> sys.exit(0)
</span><span class="cx">
</span><span class="cx">
</span><del>-
</del><span class="cx"> class PrincipalService(WorkerService):
</span><span class="cx"> """
</span><span class="cx"> Executes principals-related functions in a context which has access to the store
</span><span class="lines">@@ -155,8 +158,6 @@
</span><span class="cx"> "add-read-proxy=",
</span><span class="cx"> "add-write-proxy=",
</span><span class="cx"> "remove-proxy=",
</span><del>- "set-auto-schedule=",
- "get-auto-schedule",
</del><span class="cx"> "set-auto-schedule-mode=",
</span><span class="cx"> "get-auto-schedule-mode",
</span><span class="cx"> "set-auto-accept-group=",
</span><span class="lines">@@ -177,7 +178,7 @@
</span><span class="cx"> # Get configuration
</span><span class="cx"> #
</span><span class="cx"> configFileName = None
</span><del>- # addType = None
</del><ins>+ addType = None
</ins><span class="cx"> listPrincipalTypes = False
</span><span class="cx"> listPrincipals = None
</span><span class="cx"> searchPrincipals = None
</span><span class="lines">@@ -198,11 +199,11 @@
</span><span class="cx"> elif opt in ("-f", "--config"):
</span><span class="cx"> configFileName = arg
</span><span class="cx">
</span><del>- # elif opt in ("-a", "--add"):
- # addType = arg
</del><ins>+ elif opt in ("-a", "--add"):
+ addType = arg
</ins><span class="cx">
</span><del>- # elif opt in ("-r", "--remove"):
- # principalActions.append((action_removePrincipal,))
</del><ins>+ elif opt in ("-r", "--remove"):
+ principalActions.append((action_removePrincipal,))
</ins><span class="cx">
</span><span class="cx"> elif opt in ("", "--list-principal-types"):
</span><span class="cx"> listPrincipalTypes = True
</span><span class="lines">@@ -237,41 +238,26 @@
</span><span class="cx"> elif opt in ("", "--remove-proxy"):
</span><span class="cx"> principalActions.append((action_removeProxy, arg))
</span><span class="cx">
</span><del>- # elif opt in ("", "--set-auto-schedule"):
- # try:
- # autoSchedule = booleanArgument(arg)
- # except ValueError, e:
- # abort(e)
</del><ins>+ 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)
</ins><span class="cx">
</span><del>- # principalActions.append((action_setAutoSchedule, autoSchedule))
</del><ins>+ principalActions.append((action_setAutoScheduleMode, autoScheduleMode))
</ins><span class="cx">
</span><del>- # elif opt in ("", "--get-auto-schedule"):
- # principalActions.append((action_getAutoSchedule,))
</del><ins>+ elif opt in ("", "--get-auto-schedule-mode"):
+ principalActions.append((action_getAutoScheduleMode,))
</ins><span class="cx">
</span><del>- # 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)
</del><ins>+ elif opt in ("", "--set-auto-accept-group"):
+ principalActions.append((action_setAutoAcceptGroup, arg))
</ins><span class="cx">
</span><del>- # principalActions.append((action_setAutoScheduleMode, autoScheduleMode))
</del><ins>+ elif opt in ("", "--get-auto-accept-group"):
+ principalActions.append((action_getAutoAcceptGroup,))
</ins><span class="cx">
</span><del>- # 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,))
-
</del><span class="cx"> # elif opt in ("", "--set-geo"):
</span><span class="cx"> # principalActions.append((action_setValue, "Geo", arg))
</span><span class="cx">
</span><span class="lines">@@ -303,28 +289,38 @@
</span><span class="cx"> function = runListPrincipalTypes
</span><span class="cx"> params = ()
</span><span class="cx">
</span><del>- # elif addType:
</del><ins>+ elif addType:
</ins><span class="cx">
</span><del>- # try:
- # addType = matchStrings(addType, ["locations", "resources", "addresses"])
- # except ValueError, e:
- # print(e)
- # return
</del><ins>+ try:
+ addType = matchStrings(
+ addType,
+ [
+ "locations", "resources", "addresses", "users", "groups"
+ ]
+ )
+ except ValueError, e:
+ print(e)
+ return
</ins><span class="cx">
</span><del>- # try:
- # fullName, shortName, guid = parseCreationArgs(args)
- # except ValueError, e:
- # print(e)
- # return
</del><ins>+ try:
+ fullName, shortName, uid = parseCreationArgs(args)
+ except ValueError, e:
+ print(e)
+ return
</ins><span class="cx">
</span><del>- # if shortName is not None:
- # shortNames = [shortName]
- # else:
- # shortNames = ()
</del><ins>+ if fullName is not None:
+ fullNames = [fullName]
+ else:
+ fullNames = ()
</ins><span class="cx">
</span><del>- # function = runAddPrincipal
- # params = (addType, guid, shortNames, fullName)
</del><ins>+ if shortName is not None:
+ shortNames = [shortName]
+ else:
+ shortNames = ()
</ins><span class="cx">
</span><ins>+ function = runAddPrincipal
+ params = (addType, uid, shortNames, fullNames)
+
</ins><span class="cx"> elif listPrincipals:
</span><span class="cx"> try:
</span><span class="cx"> listPrincipals = matchStrings(
</span><span class="lines">@@ -349,13 +345,6 @@
</span><span class="cx"> if not args:
</span><span class="cx"> usage("No principals specified.")
</span><span class="cx">
</span><del>- # We don't have a directory yet
- # for arg in args:
- # try:
- # yield recordForPrincipalID(arg, checkOnly=True)
- # except ValueError, e:
- # abort(e)
-
</del><span class="cx"> unicodeArgs = [a.decode("utf-8") for a in args]
</span><span class="cx"> function = runPrincipalActions
</span><span class="cx"> params = (unicodeArgs, principalActions)
</span><span class="lines">@@ -384,7 +373,7 @@
</span><span class="cx"> printRecordList(records)
</span><span class="cx"> else:
</span><span class="cx"> print("No records of type %s" % (listPrincipals,))
</span><del>- except UnknownRecordTypeError, e:
</del><ins>+ except InvalidDirectoryRecordError, e:
</ins><span class="cx"> usage(e)
</span><span class="cx"> returnValue(None)
</span><span class="cx">
</span><span class="lines">@@ -453,28 +442,33 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-# @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)
</del><ins>+@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)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-# def action_removePrincipal(store, record):
-# directory = store.directoryService()
-# fullName = record.displayName
-# shortName = record.shortNames[0]
</del><ins>+@inlineCallbacks
+def action_removePrincipal(store, record):
+ directory = store.directoryService()
+ fullName = record.displayName
+ shortNames = ",".join(record.shortNames)
</ins><span class="cx">
</span><del>-# yield directory.destroyRecord(record.recordType, uid=record.uid)
-# print("Removed '%s' %s %s" % (fullName, shortName, record.uid))
</del><ins>+ yield directory.removeRecords([record.uid])
+ print(
+ "Removed '{full}' {shorts} {uid}".format(
+ full=fullName, shorts=shortNames, uid=record.uid
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -622,149 +616,122 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-# @inlineCallbacks
-# def action_setAutoSchedule(rootResource, directory, store, principal, autoSchedule):
-# if principal.record.recordType == "groups":
-# print("Enabling auto-schedule for %s is not allowed." % (principal,))
</del><ins>+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"
+ )
+ )
+ )
</ins><span class="cx">
</span><del>-# elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-# print("Enabling auto-schedule for %s is not allowed." % (principal,))
</del><span class="cx">
</span><del>-# else:
-# print("Setting auto-schedule to %s for %s" % (
-# {True: "true", False: "false"}[autoSchedule],
-# prettyPrincipal(principal),
-# ))
</del><ins>+@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)
+ )
+ )
</ins><span class="cx">
</span><del>-# (yield updateRecord(False, directory,
-# principal.record.recordType,
-# guid=principal.record.guid,
-# shortNames=principal.record.shortNames,
-# fullName=principal.record.fullName,
-# autoSchedule=autoSchedule,
-# **principal.record.extras
-# ))
</del><ins>+ 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)
+ )
+ )
</ins><span class="cx">
</span><ins>+ else:
+ print(
+ "Setting auto-schedule-mode to {mode} for {record}".format(
+ mode=autoScheduleMode.description,
+ record=prettyRecord(record),
+ )
+ )
</ins><span class="cx">
</span><ins>+ # Get original fields
+ newFields = record.fields.copy()
</ins><span class="cx">
</span><del>-# def action_getAutoSchedule(rootResource, directory, store, principal):
-# autoSchedule = principal.getAutoSchedule()
-# print("Auto-schedule for %s is %s" % (
-# prettyPrincipal(principal),
-# {True: "true", False: "false"}[autoSchedule],
-# ))
</del><ins>+ # Set new values
+ newFields[record.service.fieldName.autoScheduleMode] = autoScheduleMode
</ins><span class="cx">
</span><ins>+ updatedRecord = DirectoryRecord(record.service, newFields)
+ yield record.service.updateRecords([updatedRecord], create=False)
</ins><span class="cx">
</span><span class="cx">
</span><del>-# @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,))
</del><ins>+@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)
+ )
+ )
</ins><span class="cx">
</span><del>-# elif principal.record.recordType == "users" and not config.Scheduling.Options.AutoSchedule.AllowUsers:
-# print("Setting auto-schedule mode for %s is not allowed." % (principal,))
</del><ins>+ 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)
+ )
+ )
</ins><span class="cx">
</span><del>-# else:
-# print("Setting auto-schedule mode to %s for %s" % (
-# autoScheduleMode,
-# prettyPrincipal(principal),
-# ))
</del><ins>+ 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),
+ ))
</ins><span class="cx">
</span><del>-# (yield updateRecord(False, directory,
-# principal.record.recordType,
-# guid=principal.record.guid,
-# shortNames=principal.record.shortNames,
-# fullName=principal.record.fullName,
-# autoScheduleMode=autoScheduleMode,
-# **principal.record.extras
-# ))
</del><ins>+ # Get original fields
+ newFields = record.fields.copy()
</ins><span class="cx">
</span><ins>+ # Set new values
+ newFields[record.service.fieldName.autoAcceptGroup] = groupRecord.uid
</ins><span class="cx">
</span><ins>+ updatedRecord = DirectoryRecord(record.service, newFields)
+ yield record.service.updateRecords([updatedRecord], create=False)
</ins><span class="cx">
</span><del>-# 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,
-# ))
</del><span class="cx">
</span><span class="cx">
</span><ins>+@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)
+ )
+ )
</ins><span class="cx">
</span><del>-# @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,))
</del><span class="cx">
</span><del>-# 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"]]
-# ))
-
-
-
</del><span class="cx"> def abort(msg, status=1):
</span><span class="cx"> sys.stdout.write("%s\n" % (msg,))
</span><span class="cx"> try:
</span><span class="lines">@@ -777,32 +744,19 @@
</span><span class="cx">
</span><span class="cx"> def parseCreationArgs(args):
</span><span class="cx"> """
</span><del>- 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.
</del><ins>+ 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.
</ins><span class="cx"> """
</span><span class="cx">
</span><del>- 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
</del><ins>+ fullName = args[0].decode("utf-8")
+ shortName = args[1].decode("utf-8")
+ uid = args[2].decode("utf-8")
</ins><span class="cx">
</span><del>- 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")
</del><ins>+ return fullName, shortName, uid
</ins><span class="cx">
</span><del>- return fullName, shortName, guid
</del><span class="cx">
</span><span class="cx">
</span><del>-
</del><span class="cx"> def isUUID(value):
</span><span class="cx"> try:
</span><span class="cx"> UUID(value)
</span><span class="lines">@@ -835,84 +789,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-@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.
</del><span class="cx">
</span><del>- If C{create} is true, the record is created, otherwise update the record
- matching the guid in kwargs.
- """
</del><span class="cx">
</span><del>- 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)
-
-
-
</del><span class="cx"> if __name__ == "__main__":
</span><span class="cx"> main()
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectoryprincipalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/principal.py (12981 => 12982)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -824,11 +824,10 @@
</span><span class="cx"> url = joinURL(parent.principalCollectionURL(), self.principalUID()) + slash
</span><span class="cx"> self._url = url
</span><span class="cx">
</span><del>- # MOVE2WHO - hack: just adding an "s" using recordType.name (need a mapping)
</del><span class="cx"> self._alternate_urls = tuple([
</span><span class="cx"> joinURL(
</span><span class="cx"> parent.parent.principalCollectionURL(),
</span><del>- (record.recordType.name + "s"),
</del><ins>+ record.service.recordTypeToOldName(record.recordType),
</ins><span class="cx"> quote(shortName.encode("utf-8"))
</span><span class="cx"> ) + slash
</span><span class="cx"> for shortName in record.shortNames
</span></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4txdavwhoaugmentpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/sagen/move2who-4/txdav/who/augment.py (12981 => 12982)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx">
</span><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><span class="cx">
</span><ins>+from twistedcaldav.directory.augment import AugmentRecord
</ins><span class="cx"> from twext.python.log import Logger
</span><span class="cx"> from twext.who.directory import DirectoryRecord
</span><span class="cx"> from twext.who.directory import DirectoryService as BaseDirectoryService
</span><span class="lines">@@ -172,11 +173,77 @@
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def updateRecords(self, records, create=False):
</span><del>- return self._directory.updateRecords(records, create=create)
</del><ins>+ """
+ Pull out the augmented fields from each record, apply those to the
+ augments database, then update the base records.
+ """
</ins><span class="cx">
</span><ins>+ baseRecords = []
+ augmentRecords = []
</ins><span class="cx">
</span><del>- @inlineCallbacks
</del><ins>+ 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)
+
+
</ins><span class="cx"> def removeRecords(self, uids):
</span><ins>+ self._augmentDB.removeAugmentRecords(uids)
</ins><span class="cx"> return self._directory.removeRecords(uids)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -185,6 +252,7 @@
</span><span class="cx"> fields[field] = value
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def _augment(self, record):
</span><span class="cx"> if record is None:
</span><span class="lines">@@ -205,12 +273,12 @@
</span><span class="cx"> # print("Got augment record", augmentRecord)
</span><span class="cx">
</span><span class="cx"> if augmentRecord:
</span><del>- # record.enabled = augmentRecord.enabled
- # record.serverID = augmentRecord.serverID
</del><ins>+
</ins><span class="cx"> self._assignToField(
</span><span class="cx"> fields, "hasCalendars",
</span><span class="cx"> augmentRecord.enabledForCalendaring
</span><span class="cx"> )
</span><ins>+
</ins><span class="cx"> self._assignToField(
</span><span class="cx"> fields, "hasContacts",
</span><span class="cx"> augmentRecord.enabledForAddressBooks
</span><span class="lines">@@ -229,15 +297,22 @@
</span><span class="cx"> fields, "autoScheduleMode",
</span><span class="cx"> autoScheduleMode
</span><span class="cx"> )
</span><ins>+
</ins><span class="cx"> self._assignToField(
</span><span class="cx"> fields, "autoAcceptGroup",
</span><del>- unicode(augmentRecord.autoAcceptGroup)
</del><ins>+ augmentRecord.autoAcceptGroup.decode("utf-8")
</ins><span class="cx"> )
</span><ins>+
</ins><span class="cx"> self._assignToField(
</span><span class="cx"> fields, "loginAllowed",
</span><span class="cx"> augmentRecord.enabledForLogin
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+ self._assignToField(
+ fields, "serviceNodeUID",
+ augmentRecord.serverID.decode("utf-8")
+ )
+
</ins><span class="cx"> if (
</span><span class="cx"> (
</span><span class="cx"> fields.get(
</span></span></pre>
</div>
</div>
</body>
</html>