[CalendarServer-changes] [11176] CalendarServer/branches/users/gaya/sharedgroups-3
source_changes at macosforge.org
source_changes at macosforge.org
Mon May 13 18:50:25 PDT 2013
Revision: 11176
http://trac.calendarserver.org//changeset/11176
Author: gaya at apple.com
Date: 2013-05-13 18:50:25 -0700 (Mon, 13 May 2013)
Log Message:
-----------
checkpoint: All tests work. All Calendar CalDAVTester tests work.
Modified Paths:
--------------
CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py
CalendarServer/branches/users/gaya/sharedgroups-3/txdav/carddav/datastore/sql.py
CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql.py
Modified: CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py 2013-05-14 01:48:52 UTC (rev 11175)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/twistedcaldav/storebridge.py 2013-05-14 01:50:25 UTC (rev 11176)
@@ -460,8 +460,7 @@
"""
# Check sharee collection first
- isShareeResource = self.isShareeResource()
- if isShareeResource:
+ if self.isShareeResource():
log.debug("Removing shared collection %s" % (self,))
yield self.removeShareeCollection(request)
returnValue(NO_CONTENT)
Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/carddav/datastore/sql.py 2013-05-14 01:48:52 UTC (rev 11175)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/carddav/datastore/sql.py 2013-05-14 01:50:25 UTC (rev 11176)
@@ -29,6 +29,7 @@
from twext.enterprise.dal.syntax import Delete, Insert, Len, Parameter, \
Update, Union, Max, Select, utcNowSQL
+from twext.enterprise.locking import NamedLock
from twext.python.clsprop import classproperty
from twext.web2.http import HTTPError
from twext.web2.http_headers import MimeType
@@ -37,13 +38,13 @@
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.python import hashlib
from twistedcaldav import carddavxml, customxml
+from twistedcaldav.config import config
from twistedcaldav.memcacher import Memcacher
from twistedcaldav.vcard import Component as VCard, InvalidVCardDataError, \
vCardProductID, Property
from txdav.base.propertystore.base import PropertyName
from txdav.base.propertystore.sql import PropertyStore
-from txdav.carddav.datastore.util import validateAddressBookComponent
from txdav.carddav.iaddressbookstore import IAddressBookHome, IAddressBook, \
IAddressBookObject, GroupForSharedAddressBookDeleteNotAllowedError, \
GroupWithUnsharedAddressNotAllowedError, SharedGroupDeleteNotAllowedError
@@ -55,7 +56,10 @@
_BIND_MODE_OWN, _BIND_MODE_WRITE, _BIND_STATUS_ACCEPTED, \
_BIND_STATUS_DECLINED, _BIND_STATUS_INVITED
from txdav.common.icommondatastore import InternalDataStoreError, \
+ InvalidUIDError, UIDExistsError, ObjectResourceTooBigError, \
+ InvalidObjectResourceError, InvalidComponentForStoreError, \
AllRetriesFailed
+
from txdav.xml.rfc2518 import ResourceType
from zope.interface.declarations import implements
@@ -1586,11 +1590,81 @@
yield addressbook.notifyChanged()
+ # Stuff from put_addressbook_common
+ def fullValidation(self, component, inserting):
+ """
+ Do full validation of source and destination calendar data.
+ """
+
+ # Basic validation
+
+ # Valid data sizes
+ if config.MaxResourceSize:
+ vcardsize = len(str(component))
+ if vcardsize > config.MaxResourceSize:
+ raise ObjectResourceTooBigError()
+
+ # Valid calendar data checks
+ self.validAddressDataCheck(component, inserting)
+
+
+ def validAddressDataCheck(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).
+ """
+
+ # Valid calendar data checks
+ if not isinstance(component, VCard):
+ raise InvalidObjectResourceError("Wrong type of object: %s" % (type(component),))
+
+ try:
+ component.validVCardData()
+ except InvalidVCardDataError, e:
+ raise InvalidObjectResourceError(str(e))
+ try:
+ component.validForCardDAV()
+ except InvalidVCardDataError, e:
+ raise InvalidComponentForStoreError(str(e))
+
+
@inlineCallbacks
+ def _lockUID(self, component, inserting):
+ """
+ Create a lock on the component's UID and verify, after getting the lock, that the incoming UID
+ meets the requirements of the store.
+ """
+
+ new_uid = component.resourceUID()
+ yield NamedLock.acquire(self._txn, "vCardUIDLock:%s" % (hashlib.md5(new_uid).hexdigest(),))
+
+ # UID conflict check - note we do this after reserving the UID to avoid a race condition where two requests
+ # try to write the same calendar data to two different resource URIs.
+
+ # Cannot overwrite a resource with different UID
+ if not inserting:
+ if self._uid != new_uid:
+ raise InvalidUIDError("Cannot change the UID in an existing resource.")
+ else:
+ # New UID must be unique for the owner - no need to do this on an overwrite as we can assume
+ # the store is already consistent in this regard
+ elsewhere = (yield self.addressbook().addressbookObjectWithUID(new_uid))
+ if elsewhere is not None:
+ raise UIDExistsError("UID already exists in same addressbook.")
+
+
+ @inlineCallbacks
def setComponent(self, component, inserting=False):
self._componentChanged = False
- validateAddressBookComponent(self, self._addressbook, component, inserting)
+
+ # Handle all validation operations here.
+ self.fullValidation(component, inserting)
+
+ # UID lock - this will remain active until the end of the current txn
+ yield self._lockUID(component, inserting)
+
yield self.updateDatabase(component, inserting=inserting)
yield self._changeAddressBookRevision(self._addressbook, inserting)
@@ -1606,8 +1680,6 @@
# update revisions table of shared group's containing address book
yield self._changeAddressBookRevision(self.ownerHome().addressbook(), inserting)
- # TODO: a better job here!
- #self._componentChanged = (self._component != component)
self._component = component
returnValue(self._componentChanged)
@@ -1720,6 +1792,7 @@
# don't store group members in object text
+ orginialComponent = str(component)
# sort addresses in component text
memberAddresses = component.resourceMemberAddresses()
component.removeProperties("X-ADDRESSBOOKSERVER-MEMBER")
@@ -1730,6 +1803,7 @@
componentText = str(component)
self._md5 = hashlib.md5(componentText).hexdigest()
self._size = len(componentText)
+ self._componentChanged = componentText != orginialComponent
# remove members from component get new text
component.removeProperties("X-ADDRESSBOOKSERVER-MEMBER")
Modified: CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql.py 2013-05-14 01:48:52 UTC (rev 11175)
+++ CalendarServer/branches/users/gaya/sharedgroups-3/txdav/common/datastore/sql.py 2013-05-14 01:50:25 UTC (rev 11176)
@@ -3048,7 +3048,17 @@
)
+ @inlineCallbacks
+ def invalidateQueryCache(self):
+ queryCacher = self._txn._queryCacher
+ if queryCacher is not None:
+ cacheKey = queryCacher.keyForHomeChildMetaData(self._resourceID)
+ yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+ cacheKey = queryCacher.keyForObjectWithName(self._home._resourceID, self._name)
+ yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+
+
class CommonHomeChild(LoggingMixIn, FancyEqMixin, Memoizable, _SharedSyncLogic, HomeChildBase, SharingMixIn):
"""
Common ancestor class of AddressBooks and Calendars.
@@ -3412,16 +3422,6 @@
return "<%s: %s>" % (self.__class__.__name__, self._resourceID)
- @inlineCallbacks
- def invalidateQueryCache(self):
- queryCacher = self._txn._queryCacher
- if queryCacher is not None:
- cacheKey = queryCacher.keyForHomeChildMetaData(self._resourceID)
- yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
- cacheKey = queryCacher.keyForObjectWithName(self._home._resourceID, self._name)
- yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
-
-
def exists(self):
"""
An empty resource-id means this object does not yet exist in the DB.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130513/993c1bc5/attachment.html>
More information about the calendarserver-changes
mailing list