[CalendarServer-changes] [2095]
CalendarServer/branches/users/cdaboo/private_events-2081/
twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jan 8 13:30:38 PST 2008
Revision: 2095
http://trac.macosforge.org/projects/calendarserver/changeset/2095
Author: cdaboo at apple.com
Date: 2008-01-08 13:30:35 -0800 (Tue, 08 Jan 2008)
Log Message:
-----------
Filtering of data on REPORT for X-CALENDARSERVER-ACCESS. Plus a little refactoring of the GET code
to pull out common pieces.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py
CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/get.py
CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py
CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_common.py
CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_multiget.py
CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/resource.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:29:20 UTC (rev 2094)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py 2008-01-08 21:30:35 UTC (rev 2095)
@@ -475,12 +475,7 @@
@param resource: the resource whose calendar data is to be returned.
@return: an L{CalendarData} with the (filtered) calendar data.
"""
- # Check for filtering or not
- if self.children:
- filtered = self.getFromICalendar(resource.iCalendar())
- return CalendarData.fromCalendar(filtered)
- else:
- return resource.iCalendarXML()
+ return self.elementFromCalendar(resource.iCalendar())
def elementFromCalendar(self, calendar):
"""
@@ -494,6 +489,138 @@
filtered = self.getFromICalendar(calendar)
return CalendarData.fromCalendar(filtered)
+ def elementFromResourceWithAccessRestrictions(self, resource, access):
+ """
+ Return a new CalendarData element comprised of the possibly filtered
+ calendar data from the specified resource. If no filter is being applied
+ read the data directly from the resource without parsing it. If a filter
+ is required, parse the iCal data and filter using this CalendarData.
+
+ Also, apply appropriate access restriction filtering to the data.
+
+ @param resource: the resource whose calendar data is to be returned.
+ @param access: private event access restriction level.
+ @return: an L{CalendarData} with the (filtered) calendar data.
+ """
+ return self.elementFromCalendarWithAccessRestrictions(resource.iCalendar(), access)
+
+ def elementFromCalendarWithAccessRestrictions(self, calendar, access):
+ """
+ Return a new CalendarData element comprised of the possibly filtered
+ calendar.
+
+ Also, apply appropriate access restriction filtering to the data.
+
+ @param calendar: the calendar that is to be filtered and returned.
+ @param access: private event access restriction level.
+ @return: an L{CalendarData} with the (filtered) calendar data.
+ """
+
+ # Do normal filtering first
+ filtered_calendar = self.getFromICalendar(calendar)
+
+ if access in (iComponent.ACCESS_CONFIDENTIAL, iComponent.ACCESS_RESTRICTED):
+ # Create a CALDAV:calendar-data element with the appropriate iCalendar Component/Property
+ # filter in place for the access restriction in use
+
+ extra_access = ()
+ if access == iComponent.ACCESS_RESTRICTED:
+ extra_access = (
+ Property(name="SUMMARY"),
+ Property(name="LOCATION"),
+ )
+
+ filter = CalendarData(
+ CalendarComponent(
+
+ # VCALENDAR proeprties
+ Property(name="PRODID"),
+ Property(name="VERSION"),
+ Property(name="CALSCALE"),
+ Property(name=iComponent.ACCESS_PROPERTY),
+
+ # VEVENT
+ CalendarComponent(
+ Property(name="UID"),
+ Property(name="RECURRENCE-ID"),
+ Property(name="SEQUENCE"),
+ Property(name="DTSTAMP"),
+ Property(name="STATUS"),
+ Property(name="TRANSP"),
+ Property(name="DTSTART"),
+ Property(name="DTEND"),
+ Property(name="DURATION"),
+ Property(name="RRULE"),
+ Property(name="RDATE"),
+ Property(name="EXRULE"),
+ Property(name="EXDATE"),
+ *extra_access,
+ **{"name":"VEVENT"}
+ ),
+
+ # VTODO
+ CalendarComponent(
+ Property(name="UID"),
+ Property(name="RECURRENCE-ID"),
+ Property(name="SEQUENCE"),
+ Property(name="DTSTAMP"),
+ Property(name="STATUS"),
+ Property(name="DTSTART"),
+ Property(name="COMPLETED"),
+ Property(name="DUE"),
+ Property(name="DURATION"),
+ Property(name="RRULE"),
+ Property(name="RDATE"),
+ Property(name="EXRULE"),
+ Property(name="EXDATE"),
+ *extra_access,
+ **{"name":"VTODO"}
+ ),
+
+ # VJOURNAL
+ CalendarComponent(
+ Property(name="UID"),
+ Property(name="RECURRENCE-ID"),
+ Property(name="SEQUENCE"),
+ Property(name="DTSTAMP"),
+ Property(name="STATUS"),
+ Property(name="TRANSP"),
+ Property(name="DTSTART"),
+ Property(name="RRULE"),
+ Property(name="RDATE"),
+ Property(name="EXRULE"),
+ Property(name="EXDATE"),
+ *extra_access,
+ **{"name":"VJOURNAL"}
+ ),
+
+ # VFREEBUSY
+ CalendarComponent(
+ Property(name="UID"),
+ Property(name="DTSTAMP"),
+ Property(name="DTSTART"),
+ Property(name="DTEND"),
+ Property(name="DURATION"),
+ Property(name="FREEBUSY"),
+ *extra_access,
+ **{"name":"VFREEBUSY"}
+ ),
+
+ # VTIMEZONE
+ CalendarComponent(
+ AllProperties(),
+ AllComponents(),
+ name="VTIMEZONE",
+ ),
+ name="VCALENDAR",
+ ),
+ )
+
+ # Now "filter" the resource calendar data through the CALDAV:calendar-data element
+ return filter.elementFromCalendar(filtered_calendar)
+ else:
+ return CalendarData.fromCalendar(filtered_calendar)
+
def getFromICalendar(self, calendar):
"""
Returns a calendar object containing the data in the given calendar
Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/get.py
===================================================================
--- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/get.py 2008-01-08 21:29:20 UTC (rev 2094)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/get.py 2008-01-08 21:30:35 UTC (rev 2095)
@@ -48,111 +48,16 @@
d.getResult()
# Non DAV:owner's have limited access to the data
- d = waitForDeferred(self.owner(request))
+ d = waitForDeferred(self.isOwner(request))
yield d
- owner = d.getResult()
+ isowner = d.getResult()
- authz = self.currentPrincipal(request)
- if davxml.Principal(owner) != authz:
+ if not isowner:
- # Create a CALDAV:calendar-data element with the appropriate iCalendar Component/Property
- # filter in place for the access restriction in use
-
- extra_access = ()
- if access == Component.ACCESS_RESTRICTED:
- extra_access = (
- caldavxml.Property(name="SUMMARY"),
- caldavxml.Property(name="LOCATION"),
- )
+ # Now "filter" the resource calendar data through the CALDAV:calendar-data element and apply
+ # access restrictions to the data.
+ caldata = caldavxml.CalendarData().elementFromResourceWithAccessRestrictions(self, access).calendarData()
- filter = caldavxml.CalendarData(
- caldavxml.CalendarComponent(
-
- # VCALENDAR proeprties
- caldavxml.Property(name="PRODID"),
- caldavxml.Property(name="VERSION"),
- caldavxml.Property(name="CALSCALE"),
- caldavxml.Property(name=Component.ACCESS_PROPERTY),
-
- # VEVENT
- caldavxml.CalendarComponent(
- caldavxml.Property(name="UID"),
- caldavxml.Property(name="RECURRENCE-ID"),
- caldavxml.Property(name="SEQUENCE"),
- caldavxml.Property(name="DTSTAMP"),
- caldavxml.Property(name="STATUS"),
- caldavxml.Property(name="TRANSP"),
- caldavxml.Property(name="DTSTART"),
- caldavxml.Property(name="DTEND"),
- caldavxml.Property(name="DURATION"),
- caldavxml.Property(name="RRULE"),
- caldavxml.Property(name="RDATE"),
- caldavxml.Property(name="EXRULE"),
- caldavxml.Property(name="EXDATE"),
- *extra_access,
- **{"name":"VEVENT"}
- ),
-
- # VTODO
- caldavxml.CalendarComponent(
- caldavxml.Property(name="UID"),
- caldavxml.Property(name="RECURRENCE-ID"),
- caldavxml.Property(name="SEQUENCE"),
- caldavxml.Property(name="DTSTAMP"),
- caldavxml.Property(name="STATUS"),
- caldavxml.Property(name="DTSTART"),
- caldavxml.Property(name="COMPLETED"),
- caldavxml.Property(name="DUE"),
- caldavxml.Property(name="DURATION"),
- caldavxml.Property(name="RRULE"),
- caldavxml.Property(name="RDATE"),
- caldavxml.Property(name="EXRULE"),
- caldavxml.Property(name="EXDATE"),
- *extra_access,
- **{"name":"VTODO"}
- ),
-
- # VJOURNAL
- caldavxml.CalendarComponent(
- caldavxml.Property(name="UID"),
- caldavxml.Property(name="RECURRENCE-ID"),
- caldavxml.Property(name="SEQUENCE"),
- caldavxml.Property(name="DTSTAMP"),
- caldavxml.Property(name="STATUS"),
- caldavxml.Property(name="TRANSP"),
- caldavxml.Property(name="DTSTART"),
- caldavxml.Property(name="RRULE"),
- caldavxml.Property(name="RDATE"),
- caldavxml.Property(name="EXRULE"),
- caldavxml.Property(name="EXDATE"),
- *extra_access,
- **{"name":"VJOURNAL"}
- ),
-
- # VFREEBUSY
- caldavxml.CalendarComponent(
- caldavxml.Property(name="UID"),
- caldavxml.Property(name="DTSTAMP"),
- caldavxml.Property(name="DTSTART"),
- caldavxml.Property(name="DTEND"),
- caldavxml.Property(name="DURATION"),
- caldavxml.Property(name="FREEBUSY"),
- *extra_access,
- **{"name":"VFREEBUSY"}
- ),
-
- # VTIMEZONE
- caldavxml.CalendarComponent(
- caldavxml.AllProperties(),
- caldavxml.AllComponents(),
- name="VTIMEZONE",
- ),
- name="VCALENDAR",
- ),
- )
-
- # Now "filter" the resource calendar data through the CALDAV:calendar-data element
- caldata = filter.elementFromResource(self).calendarData()
response = Response()
response.stream = MemoryStream(caldata)
response.headers.setHeader("content-type", MimeType.fromString("text/calendar; charset=utf-8"))
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:29:20 UTC (rev 2094)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py 2008-01-08 21:30:35 UTC (rev 2095)
@@ -104,7 +104,7 @@
@param uri: the uri for the calendar collecton resource.
"""
- def queryCalendarObjectResource(resource, uri, name, calendar, query_ok = False):
+ def queryCalendarObjectResource(resource, uri, name, calendar, query_ok=False, isowner=True):
"""
Run a query on the specified calendar.
@param resource: the L{CalDAVFile} for the calendar.
@@ -124,7 +124,7 @@
else:
href = davxml.HRef.fromString(uri)
- return report_common.responseForHref(request, responses, href, resource, calendar, propertiesForResource, query)
+ return report_common.responseForHref(request, responses, href, resource, calendar, propertiesForResource, query, isowner)
else:
return succeed(None)
@@ -146,7 +146,12 @@
filteredaces = waitForDeferred(calresource.inheritedACEsforChildren(request))
yield filteredaces
filteredaces = filteredaces.getResult()
-
+
+ # Check private events access status
+ d = waitForDeferred(calresource.isOwner(request))
+ yield d
+ isowner = d.getResult()
+
# Check for disabled access
if filteredaces is not None:
# See whether the filter is valid for an index only query
@@ -183,7 +188,7 @@
else:
calendar = None
- d = waitForDeferred(queryCalendarObjectResource(child, uri, child_uri_name, calendar, query_ok = index_query_ok))
+ d = waitForDeferred(queryCalendarObjectResource(child, uri, child_uri_name, calendar, query_ok = index_query_ok, isowner=isowner))
yield d
d.getResult()
else:
@@ -205,6 +210,11 @@
tz = tz.getResult()
filter.settimezone(tz)
+ # Check private events access status
+ d = waitForDeferred(calresource.isOwner(request))
+ yield d
+ isowner = d.getResult()
+
calendar = calresource.iCalendar()
d = waitForDeferred(queryCalendarObjectResource(calresource, uri, None, calendar))
yield d
Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_common.py 2008-01-08 21:29:20 UTC (rev 2094)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_common.py 2008-01-08 21:30:35 UTC (rev 2095)
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
+from twistedcaldav.customxml import TwistedCalendarAccessProperty
__all__ = [
"applyToCalendarCollections",
@@ -93,7 +94,7 @@
applyToCalendarCollections = deferredGenerator(applyToCalendarCollections)
-def responseForHref(request, responses, href, resource, calendar, propertiesForResource, propertyreq):
+def responseForHref(request, responses, href, resource, calendar, propertiesForResource, propertyreq, isowner=True):
"""
Create an appropriate property status response for the given resource.
@@ -102,10 +103,12 @@
@param href: the L{HRef} element of the resource being targetted.
@param resource: the L{CalDAVFile} for the targetted resource.
@param calendar: the L{Component} for the calendar for the resource. This may be None
- if the calendar has not already been read in, in which case the resource
- will be used to get the calendar if needed.
+ if the calendar has not already been read in, in which case the resource
+ will be used to get the calendar if needed.
@param propertiesForResource: the method to use to get the list of properties to return.
@param propertyreq: the L{PropertyContainer} element for the properties of interest.
+ @param isowner: C{True} if the authorized principal making the request is the DAV:owner,
+ C{False} otherwise.
"""
def _defer(properties_by_status):
@@ -122,38 +125,42 @@
)
)
- d = propertiesForResource(request, propertyreq, resource, calendar)
+ d = propertiesForResource(request, propertyreq, resource, calendar, isowner)
d.addCallback(_defer)
return d
-def allPropertiesForResource(request, prop, resource, calendar=None): #@UnusedVariable
+def allPropertiesForResource(request, prop, resource, calendar=None, isowner=True): #@UnusedVariable
"""
Return all (non-hidden) properties for the specified resource.
@param request: the L{IRequest} for the current request.
@param prop: the L{PropertyContainer} element for the properties of interest.
@param resource: the L{CalDAVFile} for the targetted resource.
@param calendar: the L{Component} for the calendar for the resource. This may be None
- if the calendar has not already been read in, in which case the resource
- will be used to get the calendar if needed.
+ if the calendar has not already been read in, in which case the resource
+ will be used to get the calendar if needed.
+ @param isowner: C{True} if the authorized principal making the request is the DAV:owner,
+ C{False} otherwise.
@return: a map of OK and NOT FOUND property values.
"""
def _defer(props):
- return _namedPropertiesForResource(request, props, resource, calendar)
+ return _namedPropertiesForResource(request, props, resource, calendar, isowner)
d = resource.listAllprop(request)
d.addCallback(_defer)
return d
-def propertyNamesForResource(request, prop, resource, calendar=None): #@UnusedVariable
+def propertyNamesForResource(request, prop, resource, calendar=None, isowner=True): #@UnusedVariable
"""
Return property names for all properties on the specified resource.
@param request: the L{IRequest} for the current request.
@param prop: the L{PropertyContainer} element for the properties of interest.
@param resource: the L{CalDAVFile} for the targetted resource.
@param calendar: the L{Component} for the calendar for the resource. This may be None
- if the calendar has not already been read in, in which case the resource
- will be used to get the calendar if needed.
+ if the calendar has not already been read in, in which case the resource
+ will be used to get the calendar if needed.
+ @param isowner: C{True} if the authorized principal making the request is the DAV:owner,
+ C{False} otherwise.
@return: a map of OK and NOT FOUND property values.
"""
@@ -167,19 +174,21 @@
d.addCallback(_defer)
return d
-def propertyListForResource(request, prop, resource, calendar=None):
+def propertyListForResource(request, prop, resource, calendar=None, isowner=True):
"""
Return the specified properties on the specified resource.
@param request: the L{IRequest} for the current request.
@param prop: the L{PropertyContainer} element for the properties of interest.
@param resource: the L{CalDAVFile} for the targetted resource.
@param calendar: the L{Component} for the calendar for the resource. This may be None
- if the calendar has not already been read in, in which case the resource
- will be used to get the calendar if needed.
+ if the calendar has not already been read in, in which case the resource
+ will be used to get the calendar if needed.
+ @param isowner: C{True} if the authorized principal making the request is the DAV:owner,
+ C{False} otherwise.
@return: a map of OK and NOT FOUND property values.
"""
- return _namedPropertiesForResource(request, prop.children, resource, calendar)
+ return _namedPropertiesForResource(request, prop.children, resource, calendar, isowner)
def validPropertyListCalendarDataTypeVersion(prop):
"""
@@ -204,15 +213,17 @@
return result, message, generate_calendar_data
-def _namedPropertiesForResource(request, props, resource, calendar=None):
+def _namedPropertiesForResource(request, props, resource, calendar=None, isowner=True):
"""
Return the specified properties on the specified resource.
@param request: the L{IRequest} for the current request.
@param props: a list of property elements or qname tuples for the properties of interest.
@param resource: the L{CalDAVFile} for the targetted resource.
@param calendar: the L{Component} for the calendar for the resource. This may be None
- if the calendar has not already been read in, in which case the resource
- will be used to get the calendar if needed.
+ if the calendar has not already been read in, in which case the resource
+ will be used to get the calendar if needed.
+ @param isowner: C{True} if the authorized principal making the request is the DAV:owner,
+ C{False} otherwise.
@return: a map of OK and NOT FOUND property values.
"""
properties_by_status = {
@@ -222,10 +233,19 @@
for property in props:
if isinstance(property, caldavxml.CalendarData):
+ # Handle private events access restrictions
+ if not isowner:
+ try:
+ access = resource.readDeadProperty(TwistedCalendarAccessProperty)
+ except HTTPError:
+ access = None
+ else:
+ access = None
+
if calendar:
- propvalue = property.elementFromCalendar(calendar)
+ propvalue = property.elementFromCalendarWithAccessRestrictions(calendar, access)
else:
- propvalue = property.elementFromResource(resource)
+ propvalue = property.elementFromResourceWithAccessRestrictions(resource, access)
if propvalue is None:
raise ValueError("Invalid CalDAV:calendar-data for request: %r" % (property,))
properties_by_status[responsecode.OK].append(propvalue)
Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_multiget.py
===================================================================
--- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_multiget.py 2008-01-08 21:29:20 UTC (rev 2094)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_multiget.py 2008-01-08 21:30:35 UTC (rev 2095)
@@ -63,17 +63,15 @@
if propertyreq.qname() == ("DAV:", "allprop"):
propertiesForResource = report_common.allPropertiesForResource
- generate_calendar_data = False
elif propertyreq.qname() == ("DAV:", "propname"):
propertiesForResource = report_common.propertyNamesForResource
- generate_calendar_data = False
elif propertyreq.qname() == ("DAV:", "prop"):
propertiesForResource = report_common.propertyListForResource
# Verify that any calendar-data element matches what we can handle
- result, message, generate_calendar_data = report_common.validPropertyListCalendarDataTypeVersion(propertyreq)
+ result, message, _ignore = report_common.validPropertyListCalendarDataTypeVersion(propertyreq)
if not result:
log.err(message)
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "supported-calendar-data")))
@@ -113,14 +111,21 @@
# Check for disabled access
if filteredaces is None:
disabled = True
+
+ # Check private events access status
+ d = waitForDeferred(self.isOwner(request))
+ yield d
+ isowner = d.getResult()
elif self.isCollection():
requestURIis = "collection"
filteredaces = None
lastParent = None
+ isowner = None
else:
requestURIis = "resource"
filteredaces = None
+ isowner = None
if not disabled:
@@ -169,7 +174,7 @@
# Get properties for all valid readable resources
for resource, href in ok_resources:
- d = waitForDeferred(report_common.responseForHref(request, responses, davxml.HRef.fromString(href), resource, None, propertiesForResource, propertyreq))
+ d = waitForDeferred(report_common.responseForHref(request, responses, davxml.HRef.fromString(href), resource, None, propertiesForResource, propertyreq, isowner=isowner))
yield d
d.getResult()
@@ -233,7 +238,11 @@
filteredaces = waitForDeferred(parent.inheritedACEsforChildren(request))
yield filteredaces
filteredaces = filteredaces.getResult()
-
+
+ # Check private events access status
+ d = waitForDeferred(parent.isOwner(request))
+ yield d
+ isowner = d.getResult()
else:
name = unquote(resource_uri[resource_uri.rfind("/") + 1:])
if (resource_uri != request.uri) or not self.exists():
@@ -254,6 +263,11 @@
filteredaces = waitForDeferred(parent.inheritedACEsforChildren(request))
yield filteredaces
filteredaces = filteredaces.getResult()
+
+ # Check private events access status
+ d = waitForDeferred(parent.isOwner(request))
+ yield d
+ isowner = d.getResult()
# Check privileges - must have at least DAV:read
try:
@@ -264,7 +278,7 @@
responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
continue
- d = waitForDeferred(report_common.responseForHref(request, responses, href, child, None, propertiesForResource, propertyreq))
+ d = waitForDeferred(report_common.responseForHref(request, responses, href, child, None, propertiesForResource, propertyreq, isowner=isowner))
yield d
d.getResult()
Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/resource.py 2008-01-08 21:29:20 UTC (rev 2094)
+++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/resource.py 2008-01-08 21:30:35 UTC (rev 2095)
@@ -304,6 +304,19 @@
else:
yield None
+ @deferredGenerator
+ def isOwner(self, request):
+ """
+ Determine whether the DAV:owner of this resource matches the currently authorized principal
+ in the request.
+ """
+
+ d = waitForDeferred(self.owner(request))
+ yield d
+ owner = d.getResult()
+ result = (davxml.Principal(owner) == self.currentPrincipal(request))
+ yield result
+
##
# CalDAV
##
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080108/5a9162c2/attachment-0001.html
More information about the calendarserver-changes
mailing list