[CalendarServer-changes] [12042] CalendarServer/branches/users/sagen/groupcacher

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 12 11:22:11 PDT 2014


Revision: 12042
          http://trac.calendarserver.org//changeset/12042
Author:   gaya at apple.com
Date:     2013-12-06 21:24:08 -0800 (Fri, 06 Dec 2013)
Log Message:
-----------
checkpoint

Modified Paths:
--------------
    CalendarServer/branches/users/sagen/groupcacher/twext/who/groups.py
    CalendarServer/branches/users/sagen/groupcacher/twext/who/test/test_groups.py
    CalendarServer/branches/users/sagen/groupcacher/twistedcaldav/ical.py
    CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/util.py

Modified: CalendarServer/branches/users/sagen/groupcacher/twext/who/groups.py
===================================================================
--- CalendarServer/branches/users/sagen/groupcacher/twext/who/groups.py	2013-12-06 21:43:35 UTC (rev 12041)
+++ CalendarServer/branches/users/sagen/groupcacher/twext/who/groups.py	2013-12-07 05:24:08 UTC (rev 12042)
@@ -25,7 +25,7 @@
 from twext.who.delegates import allGroupDelegates
 from twext.who.idirectory import RecordType
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twistedcaldav.ical import ignoredComponents
+from txdav.caldav.datastore.util import normalizationLookup
 from txdav.common.datastore.sql_tables import schema
 import datetime
 import hashlib
@@ -133,15 +133,6 @@
             )
         ).on(self.transaction)
 
-        # get group individual UIDs
-        groupMemember = schema.GROUP_MEMBERSHIP
-        rows = yield Select(
-                [groupMemember.MEMBER_GUID, ],
-                From=groupMemember,
-                Where=groupMemember.GROUP_ID == self.groupID,
-        ).on(self.transaction)
-        individualGUIDs = [row[0] for row in rows]
-
         # get calendar Object
         calObject = schema.CALENDAR_OBJECT
         rows = yield Select(
@@ -150,7 +141,7 @@
                 Where=calObject.RESOURCE_ID == self.eventID,
         ).on(self.transaction)
 
-        calendarID = row[0][0]
+        calendarID = rows[0][0]
         calendarHome = (yield self.Calendar._ownerHomeWithResourceID.on(
             self.transaction, resourceID=calendarID)
         )[0][0]
@@ -159,43 +150,20 @@
         calendarObject = yield calendar.objectResourceWithID(self.eventID)
         changed = False
 
-        individualUUIDs = set(["urn:uuid:" + individualGUID for individualGUID in individualGUIDs])
-        groupUUID = "urn:uuid:" + self.groupGUID()
-        vcalendar = yield calendarObject.component()
-        for component in vcalendar.subcomponents():
-            if component.name() in ignoredComponents:
-                continue
+        # get group individual UIDs
+        groupMemember = schema.GROUP_MEMBERSHIP
+        rows = yield Select(
+                [groupMemember.MEMBER_GUID, ],
+                From=groupMemember,
+                Where=groupMemember.GROUP_ID == self.groupID,
+        ).on(self.transaction)
+        individualGUIDs = [row[0] for row in rows]
 
-            oldAttendeeProps = component.getAttendees()
-            oldAttendeeUUIDs = set([attendeeProp.value() for attendeeProp in oldAttendeeProps])
+        component = yield calendarObject.component()
+        changed = component.expandGroupAttendee(self.groupGUID, individualGUIDs, normalizationLookup, self.directoryService().recordWithCalendarUserAddress)
 
-            # add new member attendees
-            for individualUUID in individualUUIDs - oldAttendeeUUIDs:
-                individualGUID = individualUUID[len("urn:uuid:"):]
-                directoryRecord = self.transaction.directoryService().recordWithUID(individualGUID)
-                newAttendeeProp = directoryRecord.attendee(params={"MEMBER": groupUUID})
-                component.addProperty(newAttendeeProp)
-                changed = True
-
-            # remove attendee or update MEMBER attribute for non-primary attendees in this group,
-            for attendeeProp in oldAttendeeProps:
-                if attendeeProp.hasParameter("MEMBER"):
-                    parameterValues = attendeeProp.parameterValues("MEMBER")
-                    if groupUUID in parameterValues:
-                        if attendeeProp.value() not in individualUUIDs:
-                            attendeeProp.removeParameterValue("MEMBER", groupUUID)
-                            if not attendeeProp.parameterValues("MEMBER"):
-                                component.removeProperty(attendeeProp)
-                            changed = True
-                    else:
-                        if attendeeProp.value() in individualUUIDs:
-                            attendeeProp.setParameter("MEMBER", parameterValues + [groupUUID, ])
-                            changed = True
-
-        # replace old with new
         if changed:
