def on_update(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 """ trans.actions.append( (self.delete, (trans, ))) try: oUser = currentThread().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 serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
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 """ trans.actions.append( (self.recycle, (rbID, trans)) ) try: oUser = currentThread().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 serverExceptions.ContainmentError oRecycleBin._addItemReference(oDeleted) db.putItem(oRecycleBin, trans) else: raise serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
def __loadcache(self, istart): # print 'loading cache ' + str(istart) self.__cache = [ db.getItem(id) for id in self._list[istart:istart + self.__objectcache] ] self.__cacheindex = istart
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.serverExceptions.DBItemNotFound: if the item does not exist """ if (trans): trans.actions.append( (getItem, (sPath, trans)) ) try: oItem = db.getItem(sPath, trans) except serverExceptions.DBTransactionIncomplete: trans.retry() # check read permissions if objectAccess.getAccess(oItem, currentThread().session.user): 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 """ trans.actions.append( (self.restoreTo, (sParentId, trans)) ) try: ## TODO: check if oDeleted exists oDeleted = db.getDeletedItem(self._deletedId, trans) oParent = db.getItem(sParentId, trans) if not(oDeleted.getContentclass() in oParent.containment): raise serverExceptions.ContainmentError # try to restore original item self._restore(oDeleted, oParent, trans) self.delete(trans, False) # update container oParent._addItemReference(oDeleted) db.putItem(oParent, trans) except serverExceptions.DBTransactionIncomplete: trans.retry()
def restore(self, trans): """ Restores the deleted item to its original location, if it still exists. @param trans: A valid transaction handle @return: None @raise porcupine.serverExceptions.DBItemNotFound: If the original location no longer exists. """ trans.actions.append( (self.restore, (trans, )) ) try: ## TODO: check if oDeleted exists oDeleted = db.getDeletedItem(self._deletedId, trans) oOriginalParent = db.getItem(oDeleted._parentid, trans) # try to restore original item self._restore(oDeleted, oOriginalParent, trans) self.delete(trans, False) # update container oOriginalParent._addItemReference(oDeleted) db.putItem(oOriginalParent, trans) except serverExceptions.DBTransactionIncomplete: trans.retry()
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 """ trans.actions.append( (self.copyTo, (targetId, trans)) ) try: oTarget = db.getItem(targetId, trans) if self.isCollection and oTarget.isContainedIn(self._id): raise serverExceptions.TargetContainedInSource #check permissions on target folder oUser = currentThread().session.user iUserRole = objectAccess.getAccess(oTarget, oUser) if not(self._isSystem) and iUserRole>objectAccess.READER: if not(self.getContentclass() in oTarget.containment): raise serverExceptions.ContainmentError self._copy(oTarget, trans, True) else: raise serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
def createGuestSessionAndRedirect(self, sPath): # create new session with the specified guest user oGuest = db.getItem(serverSettings.guest_account) oNewSession = sessionManager.create(oGuest) self.response = response.HTTPResponse() SESSION_ID = oNewSession.sessionid; ROOT = self.request.getRootUrl() PATH = sPath QS = self.request.getQueryString() # add cookie with sessionid self.response.cookies['_sid'] = SESSION_ID self.response.cookies['_sid']['path'] = '/' if '_nojavascript' in QS: self.response.redirect('%(ROOT)s/{%(SESSION_ID)s}%(PATH)s' % locals()) else: oFile = open(COOKIE_DETECT_PAGE) sBody = oFile.read() oFile.close() self.response.write( sBody % locals() ) self.response.end()
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 """ trans.actions.append( (self.moveTo, (targetId, trans)) ) try: oUser = currentThread().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): raise serverExceptions.TargetContainedInSource if (not(self._isSystem) and bCanMove and iUserRole2 > objectAccess.READER): if not(self.getContentclass() in oTarget.containment): raise serverExceptions.ContainmentError 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 serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
def runAsSystem(self): """Causes the servlet to run under the SYSTEM account. Use this method carefully, since it gives full access rights to the Porupine database. @return: None """ currentThread().session.user = db.getItem('system')
def __get__(self, servlet, servlet_class): policy = db.getItem(self.policyid) user = servlet.session.user if self.userHasPolicy(user, policy): return types.MethodType(self.func, servlet, servlet_class) else: raise serverExceptions.PolicyViolation, "This action is restricted due to policy '%s'" % policy.displayName.value
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(): #open database db.open(dbparams.db_class) #create in-memory session manager sessionManager.open(inMemorySessionManager.SessionManager, 1200) oSystemUser = db.getItem('system') currentThread().session = sessionManager.create(oSystemUser) currentThread().trans = None return db
def on_update(item, new_attr, old_attr, trans): from porcupine import datatypes # remove duplicates new_attr.value = list(sets.Set(new_attr.value)) # get previous value if old_attr: prvValue = sets.Set(old_attr.value) noAccessList = RelatorNEventHandler.getNoAccessIds(old_attr, trans) else: prvValue = sets.Set() noAccessList = [] # get current value currentValue = sets.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 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 __get__(self, servlet, servlet_class): policy = db.getItem(policyid) user = servlet.session.user if self.userHasPolicy(user, policy): return types.MethodType(self.func, servlet, servlet_class) else: raise serverExceptions.PolicyViolation, \ "This action is restricted due to policy '%s'" \ % policy.displayName.value
def update(self, trans): """ Updates the item. @param trans: A valid transaction handle @return: None """ trans.actions.append( (self.update, (trans, )) ) try: oOldItem = db.getItem(self._id, trans) oUser = currentThread().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 serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
def runas_wrapper(*args): user = db.getItem(userid) servlet.originalUser = servlet.session.user servlet.session.user = user try: return self.func(*args) finally: # restore original user unless # the servlet hasn't switched identity if servlet.session.user == user: servlet.session.user = servlet.originalUser
def createGuestSessionAndRedirect(self, sPath): # create new session with the specified guest user oGuest = db.getItem(serverSettings.guest_account) oNewSession = sessionManager.create(oGuest) self.response.redirect( '%s/{%s}%s%s' % ( self.request.getRootUrl() ,oNewSession.sessionid ,sPath ,self.request.getQueryString() ) )
def on_update(item, new_attr, old_attr, trans): # check containment if [obj for obj in new_attr.value if obj.getContentclass() != new_attr.compositeClass]: raise serverExceptions.ContainmentError dctObjects = {} for obj in new_attr.value: obj._containerid = item._id dctObjects[obj._id] = obj new_ids = sets.Set([obj._id for obj in new_attr.value]) # get previous value if old_attr: old_ids = sets.Set(old_attr.value) else: old_ids = sets.Set() # calculate added composites lstAdded = list(new_ids - old_ids) for sID in lstAdded: db.handle_update(dctObjects[sID], None, trans) dctObjects[sID]._isDeleted = False db.putItem(dctObjects[sID], trans) # calculate constant composites lstConstant = list(new_ids & old_ids) for sID in lstConstant: db.handle_update(dctObjects[sID], db.getItem(sID, trans) , trans) db.putItem(dctObjects[sID], trans) # calculate removed composites lstRemoved = list(old_ids - new_ids) for sID in lstRemoved: composite4removal = db.getItem(sID, trans) CompositionEventHandler.removeComposite(composite4removal, trans) new_attr.value = list(new_ids)
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 """ trans.actions.append( (self.appendTo, (parent, trans)) ) try: if type(parent)==str: oParent = db.getItem(parent, trans) else: oParent = parent oUser = currentThread().session.user iUserRole = objectAccess.getAccess(oParent, oUser) if iUserRole == objectAccess.READER: raise serverExceptions.PermissionDenied if not(self.getContentclass() in oParent.containment): raise serverExceptions.ContainmentError # 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 serverExceptions.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) except serverExceptions.DBTransactionIncomplete: trans.retry()
def on_delete(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: CompositionEventHandler.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 isContainedIn(self, itemId): """ 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) return False
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 _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(item, attr, trans, bPermanent): if not item._isDeleted: from porcupine import datatypes if attr.value: if attr.respectsReferences: raise serverExceptions.ReferentialIntegrityError # 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)
def on_delete(item, attr, trans, bPermanent): if not item._isDeleted: from porcupine import datatypes lstValue = attr.value if lstValue and attr.respectsReferences: raise serverExceptions.ReferentialIntegrityError # 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 _copy(self, target, trans, clearRolesInherited=False): oCopy = self.clone() if clearRolesInherited: oCopy.inheritRoles = False oUser = currentThread().session.user oCopy._owner = oUser._id oCopy._created = time.time() oCopy.modifiedBy = oUser.displayName.value oCopy.modified = time.time() oCopy._parentid = target._id db.handle_update(oCopy, None, trans) db.putItem(oCopy, trans) if self.isCollection: lstChildrentIds = self._items.values() + self._subfolders.values() for sId in lstChildrentIds: child = db.getItem(sId, trans) if child and objectAccess.getAccess(child, oUser): child._copy(oCopy, trans) target._addItemReference(oCopy) db.putItem(target, trans)
def getSecurity(self): """Getter of L{security} property @rtype: dict """ return(db.getItem(self._containerid).security)
def getResponse(self): # get request parameters sMethod = self.request.serverVariables['REQUEST_METHOD'] sBrowser = self.request.serverVariables['HTTP_USER_AGENT'] sLang = self.request.getLang() sPath = self.request.serverVariables.setdefault('PATH_INFO', '/') or '/' self.response = response.BaseResponse() servlet = None sAction = None self.request.item = None registration = None try: try: oSession = None cookiesEnabled = True if self.request.cookies.has_key('_sid'): oSession = sessionManager.fetchSession( self.request.cookies['_sid'].value ) else: cookiesEnabled = False oSessionMatch = re.match(SESSIONID, sPath) if oSessionMatch: sPath = sPath.replace(oSessionMatch.group(), '', 1) or '/' oSession = sessionManager.fetchSession(oSessionMatch.group(1)) if oSession: self.session = oSession self.request.serverVariables["AUTH_USER"] = oSession.user.displayName.value oUser = oSession.user if not cookiesEnabled: if not oSession.sessionid in self.request.serverVariables["SCRIPT_NAME"]: self.request.serverVariables["SCRIPT_NAME"] += '/{%s}' % oSession.sessionid else: lstScript = self.request.serverVariables["SCRIPT_NAME"].split('/') self.request.serverVariables["SCRIPT_NAME"] = "/%s/{%s}" %(lstScript[1], oSession.sessionid) else: # invalid sesionid # create new session and redirect self.createGuestSessionAndRedirect(sPath) # else: # self.createGuestSessionAndRedirect(sPath) try: self.request.item = db.getItem(sPath) # db request sItemCC = self.request.item.getContentclass() # get cmd parameter sCmd = self.request.queryString.setdefault('cmd',[''])[0] registration = registrations.storeConfig.getRegistration( sItemCC, sMethod, sCmd, sBrowser, sLang) if not(serverSettings.allow_guests or \ hasattr(oUser, 'authenticate')) and \ serverSettings.login_page != (sPath + \ self.request.getQueryString())[:len(serverSettings.login_page)]: sLoginUrl = self.request.getRootUrl() + serverSettings.login_page self.response.redirect(sLoginUrl) if not registration: raise serverExceptions.NoViewRegistered except serverExceptions.DBItemNotFound: # app request lstPath = sPath.split('/') appName = lstPath[1] # remove blank entry & app name to get the requested path sAppPath = '/'.join(lstPath[2:]) webApp = registrations.apps.setdefault(appName, None) if webApp: registration = webApp.getRegistration( sAppPath, sMethod, sBrowser, sLang) if not registration: raise serverExceptions.ItemNotFound, \ 'The resource "%s" does not exist' % sPath rtype = registration.type if rtype == 2: #servlet servlet = registration.context(serverProxy.proxy, oSession, self.request) servlet.execute() elif rtype == 1: # psp page servlet = psp.PspExecutor(serverProxy.proxy, oSession, self.request) servlet.execute(registration.context) elif rtype == 0: # static file self.response.loadFromFile(registration.context) if registration.encoding: self.response.charset = registration.encoding except serverExceptions.ResponseEnd, e: pass if registration: # do we have caching directive? if registration.max_age: self.response.setExpiration(registration.max_age) # apply post-processing filters dummy = [ filter.apply(self.response, self.request, registration) for filter in registration.filters ]