def pwrecover(self, authtoken=None, skey=None, *args, **kwargs): if authtoken: data = securitykey.validate(authtoken) if data and isinstance(data, dict) and "userKey" in data.keys( ) and "password" in data.keys(): skel = self.userModule.editSkel() assert skel.fromDB(data["userKey"]) skel["password"] = data["password"] skel.toDB() return self.userModule.render.view( skel, self.passwordRecoverySuccessTemplate) else: return self.userModule.render.view( None, self.passwordRecoveryInvalidTokenTemplate) else: skel = self.lostPasswordSkel() if len(kwargs) == 0 or not skel.fromClient( kwargs) or not securitykey.validate(skey): return self.userModule.render.passwdRecover( skel, tpl=self.passwordRecoveryTemplate) user = self.userModule.viewSkel().all().filter( "name.idx =", skel["name"].lower()).get() if not user or user[ "status"] < 10: # Unknown user or locked account skel.errors["name"] = _("Unknown user") return self.userModule.render.passwdRecover( skel, tpl=self.passwordRecoveryTemplate) try: if user["changedate"] > (datetime.datetime.now() - datetime.timedelta(days=1)): # This user probably has already requested a password reset # within the last 24 hrss return self.userModule.render.view( skel, self.passwordRecoveryAlreadySendTemplate) except AttributeError: #Some newly generated user-objects dont have such a changedate yet pass user["changedate"] = datetime.datetime.now() db.Put(user) userSkel = self.userModule.viewSkel().ensureIsCloned() assert userSkel.fromDB(user.key()) userSkel.skey = baseBone(descr="Skey") userSkel["skey"] = securitykey.create(60 * 60 * 24, userKey=str(user.key()), password=skel["password"]) utils.sendEMail([userSkel["name"]], self.userModule.passwordRecoveryMail, userSkel) return self.userModule.render.view( {}, self.passwordRecoveryInstuctionsSendTemplate)
def getUploadURL( self, *args, **kwargs ): skey = kwargs.get("skey", "") if not self.canAdd("leaf", None): raise errors.Forbidden() if not securitykey.validate(skey): raise errors.PreconditionFailed() return blobstore.create_upload_url("%s/upload" % self.modulePath)
def setIndex(self, item, index, skey, *args, **kwargs): """ Changes the order of the elements in the current level by changing the index of *item*. .. seealso:: :func:`canSetIndex` :param item: URL-safe key of the item which index should be changed. :type item: str :param index: New index for this item. This value must be cast-able to float. :type index: str :returns: A rendered success result generated by the default renderer. :raises: :exc:`server.errors.NotFound`, when no entry with the given *key* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() if not self.canSetIndex(item, index): raise errors.Unauthorized() fromItem = db.Get(item) fromItem["sortindex"] = float(index) db.Put(fromItem) skel = self.editSkel() assert skel.fromDB(item) self.onItemSetIndex(skel) self.onItemChanged(skel) return self.render.setIndexSuccess(obj=fromItem)
def triggerSendNewsletter(self, key, skey, *args, **kwargs): if not securitykey.validate(skey): raise errors.PreconditionFailed() user = utils.getCurrentUser() if not (user and "root" in user["access"]): raise errors.Unauthorized() skel = self.viewSkel() if not skel.fromDB(key): raise errors.NotFound() if skel["triggered"] or skel["sent"]: raise errors.Forbidden("This newsletter was already sent.") try: setStatus(skel["key"], values={ "triggered": True, "triggereddate": datetime.datetime.now(), }, check={ "triggered": False, "sent": False }) except Exception as e: logging.exception(e) raise errors.Forbidden() self.fetchNewsletterRecipients(str(skel["key"])) return json.dumps("OKAY")
def delete(self, key, skey, *args, **kwargs): """ Delete an entry and all its children. The function runs several access control checks on the data before it is deleted. .. seealso:: :func:`canDelete`, :func:`editSkel`, :func:`onItemDeleted` :param key: URL-safe key of the entry to be deleted. :type key: str :returns: The rendered, deleted object of the entry. :raises: :exc:`server.errors.NotFound`, when no entry with the given *key* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() skel = self.editSkel() if not skel.fromDB(key): raise errors.NotFound() if not self.canDelete(skel): raise errors.Unauthorized() self.deleteRecursive(key) skel.delete() self.onItemDeleted(skel) self.onItemChanged(skel) return self.render.deleteSuccess(skel)
def index(self, *args, **kwargs): if not self.canUse(): raise errors.Forbidden() #Unauthorized skel = self.mailSkel() if len(kwargs) == 0: return self.render.add(skel=skel, failed=False) if not skel.fromClient(kwargs) or not "skey" in kwargs.keys(): return self.render.add(skel=skel, failed=True) if not securitykey.validate(kwargs["skey"]): raise errors.PreconditionFailed() # Allow bones to perform outstanding "magic" operations before sending the mail for key, _bone in skel.items(): if isinstance(_bone, baseBone): _bone.performMagic(skel.valuesCache, key, isAdd=True) # Get recipients rcpts = self.getRcpts(skel) # Get additional options for sendEMail opts = self.getOptions(skel) if not isinstance(opts, dict): opts = {} # Send the email! utils.sendEMail(rcpts, self.mailTemplate, skel, **opts) self.onItemAdded(skel) return self.render.addItemSuccess(skel)
def login(self, name=None, password=None, skey="", *args, **kwargs): if self.userModule.getCurrentUser(): #Were already logged in return self.userModule.render.loginSucceeded() if not name or not password or not securitykey.validate(skey): return self.userModule.render.login(self.loginSkel()) query = db.Query(self.userModule.viewSkel().kindName) res = query.filter("name.idx >=", name.lower()).get() if res is None: res = {"password": "", "status": 0, "name": "", "name.idx": ""} if "password_salt" in res.keys(): # Its the new, more secure passwd passwd = pbkdf2(password[:conf["viur.maxPasswordLength"]], res["password_salt"]) else: passwd = sha512(password.encode("UTF-8") + conf["viur.salt"]).hexdigest() isOkay = True # We do this exactly that way to avoid timing attacks # Check if the username matches storedUserName = res.get("name.idx", "") if len(storedUserName) != len(name.lower()): isOkay = False else: for x, y in izip(storedUserName, name.lower()): if x != y: isOkay = False # Check if the password matches storedPasswordHash = res.get("password", "") if len(storedPasswordHash) != len(passwd): isOkay = False else: for x, y in izip(storedPasswordHash, passwd): if x != y: isOkay = False # Verify that this account isn't blocked if res["status"] < 10: isOkay = False if not isOkay: skel = self.loginSkel() skel.fromClient({"name": name, "nomissing": "1"}) return self.userModule.render.login(skel, loginFailed=True) else: if not "password_salt" in res.keys( ): #Update the password to the new, more secure format res["password_salt"] = utils.generateRandomString(13) res["password"] = pbkdf2( password[:conf["viur.maxPasswordLength"]], res["password_salt"]) db.Put(res) return self.userModule.continueAuthenticationFlow(self, res.key())
def logout(self, skey="", *args, **kwargs): """ Implements the logout action. It also terminates the current session (all keys not listed in viur.session.persistentFieldsOnLogout will be lost). """ user = session.current.get("user") if not user: raise errors.Unauthorized() if not securitykey.validate(skey): raise errors.PreconditionFailed() self.onLogout(user) oldSession = {k: v for k, v in session.current.items() } # Store all items in the current session session.current.reset() # Copy the persistent fields over for k in conf["viur.session.persistentFieldsOnLogout"]: if k in oldSession: session.current[k] = oldSession[k] del oldSession return self.render.logoutSuccess()
def edit(self, *args, **kwargs): """ Modify an existing entry, and render the entry, eventually with error notes on incorrect data. Data is taken by any other arguments in *kwargs*. The entry is fetched by its entity key, which either is provided via *kwargs["key"]*, or as the first parameter in *args*. The function performs several access control checks on the requested entity before it is modified. .. seealso:: :func:`editSkel`, :func:`onItemEdited`, :func:`canEdit` :returns: The rendered, edited object of the entry, eventually with error hints. :raises: :exc:`server.errors.NotAcceptable`, when no *key* is provided. :raises: :exc:`server.errors.NotFound`, when no entry with the given *key* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" if "key" in kwargs: key = kwargs["key"] elif len(args) == 1: key = args[0] else: raise errors.NotAcceptable() skel = self.editSkel() if not skel.fromDB(key): raise errors.NotAcceptable() if not self.canEdit(skel): raise errors.Unauthorized() if (len(kwargs) == 0 # no data supplied or skey == "" # no security key or not request.current.get(). isPostRequest # failure if not using POST-method or not skel.fromClient( kwargs) # failure on reading into the bones or ("bounce" in list(kwargs.keys()) and kwargs["bounce"] == "1" ) # review before changing ): # render the skeleton in the version it could as far as it could be read. return self.render.edit(skel) if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() skel.toDB() # write it! self.onItemEdited(skel) return self.render.editItemSuccess(skel)
def reparent(self, item, dest, skey, *args, **kwargs): """ Moves an entry *item* (and everything beneath it) to another parent-node *dest*. .. seealso:: :func:`canReparent` :param item: URL-safe key of the item which will be moved. :type item: str :param dest: URL-safe key of the new parent for this item. :type dest: str :returns: A rendered success result generated by the default renderer. :raises: :exc:`server.errors.NotFound`, when no entry with the given *id* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() if not self.canReparent(item, dest): raise errors.Unauthorized() if not self.isValidParent(dest) or item == dest: raise errors.NotAcceptable() ## Test for recursion isValid = False currLevel = db.Get(dest) for x in range(0, 99): if str(currLevel.key()) == item: break if currLevel.key().kind( ) == self.viewSkel().kindName + "_rootNode": # We reached a rootNode isValid = True break currLevel = db.Get(currLevel["parententry"]) if not isValid: raise errors.NotAcceptable() ## Update entry fromItem = db.Get(item) fromItem["parententry"] = dest fromItem["parentrepo"] = str(self.getRootNode(dest).key()) db.Put(fromItem) skel = self.editSkel() assert skel.fromDB(item) self.onItemReparent(skel) self.onItemChanged(skel) return self.render.reparentSuccess(obj=fromItem)
def setSortIndex(self, key, index, skey, *args, **kwargs): if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() skel = self.editSkel() if not skel.fromDB(key): raise errors.NotFound() skel["sortindex"] = float(index) skel.toDB(clearUpdateTag=True) return self.render.renderEntry(skel, "setSortIndexSuccess")
def verify(self, skey, *args, **kwargs ): data = securitykey.validate(skey) skel = self.userModule.baseSkel() if not data or not isinstance(data, dict) or not "userKey" in data or not skel.fromDB(data["userKey"]): return self.userModule.render.view(None, self.verifyFailedTemplate) if self.registrationAdminVerificationRequired: skel["status"] = 2 else: skel["status"] = 10 skel.toDB() return self.userModule.render.view(skel, self.verifySuccessTemplate)
def clone(self, fromRepo, toRepo, fromParent=None, toParent=None, *args, **kwargs): """ Clones a hierarchy recursively. This function only initiates the cloning process, which is performed in the background. It states only a successful result when the clone action has been correctly initiated. :param fromRepo: URL-safe key of the key to the repository (=root-node Key) to clone from. :type fromRepo: str :param toRepo: URL-safe key of the key to the repository (=root-node Key) to clone to. :type toRepo: str :param fromParent: URL-safe key of the parent to clone from; for root nodes, this is equal \ to fromRepo, and can be omitted. :type fromParent: str :param toParent: URL-safe key of the parent to clone to; for root nodes, this is equal to \ toRepo, and can be omitted. :type toParent: str :returns: A rendered success result generated by the default renderer. :raises: :exc:`server.errors.NotAcceptable`, when no valid *parent* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" if fromParent is None: fromParent = fromRepo if toParent is None: toParent = toRepo if not (self.isValidParent(fromParent) and self.isValidParent(toParent)): # Ensure the parents exists raise errors.NotAcceptable() if not self.canAdd(toParent): raise errors.Unauthorized() if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() self._clone(fromRepo, toRepo, fromParent, toParent) return self.render.cloneSuccess()
def edit(self, skelType, key, skey="", *args, **kwargs): """ Modify an existing entry, and render the entry, eventually with error notes on incorrect data. Data is taken by any other arguments in *kwargs*. The function performs several access control checks on the requested entity before it is added. .. seealso:: :func:`onItemAdded`, :func:`canEdit` :param skelType: Defines the type of the entry that should be modified and may either be "node" or "leaf". :type skelType: str :param key: URL-safe key of the item to be edited. :type key: str :returns: The rendered, modified object of the entry, eventually with error hints. :raises: :exc:`server.errors.NotAcceptable`, when no valid *skelType* was provided. :raises: :exc:`server.errors.NotFound`, when no valid *node* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if skelType == "node": skel = self.editNodeSkel() elif skelType == "leaf": skel = self.editLeafSkel() else: raise errors.NotAcceptable() if not skel.fromDB(key): raise errors.NotFound() if not self.canEdit(skelType, skel): raise errors.Unauthorized() if (len(kwargs) == 0 # no data supplied or skey == "" # no security key #or not request.current.get().isPostRequest fixme: POST-method check missing? # failure if not using POST-method or not skel.fromClient( kwargs) # failure on reading into the bones or ("bounce" in kwargs and kwargs["bounce"] == "1" ) # review before adding ): return self.render.edit(skel) if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() skel.toDB() self.onItemEdited(skel) return self.render.editItemSuccess(skel)
def markCanceled(self, key, skey, *args, **kwargs): """ Exposed function for marking an order as cancelled. :param key: The key of the order to be marked. :type key: str """ if not self.canEdit(key): raise errors.Unauthorized() if not securitykey.validate(skey): raise errors.PreconditionFailed() self.setCanceled(key) return "OKAY"
def delete(self, skelType, key, *args, **kwargs): """ Deletes an entry or an directory (including its contents). The function runs several access control checks on the data before it is deleted. .. seealso:: :func:`canDelete`, :func:`onItemDeleted` :param skelType: Defines the type of the entry that should be deleted and may either be "node" or "leaf". :type skelType: str :param key: URL-safe key of the item to be deleted. :type key: str :returns: The rendered, deleted object of the entry. :raises: :exc:`server.errors.NotFound`, when no entry with the given *key* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if skelType == "node": skel = self.viewNodeSkel() elif skelType == "leaf": skel = self.viewLeafSkel() else: raise errors.NotAcceptable() if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" if not skel.fromDB(key): raise errors.NotFound() if not self.canDelete(skelType, skel): raise errors.Unauthorized() if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() if type == "leaf": skel.delete() else: self.deleteRecursive(key) skel.delete() self.onItemDeleted(skel) return (self.render.deleteSuccess(skel, skelType=skelType))
def edit(self, *args, **kwargs): """ Modify the existing entry, and render the entry, eventually with error notes on incorrect data. The entry is fetched by its entity key, which either is provided via *kwargs["key"]*, or as the first parameter in *args*. The function performs several access control checks on the singleton's entity before it is modified. .. seealso:: :func:`editSkel`, :func:`onItemEdited`, :func:`canEdit` :returns: The rendered, edited object of the entry, eventually with error hints. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" skel = self.editSkel() if not self.canEdit(): raise errors.Unauthorized() key = db.Key.from_path(self.editSkel().kindName, self.getKey()) if not skel.fromDB( str(key)): #Its not there yet; we need to set the key again skel["key"] = str(key) if (len(kwargs) == 0 # no data supplied or skey == "" #no skey provided or not skel.fromClient( kwargs) # failure on reading into the bones or ("bounce" in kwargs and kwargs["bounce"] == "1")): # review before changing return self.render.edit(skel) if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() skel.toDB() self.onItemEdited(skel) return self.render.editItemSuccess(skel)
def add(self, parent, *args, **kwargs): """ Add a new entry with the given parent, and render the entry, eventually with error notes on incorrect data. Data is taken by any other arguments in *kwargs*. The function performs several access control checks on the requested entity before it is added. .. seealso:: :func:`addSkel`, :func:`onItemAdded`, :func:`canAdd` :param parent: URL-safe key of the parent. :type parent: str :returns: The rendered, added object of the entry, eventually with error hints. :raises: :exc:`server.errors.NotAcceptable`, when no valid *parent* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" if not self.isValidParent(parent): # Ensure the parent exists raise errors.NotAcceptable() if not self.canAdd(parent): raise errors.Unauthorized() skel = self.addSkel() if (len(kwargs) == 0 or skey == "" or not request.current.get().isPostRequest or not skel.fromClient(kwargs) or ("bounce" in kwargs and kwargs["bounce"] == "1")): return self.render.add(skel) if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() skel["parententry"] = str(parent) skel["parentrepo"] = str(self.getRootNode(parent).key()) key = skel.toDB() self.onItemAdded(skel) self.onItemChanged(skel) return self.render.addItemSuccess(skel)
def add(self, *args, **kwargs): """ Add a new entry, and render the entry, eventually with error notes on incorrect data. Data is taken by any other arguments in *kwargs*. The function performs several access control checks on the requested entity before it is added. .. seealso:: :func:`addSkel`, :func:`onItemAdded`, :func:`canAdd` :returns: The rendered, added object of the entry, eventually with error hints. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" if not self.canAdd(): raise errors.Unauthorized() skel = self.addSkel() if (len(kwargs) == 0 # no data supplied or skey == "" # no skey supplied or not request.current.get(). isPostRequest # failure if not using POST-method or not skel.fromClient( kwargs) # failure on reading into the bones or ("bounce" in list(kwargs.keys()) and kwargs["bounce"] == "1" ) # review before adding ): # render the skeleton in the version it could as far as it could be read. return self.render.add(skel) if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() skel.toDB() self.onItemAdded(skel) return self.render.addItemSuccess(skel)
def add(self, *args, **kwargs): """ Allows guests to register a new account if self.registrationEnabled is set to true .. seealso:: :func:`addSkel`, :func:`onItemAdded`, :func:`canAdd` :returns: The rendered, added object of the entry, eventually with error hints. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" if not self.canAdd(): raise errors.Unauthorized() skel = self.addSkel() if (len(kwargs) == 0 # no data supplied or skey == "" # no skey supplied or not request.current.get(). isPostRequest # bail out if not using POST-method or not skel.fromClient( kwargs) # failure on reading into the bones or ("bounce" in list(kwargs.keys()) and kwargs["bounce"] == "1")): # review before adding # render the skeleton in the version it could as far as it could be read. return self.userModule.render.add(skel) if not securitykey.validate(skey): raise errors.PreconditionFailed() skel.toDB() if self.registrationEmailVerificationRequired and str( skel["status"]) == "1": # The user will have to verify his email-address. Create an skey and send it to his address skey = securitykey.create(duration=60 * 60 * 24 * 7, userKey=str(skel["key"]), name=skel["name"]) skel.skey = baseBone(descr="Skey") skel["skey"] = skey utils.sendEMail([skel["name"]], self.userModule.verifyEmailAddressMail, skel) self.userModule.onItemAdded( skel) # Call onItemAdded on our parent user module return self.userModule.render.addItemSuccess(skel)
def otp(self, otptoken=None, skey=None, *args, **kwargs): token = session.current.get("_otp_user") if not token: raise errors.Forbidden() if otptoken is None: self.userModule.render.edit(self.otpSkel()) if not securitykey.validate(skey): raise errors.PreconditionFailed() if token["failures"] > 3: raise errors.Forbidden( "Maximum amount of authentication retries exceeded") if len(token["otpkey"]) % 2 == 1: raise errors.PreconditionFailed( "The otp secret stored for this user is invalid (uneven length)" ) validTokens = self.generateOtps(token["otpkey"], token["otptimedrift"]) try: otptoken = int(otptoken) except: # We got a non-numeric token - this cant be correct self.userModule.render.edit(self.otpSkel(), tpl=self.otpTemplate) if otptoken in validTokens: userKey = session.current["_otp_user"]["uid"] del session.current["_otp_user"] session.current.markChanged() idx = validTokens.index(int(otptoken)) if abs(idx - self.windowSize) > 2: # The time-drift accumulates to more than 2 minutes, update our # clock-drift value accordingly self.updateTimeDrift(userKey, idx - self.windowSize) return self.userModule.secondFactorSucceeded(self, userKey) else: token["failures"] += 1 session.current["_otp_user"] = token session.current.markChanged() return self.userModule.render.edit(self.otpSkel(), loginFailed=True, tpl=self.otpTemplate)
def preview( self, skey, *args, **kwargs ): """ Renders data for the entry, without reading it from the database. This function allows to preview the entry without writing it to the database. Any entity values are provided via *kwargs*. The function uses the viewTemplate of the application. :returns: The rendered representation of the supplied data. """ if not self.canPreview(): raise errors.Unauthorized() if not securitykey.validate( skey ): raise errors.PreconditionFailed() skel = self.viewSkel() skel.fromClient( kwargs ) return self.render.view( skel )
def execute(self, taskID, *args, **kwargs ): """Queues a specific task for the next maintenance run""" global _callableTasks from server import securitykey if taskID in _callableTasks.keys(): task = _callableTasks[ taskID ]() else: return if not task.canCall(): raise errors.Unauthorized() skel = task.dataSkel() if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" if len(kwargs)==0 or skey=="" or not skel.fromClient(kwargs) or ("bounce" in list(kwargs.keys()) and kwargs["bounce"]=="1"): return self.render.add( skel ) if not securitykey.validate(skey): raise errors.PreconditionFailed() task.execute( **skel.getValues() ) return self.render.addItemSuccess( skel )
def move(self, skelType, key, destNode, *args, **kwargs): """ Move a node (including its contents) or a leaf to another node. .. seealso:: :func:`canMove` :param skelType: Defines the type of the entry that should be moved and may either be "node" or "leaf". :type skelType: str :param key: URL-safe key of the item to be moved. :type key: str :param destNode: URL-safe key of the destination node, which must be a node. :type destNode: str :returns: The rendered, edited object of the entry. :raises: :exc:`server.errors.NotFound`, when no entry with the given *key* was found. :raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions. :raises: :exc:`server.errors.PreconditionFailed`, if the *skey* could not be verified. """ if skelType == "node": srcSkel = self.editNodeSkel() elif skelType == "leaf": srcSkel = self.editLeafSkel() else: raise errors.NotAcceptable() if "skey" in kwargs: skey = kwargs["skey"] else: skey = "" destSkel = self.editNodeSkel() if not self.canMove(skelType, key, destNode): raise errors.Unauthorized() if key == destNode: # Cannot move a node into itself raise errors.NotAcceptable() ## Test for recursion isValid = False currLevel = db.Get(destNode) for x in range(0, 99): if str(currLevel.key()) == key: break if "rootNode" in currLevel and currLevel["rootNode"] == 1: #We reached a rootNode isValid = True break currLevel = db.Get(currLevel["parentdir"]) if not isValid: raise errors.NotAcceptable() #Test if key points to a rootNone tmp = db.Get(key) if "rootNode" in tmp and tmp["rootNode"] == 1: #Cant move a rootNode away.. raise errors.NotAcceptable() if not srcSkel.fromDB(key) or not destSkel.fromDB(destNode): # Could not find one of the entities raise errors.NotFound() if not securitykey.validate(skey, acceptSessionKey=True): raise errors.PreconditionFailed() srcSkel["parentdir"] = str(destNode) srcSkel["parentrepo"] = destSkel[ "parentrepo"] #Fixme: Need to recursive fixing to parentrepo? srcSkel.toDB() self.updateParentRepo(key, destSkel["parentrepo"]) return self.render.editItemSuccess(srcSkel, skelType=skelType, action="move", destNode=destSkel)
def setLanguage(lang, skey): if not securitykey.validate(skey): return if lang in conf["viur.availableLanguages"]: session.current.setLanguage(lang)
def checkout(self, step=None, key=None, skey=None, *args, **kwargs): """ Performs the checkout process trough the state machine provided by self.steps. :param step: The current step index, None for beginning a new checkout :param key: Key of the current checkout :param skey: Server security key :return: Returns the rendered template or throws redirection exceptions. """ myKindName = self.viewSkel().kindName if step is None: logging.info("Starting new checkout process") billObj = db.Entity(myKindName) billObj["idx"] = "0000000" for state in self.states: billObj["state_%s" % state] = "0" db.Put(billObj) key = str(billObj.key()) #Copy the Cart if "amountSkel" in dir(self): cart = session.current.get("cart_products") or {} s = self.amountSkel() products = [] for prod, atts in cart.items(): for i in range(0, atts["amount"]): products.append(str(prod)) s.fromClient({"product": products}) s.toDB() session.current["order_" + myKindName] = { "key": str(key), "completedSteps": [] } session.current.markChanged() raise errors.Redirect("?step=0&key=%s" % str(key)) elif key: try: orderKey = db.Key(key) step = int(step) assert (step >= 0) assert (step < len(self.steps)) except: raise errors.NotAcceptable() sessionInfo = session.current.get("order_" + myKindName) if not sessionInfo or not sessionInfo.get("key") == str(orderKey): raise errors.Unauthorized() if step in sessionInfo["completedSteps"]: session.current["order_" + myKindName]["completedSteps"] = [ x for x in sessionInfo["completedSteps"] if x < step ] session.current.markChanged() #Make sure that no steps can be skipped if step != 0 and not step - 1 in sessionInfo["completedSteps"]: raise errors.Redirect("?step=0&key=%s" % str(str(orderKey))) currentStep = self.steps[step] if "preHandler" in currentStep.keys(): try: if isinstance(currentStep["preHandler"], list): for handler in currentStep["preHandler"]: handler(self, step, str(orderKey), *args, **kwargs) else: currentStep["preHandler"](self, step, str(orderKey), refkwargs=kwargs, *args, **kwargs) except SkipStepException: session.current["order_" + myKindName]["completedSteps"].append(step) session.current.markChanged() raise errors.Redirect("?step=%s&key=%s" % (str(step + 1), str(orderKey))) except ReturnHtmlException as e: return (e.html) if "requiresSecurityKey" in currentStep and currentStep[ "requiresSecurityKey"]: if not securitykey.validate(skey): raise errors.PreconditionFailed() pass if "mainHandler" in currentStep: if currentStep["mainHandler"]["action"] == "edit": skel = self.getSkelByName( currentStep["mainHandler"]["skeleton"], str(orderKey)) skel.fromDB(str(orderKey)) if not len(kwargs.keys()) or not skel.fromClient(kwargs): return (self.render.edit( skel, tpl=currentStep["mainHandler"]["template"], step=step)) skel.toDB() if currentStep["mainHandler"]["action"] == "view": if not "complete" in kwargs or not kwargs[ "complete"] == u"1": skel = self.getSkelByName( currentStep["mainHandler"]["skeleton"], str(orderKey)) skel.fromDB(str(orderKey)) return (self.render.view( skel, tpl=currentStep["mainHandler"]["template"], step=step)) elif currentStep["mainHandler"]["action"] == "function": res = currentStep["mainHandler"]["function"](self, step, str(orderKey), *args, **kwargs) if res: return res if "postHandler" in currentStep: currentStep["postHandler"](self, step, str(orderKey), *args, **kwargs) session.current["order_" + myKindName]["completedSteps"].append(step) session.current.markChanged() logging.info("next ?step=%s&key=%s" % (str(step + 1), str(orderKey))) raise errors.Redirect("?step=%s&key=%s" % (str(step + 1), str(orderKey)))