-            # TODO:  call calendarObject._setComponentInternal( vcalendar, mode ) instead?
-            yield calendarObject.setComponent(vcalendar)
+            yield calendarObject.setComponent(component)
 
 
 

Modified: CalendarServer/branches/users/sagen/groupcacher/twext/who/test/test_groups.py
===================================================================
--- CalendarServer/branches/users/sagen/groupcacher/twext/who/test/test_groups.py	2013-12-06 21:43:35 UTC (rev 12041)
+++ CalendarServer/branches/users/sagen/groupcacher/twext/who/test/test_groups.py	2013-12-07 05:24:08 UTC (rev 12042)
@@ -343,7 +343,7 @@
 DURATION:PT1H
 ATTENDEE;CN=User 01;EMAIL=user01 at example.com;RSVP=TRUE:urn:uuid:user01
 ATTENDEE;CN=User 02;EMAIL=user02 at example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:uuid:user02
-ATTENDEE;CN=Group 01;EMAIL=group01 at example.com;RSVP=TRUE;SCHEDULE-STATUS=3.7:urn:uuid:group01
+ATTENDEE;CN=Group 01;CUTYPE=GROUP;EMAIL=group01 at example.com;RSVP=TRUE;SCHEDULE-STATUS=3.7:urn:uuid:group01
 CREATED:20060101T150000Z
 ORGANIZER;CN=User 01;EMAIL=user01 at example.com:urn:uuid:user01
 SUMMARY:event 1

Modified: CalendarServer/branches/users/sagen/groupcacher/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/sagen/groupcacher/twistedcaldav/ical.py	2013-12-06 21:43:35 UTC (rev 12041)
+++ CalendarServer/branches/users/sagen/groupcacher/twistedcaldav/ical.py	2013-12-07 05:24:08 UTC (rev 12042)
@@ -3251,7 +3251,7 @@
                 # Check that we can lookup this calendar user address - if not
                 # we cannot do anything with it
                 cuaddr = normalizeCUAddr(prop.value())
-                name, guid, cuaddrs = lookupFunction(cuaddr, principalFunction, config)
+                name, guid, cutype, cuaddrs = lookupFunction(cuaddr, principalFunction, config)
                 if guid is None:
                     continue
 
@@ -3263,8 +3263,6 @@
                 # Get any CN parameter
                 oldCN = prop.parameterValue("CN")
 
-                cutype = prop.parameterValue("CUTYPE")
-
                 if toUUID:
                     # Always re-write value to urn:uuid
                     prop.setValue("urn:uuid:%s" % (guid,))
@@ -3343,11 +3341,56 @@
                     else:
                         prop.removeParameter("EMAIL")
 
+                if cutype == "INDIVIDUAL":
+                    cutype = None
+
+                if cutype != prop.parameterValue("CUTYPE"):
+                    if cutype:
+                        prop.setParameter("CUTYPE", cutype)
+                    else:
+                        prop.removeParameter("CUTYPE")
+
             # For VPOLL also do immediate children
             if component.name() == "VPOLL":
                 component.normalizeCalendarUserAddresses(lookupFunction, principalFunction, toUUID)
 
 
+    def expandGroupAttendee(self, groupGUID, individualGUIDs, lookupFunction, principalFunction):
+
+        individualUUIDs = set(["urn:uuid:" + individualGUID for individualGUID in individualGUIDs])
+        groupUUID = "urn:uuid:" + groupGUID
+        changed = False
+        for component in self.subcomponents():
+            if component.name() in ignoredComponents:
+                continue
+
+            oldAttendeeProps = component.properties("ATTENDEE")
+            oldAttendeeUUIDs = set([attendeeProp.value() for attendeeProp in oldAttendeeProps])
+
+            # add new member attendees
+            for individualUUID in individualUUIDs - oldAttendeeUUIDs:
+                directoryRecord = lookupFunction(individualUUID, principalFunction, config)
+                newAttendeeProp = directoryRecord.attendee(params={"MEMBER": groupUUID})
+                component.addProperty(newAttendeeProp)
+                changed = True
+
+            # remove attendee or update MEMBER attribute for non-primary attendees in this group,
+            for attendeeProp in oldAttendeeProps:
+                if attendeeProp.hasParameter("MEMBER"):
+                    parameterValues = attendeeProp.parameterValues("MEMBER")
+                    if groupUUID in parameterValues:
+                        if attendeeProp.value() not in individualUUIDs:
+                            attendeeProp.removeParameterValue("MEMBER", groupUUID)
+                            if not attendeeProp.parameterValues("MEMBER"):
+                                component.removeProperty(attendeeProp)
+                            changed = True
+                    else:
+                        if attendeeProp.value() in individualUUIDs:
+                            attendeeProp.setParameter("MEMBER", parameterValues + [groupUUID, ])
+                            changed = True
+        return changed
+
+
     def allPerUserUIDs(self):
 
         results = set()

