[CalendarServer-changes] [2097] CalendarServer/branches/users/cdaboo/private_events-2081/ twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Thu Jan 10 12:23:28 PST 2008


Revision: 2097
          http://trac.macosforge.org/projects/calendarserver/changeset/2097
Author:   cdaboo at apple.com
Date:     2008-01-10 12:23:26 -0800 (Thu, 10 Jan 2008)

Log Message:
-----------
Query match access restrictions.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py
    CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py
    CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py

Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py	2008-01-08 21:32:58 UTC (rev 2096)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py	2008-01-10 20:23:26 UTC (rev 2097)
@@ -191,7 +191,7 @@
             self.filter_name = self.filter_name.encode("utf-8")
         self.defined     = not self.qualifier or (self.qualifier.qname() != (caldav_namespace, "is-not-defined"))
 
-    def match(self, item):
+    def match(self, item, access=None):
         """
         Returns True if the given calendar item (either a component, property or parameter value)
         matches this filter, False otherwise.
@@ -201,11 +201,11 @@
         # be negated by the caller
         if not self.defined: return True
 
-        if self.qualifier and not self.qualifier.match(item): return False
+        if self.qualifier and not self.qualifier.match(item, access): return False
 
         if len(self.filters) > 0:
             for filter in self.filters:
-                if filter._match(item):
+                if filter._match(item, access):
                     return True
             return False
         else:
@@ -893,12 +893,16 @@
 
     allowed_children = { (caldav_namespace, "comp-filter"): (1, 1) }
 
-    def match(self, component):
+    def match(self, component, access):
         """
         Returns True if the given calendar component matches this filter, False
         otherwise.
         """
         
+        # We only care about certain access restrictions.
+        if access not in (iComponent.ACCESS_CONFIDENTIAL, iComponent.ACCESS_RESTRICTED):
+            access = None
+
         # We need to prepare ourselves for a time-range query by pre-calculating
         # the set of instances up to the latest time-range limit. That way we can
         # avoid having to do some form of recurrence expansion for each query sub-part.
@@ -910,7 +914,7 @@
         self.children[0].setInstances(instances)
 
         # <filter> contains exactly one <comp-filter>
-        return self.children[0].match(component)
+        return self.children[0].match(component, access)
 
     def valid(self):
         """
@@ -962,7 +966,7 @@
     }
     allowed_attributes = { "name": True }
 
-    def match(self, item):
+    def match(self, item, access):
         """
         Returns True if the given calendar item (which is a component)
         matches this filter, False otherwise.
@@ -978,20 +982,26 @@
 
         if len(self.filters) > 0:
             for filter in self.filters:
-                if filter._match(item):
+                if filter._match(item, access):
                     return True
             return False
         else:
             return True
 
-    def _match(self, component):
+    def _match(self, component, access):
         # At least one subcomponent must match (or is-not-defined is set)
         for subcomponent in component.subcomponents():
+            # If access restrictions are in force, restrict matching to specific components only.
+            # In particular do not match VALARM.
+            if access and subcomponent.name() not in ("VEVENT", "VTODO", "VJOURNAL", "VFREEBUSY", "VTIMEZONE",):
+                continue
+            
+            # Try to match the component name
             if isinstance(self.filter_name, str):
                 if subcomponent.name() != self.filter_name: continue
             else:
                 if subcomponent.name() not in self.filter_name: continue
-            if self.match(subcomponent): break
+            if self.match(subcomponent, access): break
         else:
             return not self.defined
         return self.defined
@@ -1117,10 +1127,22 @@
     }
     allowed_attributes = { "name": True }
 
-    def _match(self, component):
+    def _match(self, component, access):
+        # When access restriction is in force, we need to only allow matches against the properties
+        # allowed by the access restriction level.
+        if access:
+            allowedProperties = iComponent.confidentialPropertiesMap.get(component.name(), None)
+            if allowedProperties and access == iComponent.ACCESS_RESTRICTED:
+                allowedProperties += iComponent.extraRestrictedProperties
+        else:
+            allowedProperties = None
+
         # At least one property must match (or is-not-defined is set)
         for property in component.properties():
-            if property.name() == self.filter_name and self.match(property): break
+            # Apply access restrictions, if any.
+            if allowedProperties is not None and property.name() not in allowedProperties:
+                continue
+            if property.name() == self.filter_name and self.match(property, access): break
         else:
             return not self.defined
         return self.defined
@@ -1173,7 +1195,7 @@
     }
     allowed_attributes = { "name": True }
 
-    def _match(self, property):
+    def _match(self, property, access):
         # We have to deal with the problem that the 'Native' form of a property
         # will be missing the TZID parameter due to the conversion performed. Converting
         # to non-native for the entire calendar object causes problems elsewhere, so its
@@ -1186,7 +1208,7 @@
         # At least one property must match (or is-not-defined is set)
         result = not self.defined
         for parameterName in property.params().keys():
-            if parameterName == self.filter_name and self.match(property.params()[parameterName]):
+            if parameterName == self.filter_name and self.match(property.params()[parameterName], access):
                 result = self.defined
                 break
 
@@ -1200,7 +1222,7 @@
     """
     name = "is-defined"
 
