def on_update(cls, item, new_attr, old_attr, trans): from porcupine import datatypes # get previous value if old_attr: prvValue = old_attr.value else: prvValue = '' if new_attr.value != prvValue: if new_attr.value: oItemRef = _db.getItem(new_attr.value, trans) if oItemRef.getContentclass() in new_attr.relCc: oAttrRef = getattr(oItemRef, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): oAttrRef.value.append(item._id) elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = item._id _db.putItem(oItemRef, trans) else: new_attr.value = '' if prvValue: oItemRef = _db.getItem(prvValue, trans) oAttrRef = getattr(oItemRef, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): try: oAttrRef.value.remove(item._id) except ValueError: pass elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = '' _db.putItem(oItemRef, trans)
def delete(self, trans): """ Deletes the item permanently. @param trans: A valid transaction handle @return: None """ oUser = currentThread().context.session.user self = _db.getItem(self._id, trans) iUserRole = objectAccess.getAccess(self, oUser) bCanDelete = (iUserRole > objectAccess.AUTHOR) or \ (iUserRole == objectAccess.AUTHOR and self._owner == oUser._id) if (not(self._isSystem) and bCanDelete): # delete item physically self._delete(trans) # update container oParent = _db.getItem(self._parentid, trans) oParent._removeItemReference(self) _db.putItem(oParent, trans) else: raise exceptions.PermissionDenied, \ 'The object was not deleted.\n' + \ 'The user has insufficient permissions.'
def on_update(cls, item, new_attr, old_attr, trans): from porcupine.systemObjects import Composite # load objects dctObjects = {} for i, obj in enumerate(new_attr.value): if isinstance(obj, Composite): obj._containerid = item._id elif isinstance(obj, str): obj = _db.getItem(obj, trans) new_attr.value[i] = obj else: raise exceptions.ContainmentError, \ 'Invalid object type "%s" in composition.' % \ obj.__class__.__name__ dctObjects[obj._id] = obj # check containment compositeClass = misc.getCallableByName(new_attr.compositeClass) if [obj for obj in dctObjects.values() if not isinstance(obj, compositeClass)]: raise exceptions.ContainmentError, \ 'Invalid content class "%s" in composition.' % \ obj.getContentclass() # get previous value if old_attr != None: old_ids = set(old_attr.value) else: old_ids = set() new_ids = set([obj._id for obj in new_attr.value]) # calculate added composites lstAdded = list(new_ids - old_ids) for obj_id in lstAdded: _db.handle_update(dctObjects[obj_id], None, trans) dctObjects[obj_id]._isDeleted = False _db.putItem(dctObjects[obj_id], trans) # calculate constant composites lstConstant = list(new_ids & old_ids) for obj_id in lstConstant: _db.handle_update(dctObjects[obj_id], _db.getItem(obj_id, trans), trans) _db.putItem(dctObjects[obj_id], trans) # calculate removed composites lstRemoved = list(old_ids - new_ids) for obj_id in lstRemoved: composite4removal = _db.getItem(obj_id, trans) cls.removeComposite(composite4removal, trans) new_attr.value = list(new_ids)
def recycle(self, rbID, trans): """ Moves the item to the specified recycle bin. The item then becomes inaccesible. @param rbID: The id of the destination container, which must be a L{RecycleBin} instance @type rbID: str @param trans: A valid transaction handle @return: None """ oUser = currentThread().context.session.user self = _db.getItem(self._id, trans) iUserRole = objectAccess.getAccess(self, oUser) bCanDelete = (iUserRole > objectAccess.AUTHOR) or \ (iUserRole == objectAccess.AUTHOR and self._owner == oUser._id) if (not(self._isSystem) and bCanDelete): oDeleted = DeletedItem(self) oDeleted._owner = oUser._id oDeleted._created = time.time() oDeleted.modifiedBy = oUser.displayName.value oDeleted.modified = time.time() oDeleted._parentid = rbID _db.handle_update(oDeleted, None, trans) _db.putItem(oDeleted, trans) # delete item logically self._recycle(trans) # save container oParent = _db.getItem(self._parentid, trans) oParent._removeItemReference(self) _db.putItem(oParent, trans) #update recycle bin oRecycleBin = _db.getItem(rbID, trans) if not(oDeleted.getContentclass() in oRecycleBin.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type "%s".' % oDeleted.getContentclass() oRecycleBin._addItemReference(oDeleted) _db.putItem(oRecycleBin, trans) else: raise exceptions.PermissionDenied, \ 'The object was not deleted.\n' + \ 'The user has insufficient permissions.'
def on_update(item, new_attr, old_attr, trans): from porcupine import datatypes # remove duplicates new_attr.value = list(set(new_attr.value)) # get previous value if old_attr: prvValue = set(old_attr.value) noAccessList = RelatorNEventHandler.getNoAccessIds(old_attr, trans) else: prvValue = set() noAccessList = [] # get current value currentValue = set(new_attr.value + noAccessList) if currentValue != prvValue: # calculate added references lstAdded = list(currentValue - prvValue) for sID in lstAdded: try: ref_item = _db.getItem(sID, trans) except exceptions.ObjectNotFound: ref_item = None if ref_item != None and \ (not new_attr.relCc or ref_item.getContentclass() in new_attr.relCc): oAttrRef = getattr(ref_item, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): oAttrRef.value.append(item._id) elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = item._id _db.putItem(ref_item, trans) else: new_attr.value.remove(sID) # calculate removed references lstRemoved = list(prvValue - currentValue) for sID in lstRemoved: ref_item = _db.getItem(sID, trans) oAttrRef = getattr(ref_item, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): try: oAttrRef.value.remove(item._id) except ValueError: pass elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = '' _db.putItem(ref_item, trans)
def getItem(sPath, trans=None): """ Fetches an object from the database. If the user has no read permissions on the object then C{None} is returned. @param sPath: The object's ID or the object's full path. @type sPath: str @param trans: A valid transaction handle. @rtype: L{GenericItem<porcupine.systemObjects.GenericItem>} @raise porcupine.exceptions.ObjectNotFound: if the item does not exist """ if trans: trans.actions.append((getItem, (sPath, trans))) try: oItem = _db.getItem(sPath, trans) except exceptions.DBTransactionIncomplete: trans.retry() # check read permissions if objectAccess.getAccess(oItem, currentThread().context.session.user) != 0: return oItem else: return None
def restoreTo(self, sParentId, trans): """ Restores the deleted object to the specified container. @param sParentId: The ID of the container in which the item will be restored @type sParentId: str @param trans: A valid transaction handle @return: None """ ## TODO: check if oDeleted exists oDeleted = _db.getDeletedItem(self._deletedId, trans) oParent = _db.getItem(sParentId, trans) if not(oDeleted.getContentclass() in oParent.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type "%s".' % oDeleted.getContentclass() # try to restore original item self._restore(oDeleted, oParent, trans) self.delete(trans, False) # update container oParent._addItemReference(oDeleted) _db.putItem(oParent, trans)
def on_delete(cls, item, attr, trans, bPermanent): if not item._isDeleted: from porcupine import datatypes lstValue = attr.value if lstValue and attr.respectsReferences: raise exceptions.ReferentialIntegrityError, ( 'Cannot delete object "%s" ' % item.displayName.value + 'because it is being referenced by other objects.') # remove references for sID in lstValue: oItemRef = _db.getItem(sID, trans) if oItemRef.getContentclass() in attr.relCc: oAttrRef = getattr(oItemRef, attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): try: oAttrRef.value.remove(item._id) except ValueError: pass elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = '' _db.putItem(oItemRef, trans) else: attr.value.remove(sID)
def create(target, trans=None): if type(target)==str: target = _db.getItem(target, trans) shortcut = Shortcut() shortcut.displayName.value = target.displayName.value shortcut.target.value = target._id return shortcut
def __getitem__(self, key): """Implements slicing. Valid only for resolved object sets. Useful for paging. @raise TypeError: if the object set is unresolved """ if self._resolved: if self.schema == None: if type(key) == int: item = self._list[key] if type(item) == str: return _db.getItem(self._list[key], self._txn) else: return item else: return [item for item in ObjectSet(self._list[key], schema=None, txn=self._txn)] else: if type(key) == int: return dict(zip(self.schema, self._list[key])) else: return [dict(zip(self.schema, x)) for x in self._list[key]] else: raise TypeError, 'unresolved object sets do not support slicing'
def copyTo(self, targetId, trans): """ Copies the item to the designated target. @param targetId: The ID of the destination container @type targetId: str @param trans: A valid transaction handle @return: None """ oTarget = _db.getItem(targetId, trans) if self.isCollection and oTarget.isContainedIn(self._id, trans): raise exceptions.ContainmentError, \ 'Cannot copy item to destination.\n' + \ 'The destination is contained in the source.' #check permissions on target folder oUser = currentThread().context.session.user iUserRole = objectAccess.getAccess(oTarget, oUser) if not(self._isSystem) and iUserRole>objectAccess.READER: if not(self.getContentclass() in oTarget.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type "%s".' % self.getContentclass() self._copy(oTarget, trans, True) else: raise exceptions.PermissionDenied, \ 'The object was not copied.\n' + \ 'The user has insufficient permissions.'
def moveTo(self, targetId, trans): """ Moves the item to the designated target. @param targetId: The ID of the destination container @type targetId: str @param trans: A valid transaction handle @return: None """ oUser = currentThread().context.session.user iUserRole = objectAccess.getAccess(self, oUser) bCanMove = (iUserRole > objectAccess.AUTHOR)## or (iUserRole == objectAccess.AUTHOR and oItem.owner == oUser.id) parentId = self._parentid oTarget = _db.getItem(targetId, trans) iUserRole2 = objectAccess.getAccess(oTarget, oUser) if self.isCollection and oTarget.isContainedIn(self._id, trans): raise exceptions.ContainmentError, \ 'Cannot move item to destination.\n' + \ 'The destination is contained in the source.' if (not(self._isSystem) and bCanMove and iUserRole2 > objectAccess.READER): if not(self.getContentclass() in oTarget.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type "%s".' % self.getContentclass() self._parentid = targetId self.inheritRoles = False _db.putItem(self, trans) #update target oTarget._addItemReference(self) _db.putItem(oTarget, trans) #update parent oParent = _db.getItem(parentId, trans) oParent._removeItemReference(self) _db.putItem(oParent, trans) else: raise exceptions.PermissionDenied, \ 'The object was not moved.\n' + \ 'The user has insufficient permissions.'
def _applySecurity(self, oParent, trans): if self.inheritRoles: self.security = oParent.security if self.isCollection: for sID in self._subfolders.values() + self._items.values(): oItem = _db.getItem(sID, trans) if oItem.inheritRoles: oItem._applySecurity(self, trans) _db.putItem(oItem, trans)
def getHandle(identity=None): #open database _db.open() if identity==None: identity = _db.getItem('system') currentThread().context = HttpContext() currentThread().context.user = identity currentThread().trans = None return _db
def on_update(cls, item, new_attr, old_attr, trans): from porcupine import datatypes # remove duplicates new_attr.value = list(set(new_attr.value)) # get previous value if old_attr: prvValue = set(old_attr.value) noAccessList = cls.getNoAccessIds(old_attr, trans) else: prvValue = set() noAccessList = [] # get current value currentValue = set(new_attr.value + noAccessList) if currentValue != prvValue: # calculate added references lstAdded = list(currentValue - prvValue) for sID in lstAdded: oItemRef = _db.getItem(sID, trans) if oItemRef.getContentclass() in new_attr.relCc: oAttrRef = getattr(oItemRef, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): oAttrRef.value.append(item._id) elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = item._id _db.putItem(oItemRef, trans) else: new_attr.value.remove(sID) # calculate removed references lstRemoved = list(prvValue - currentValue) for sID in lstRemoved: oItemRef = _db.getItem(sID, trans) oAttrRef = getattr(oItemRef, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): try: oAttrRef.value.remove(item._id) except ValueError: pass elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = '' _db.putItem(oItemRef, trans)
def on_delete(item, attr, trans, bPermanent): lstValue = attr.value if not item._isDeleted: from porcupine import datatypes if lstValue and attr.respectsReferences: raise exceptions.ReferentialIntegrityError, ( 'Cannot delete object "%s" ' % item.displayName.value + 'because it is being referenced by other objects.') # remove references for sID in lstValue: ref_item = _db.getItem(sID, trans) if ref_item.getContentclass() in attr.relCc: oAttrRef = getattr(ref_item, attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): try: oAttrRef.value.remove(item._id) except ValueError: pass elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = '' _db.putItem(ref_item, trans) else: attr.value.remove(sID) if attr.cascadeDelete: oParent = _db.getItem(oItemRef._parentid, trans) try: oParent._removeItemReference(oItemRef) _db.putItem(oParent, trans) except KeyError: pass if attr.cascadeDelete: for sID in lstValue: if item._isDeleted: oItemRef = _db.getDeletedItem(sID, trans) else: oItemRef = _db.getItem(sID, trans) if bPermanent: oItemRef._delete(trans) else: oItemRef._recycle(trans)
def get_response(self, raw_request): response = HttpResponse() request = HttpRequest(raw_request) item = None registration = None try: try: self.context = HttpContext(request, response) sPath = request.serverVariables['PATH_INFO'] try: item = _db.getItem(sPath) except exceptions.ObjectNotFound: # dir request lstPath = sPath.split('/') dirName = lstPath[1] # remove blank entry & app name to get the requested path sDirPath = '/'.join(lstPath[2:]) webApp = pubdirs.dirs.get(dirName, None) if webApp: registration = webApp.getRegistration( sDirPath, request.serverVariables['REQUEST_METHOD'], request.serverVariables['HTTP_USER_AGENT'], request.getLang()) if not registration: raise exceptions.NotFound, \ 'The resource "%s" does not exist' % sPath # apply pre-processing filters [filter[0].apply(self.context, registration, **filter[1]) for filter in registration.filters if filter[0].type == 'pre'] rtype = registration.type if rtype == 1: # psp page ServerPage.execute(self.context, registration.context) elif rtype == 0: # static file response.loadFromFile(registration.context) if registration.encoding: response.charset = registration.encoding else: self.dispatch_method(item) except exceptions.ResponseEnd, e: pass if registration != None: # do we have caching directive? if registration.max_age: response.setExpiration(registration.max_age) # apply post-processing filters [filter[0].apply(self.context, registration, **filter[1]) for filter in registration.filters if filter[0].type == 'post']
def getItems(self, trans=None): """ Returns the items that this data type instance embeds. @param trans: A valid transaction handle @rtype: L{ObjectSet<porcupine.core.objectSet.ObjectSet>} """ lstItems = [_db.getItem(sID, trans) for sID in self.value] return(objectSet.ObjectSet(lstItems))
def runas_wrapper(item, context): user = _db.getItem(userid) context.original_user = context.session.user context.session.user = user try: self.decorator.__get__(item, item.__class__)(context) finally: # restore original user unless # the identity is not switched if context.session.user == user: context.session.user = context.original_user
def on_create(item, attr, trans): if item._isDeleted and attr.cascadeDelete and attr.value: from porcupine.systemObjects import DeletedItem oItemRef = _db.getDeletedItem(attr.value, trans) parent = _db.getItem(oItemRef._parentid, trans) # update container parent._addItemReference(oItemRef) _db.putItem(parent, trans) deletedItem = DeletedItem(oItemRef, trans) deletedItem._undelete(oItemRef, trans) Relator1EventHandler.on_update(item, attr, None, trans)
def getHandle(): #open database _db.open(misc.getCallableByName(settings['store']['interface'])) #create in-memory session manager SessionManager.open(inMemorySessionManager.SessionManager, 1200) oSystemUser = _db.getItem('system') context = HttpContext() context.session = SessionManager.create(oSystemUser) currentThread().context = context currentThread().trans = None return _db
def appendTo(self, parent, trans): """ Adds the item to the specified container. @param parent: The id of the destination container or the container itself @type parent: str OR L{Container} @param trans: A valid transaction handle @return: None """ if type(parent) == str: oParent = _db.getItem(parent, trans) else: oParent = parent if isinstance(self, Shortcut): contentclass = self.target.getItem(trans).getContentclass() else: contentclass = self.contentclass oUser = currentThread().context.user iUserRole = objectAccess.getAccess(oParent, oUser) if iUserRole == objectAccess.READER: raise exceptions.PermissionDenied, \ 'The user does not have write permissions ' + \ 'on the parent folder.' if not(contentclass in oParent.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type "%s".' % contentclass # set security to new item if iUserRole == objectAccess.COORDINATOR: # user is COORDINATOR self._applySecurity(oParent, trans) else: # user is not COORDINATOR self.inheritRoles = True self.security = oParent.security #if trans._retries == 0: # raise exceptions.DBTransactionIncomplete self._owner = oUser._id self._created = time.time() self.modifiedBy = oUser.displayName.value self.modified = time.time() self._parentid = oParent._id _db.handle_update(self, None, trans) _db.putItem(self, trans) # update container oParent._addItemReference(self) _db.putItem(oParent, trans)
def update(self, trans): """ Updates the item. @param trans: A valid transaction handle @return: None """ oOldItem = _db.getItem(self._id, trans) oUser = currentThread().context.session.user iUserRole = objectAccess.getAccess(oOldItem, oUser) if iUserRole > objectAccess.READER: # set security if iUserRole == objectAccess.COORDINATOR: # user is COORDINATOR if (self.inheritRoles != oOldItem.inheritRoles) or \ (not self.inheritRoles and self.security != oOldItem.security): oParent = _db.getItem(self._parentid, trans) self._applySecurity(oParent, trans) else: # restore previous ACL self.security = oOldItem.security self.inheritRoles = oOldItem.inheritRoles _db.handle_update(self, oOldItem, trans) self.modifiedBy = oUser.displayName.value self.modified = time.time() _db.putItem(self, trans) if self.displayName.value != oOldItem.displayName.value: oParent = _db.getItem(self._parentid, trans) oParent._removeItemReference(oOldItem) oParent._addItemReference(self) _db.putItem(oParent, trans) else: raise exceptions.PermissionDenied, \ 'The user does not have update permissions.'
def __loadcache(self, istart): if self._resolved: self.__cache = [ _db.getItem(id, self._txn) for id in self._list[istart:istart + self._cachesize]] else: if self._safe: self.__cache = filter(None, [db.getItem(id, self._txn) for id in self._list[istart:istart + self._cachesize]]) else: self.__cache = filter(None, [self.__getItemSafe(id) for id in self._list[istart:istart + self._cachesize]])
def on_update(item, new_attr, old_attr, trans): from porcupine import datatypes, systemObjects # get previous value if old_attr: prvValue = old_attr.value else: prvValue = '' if new_attr.value != prvValue: if new_attr.value: try: ref_item = _db.getItem(new_attr.value, trans) except exceptions.ObjectNotFound: ref_item = None if ref_item != None and \ (not new_attr.relCc or ref_item.getContentclass() in new_attr.relCc): oAttrRef = getattr(ref_item, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): oAttrRef.value.append(item._id) elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = item._id _db.putItem(ref_item, trans) else: new_attr.value = '' if prvValue: ref_item = _db.getItem(prvValue, trans) oAttrRef = getattr(ref_item, new_attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): try: oAttrRef.value.remove(item._id) except ValueError: pass elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = '' _db.putItem(ref_item, trans)
def on_delete(cls, item, attr, trans, bPermanent): if bPermanent: if item._isDeleted: func_get = _db.getDeletedItem else: func_get = _db.getItem composites = [func_get(sID, trans) for sID in attr.value] for composite in composites: cls.removeComposite(composite, trans) else: for sID in attr.value: composite = _db.getItem(sID, trans) _db.handle_delete(composite, trans, False) composite._isDeleted = True _db.putItem(composite, trans)
def _delete(self, trans): """ Deletes the item physically. Bypasses security checks. Returns: None """ _db.handle_delete(self, trans, True) _db.deleteItem(self, trans) if self.isCollection: lstChildren = self._items.values() + self._subfolders.values() for sID in lstChildren: oChild = _db.getItem(sID, trans) oChild._delete(trans)
def isContainedIn(self, itemId, trans=None): """ Checks if the item is contained in the specified container. @param itemId: The id of the container @type itemId: str @rtype: bool """ oItem = self while oItem._id is not '': if oItem._id==itemId: return True oItem = _db.getItem(oItem.parentid, trans) return False
def _recycle(self, trans): """ Removes an item's references and marks it as deleted. Returns: None """ _db.handle_delete(self, trans, False) self._isDeleted = True if self.isCollection: lstChildren = self._items.values() + self._subfolders.values() for sID in lstChildren: oChild = _db.getItem(sID, trans) oChild._recycle(trans) _db.putItem(self, trans)
def on_delete(cls, item, attr, trans, bPermanent): if not item._isDeleted: from porcupine import datatypes if attr.value: if attr.respectsReferences: raise exceptions.ReferentialIntegrityError, ( 'Cannot delete object "%s" ' % item.displayName.value + 'because it is referenced by other objects.') # remove reference oItemRef = _db.getItem(attr.value, trans) oAttrRef = getattr(oItemRef, attr.relAttr) if isinstance(oAttrRef, datatypes.RelatorN): try: oAttrRef.value.remove(item._id) except ValueError: pass elif isinstance(oAttrRef, datatypes.Relator1): oAttrRef.value = '' _db.putItem(oItemRef, trans)