Modified: CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/sql.py	2013-12-06 21:43:35 UTC (rev 12041)
+++ CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/sql.py	2013-12-07 05:24:08 UTC (rev 12042)
@@ -1582,13 +1582,16 @@
             if not self.calendar().isSupportedComponent(component.mainType()):
                 raise InvalidComponentTypeError("Invalid component type %s for calendar: %s" % (component.mainType(), self.calendar(),))
 
-            # Valid attendee list size check
-            yield self.validAttendeeListSizeCheck(component, inserting)
-
             # Normalize the calendar user addresses once we know we have valid
             # calendar data
             component.normalizeCalendarUserAddresses(normalizationLookup, self.directoryService().recordWithCalendarUserAddress)
 
+            # Expand groups
+            yield self.expandGroupAttendees(component)
+
+            # Valid attendee list size check
+            yield self.validAttendeeListSizeCheck(component, inserting)
+
         # Possible timezone stripping
         if config.EnableTimezonesByReference:
             component.stripKnownTimezones()
@@ -1601,8 +1604,40 @@
             self.validAccess(component, inserting, internal_state)
 
 
-    def validCalendarDataCheck(self, component, inserting):
+    @inlineCallbacks
+    def expandGroupAttendees(self, component):
         """
+        Expand group attendees
+        """
+
+        if not config.Scheduling.Options.AllowGroupAsAttendee:
+            return
+
+        attendeeProps = component.getAllAttendeeProperties()
+        groupGUIDs = [
+            attendeeProp.value()[len("urn:uuid:"):] for attendeeProp in attendeeProps
+            if attendeeProp.parameterValue("CUTYPE") == "GROUP"
+        ]
+
+        # FIXME: need to add event to Group resource ID here
+        #        need get get members here because they may not be cached yet
+
+        for groupGUID in groupGUIDs:
+            groupID, name, membershipHash = yield self._txn.groupByGUID(groupGUID)
+
+            groupMemember = schema.GROUP_MEMBERSHIP
+            rows = yield Select(
+                    [groupMemember.MEMBER_GUID, ],
+                    From=groupMemember,
+                    Where=groupMemember.GROUP_ID == groupID,
+            ).on(self._txn)
+            individualGUIDs = [row[0] for row in rows]
+
+            component.expandGroupAttendee(groupGUID, individualGUIDs, normalizationLookup, self.directoryService().recordWithCalendarUserAddress)
+
+
+    def validCalendarDataCheck(self, component, inserting): #@UnusedVariable
+        """
         Check that the calendar data is valid iCalendar.
         @return:         tuple: (True/False if the calendar data is valid,
                                  log message string).

Modified: CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/util.py
===================================================================
--- CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/util.py	2013-12-06 21:43:35 UTC (rev 12041)
+++ CalendarServer/branches/users/sagen/groupcacher/txdav/caldav/datastore/util.py	2013-12-07 05:24:08 UTC (rev 12042)
@@ -103,7 +103,7 @@
 def normalizationLookup(cuaddr, recordFunction, config):
     """
     Lookup function to be passed to ical.normalizeCalendarUserAddresses.
-    Returns a tuple of (Full name, guid, and calendar user address list)
+    Returns a tuple of (Full name, guid, cutype and calendar user address list)
     for the given cuaddr.  The recordFunction is called to retrieve the
     record for the cuaddr.
     """
@@ -114,7 +114,7 @@
         record = None
 
     if record is None:
-        return (None, None, None)
+        return (None, None, None, None)
     else:
         # RFC5545 syntax does not allow backslash escaping in
         # parameter values. A double-quote is thus not allowed
@@ -124,6 +124,7 @@
         return (
             record.fullName.replace('"', "'"),
             record.uid,
+            record.getCUType(),
             record.calendarUserAddresses,
         )
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/e0f964e8/attachment.html>


More information about the calendarserver-changes mailing list