-    def match(self, component):
+    def match(self, component, access):
         return component is not None
 
 class IsNotDefined (CalDAVEmptyElement):
@@ -1210,7 +1232,7 @@
     """
     name = "is-not-defined"
 
-    def match(self, component):
+    def match(self, component, access):
         # Oddly, this needs always to return True so that it appears there is
         # a match - but we then "negate" the result if is-not-defined is set.
         # Actually this method should never be called as we special case the
@@ -1265,7 +1287,7 @@
         else:
             self.negate = False
 
-    def match(self, item):
+    def match(self, item, access):
         """
         Match the text for the item.
         If the item is a property, then match the property value,
@@ -1356,7 +1378,7 @@
         # No other tests
         return True
 
-    def match(self, property):
+    def match(self, property, access):
         """
         NB This is only called when doing a time-range match on a property.
         """

Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py	2008-01-08 21:32:58 UTC (rev 2096)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py	2008-01-10 20:23:26 UTC (rev 2097)
@@ -175,6 +175,16 @@
         "RESTRICTED"   : ACCESS_RESTRICTED,
     }
 
+    confidentialPropertiesMap = {
+        "VCALENDAR": ("PRODID", "VERSION", "CALSCALE", ACCESS_PROPERTY),
+        "VEVENT":    ("UID", "RECURRENCE-ID", "SEQUENCE", "DTSTAMP", "STATUS", "TRANSP", "DTSTART", "DTEND", "DURATION", "RRULE", "RDATE", "EXRULE", "EXDATE", ),
+        "VTODO":     ("UID", "RECURRENCE-ID", "SEQUENCE", "DTSTAMP", "STATUS", "DTSTART", "COMPLETED", "DUE", "DURATION", "RRULE", "RDATE", "EXRULE", "EXDATE", ),
+        "VJOURNAL":  ("UID", "RECURRENCE-ID", "SEQUENCE", "DTSTAMP", "STATUS", "DTSTART", "RRULE", "RDATE", "EXRULE", "EXDATE", ),
+        "VFREEBUSY": ("UID", "DTSTAMP", "DTSTART", "DTEND", "DURATION", "FREEBUSY", ),
+        "VTIMEZONE": None,
+    }
+    extraRestrictedProperties = ("SUMMARY", "LOCATION",)
+
     @classmethod
     def fromString(clazz, string):
         """

Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py
===================================================================
--- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py	2008-01-08 21:32:58 UTC (rev 2096)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py	2008-01-10 20:23:26 UTC (rev 2097)
@@ -31,6 +31,7 @@
 from twisted.web2.http import HTTPError, StatusResponse
 
 from twistedcaldav.caldavxml import caldav_namespace
+from twistedcaldav.customxml import TwistedCalendarAccessProperty
 from twistedcaldav.method import report_common
 
 import urllib
@@ -113,7 +114,16 @@
             @param calendar: the L{Component} calendar read from the resource.
             """
             
-            if query_ok or filter.match(calendar):
+            # Handle private events access restrictions
+            if not isowner:
+                try:
+                    access = resource.readDeadProperty(TwistedCalendarAccessProperty)
+                except HTTPError:
+                    access = None
+            else:
+                access = None
+
+            if query_ok or filter.match(calendar, access):
                 # Check size of results is within limit
                 matchcount[0] += 1
                 if matchcount[0] > max_number_of_results:

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080110/9c4a64e8/attachment-0001.html


More information about the calendarserver-changes mailing list