Esempio n. 1
0
    def view(self, *args, **kwargs):
        """
		Prepares and renders a single entry for viewing.

		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 rendered.

		.. seealso:: :func:`viewSkel`, :func:`canView`, :func:`onItemViewed`

		:returns: The rendered representation of the requested entity.

		: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.
		"""
        if "key" in kwargs:
            key = kwargs["key"]
        elif len(args) >= 1:
            key = args[0]
        else:
            raise errors.NotAcceptable()
        if not len(key):
            raise errors.NotAcceptable()
        skel = self.viewSkel()

        if not skel.fromDB(key):
            raise errors.NotFound()

        if not self.canView(skel):
            raise errors.Unauthorized()

        self.onItemViewed(skel)
        return self.render.view(skel)
Esempio n. 2
0
    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)
Esempio n. 3
0
    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)
Esempio n. 4
0
    def view(self, *args, **kwargs):
        """
		Prepares and renders a single entry for viewing.

		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 rendered.

		.. seealso:: :func:`viewSkel`, :func:`canView`, :func:`onItemViewed`

		:returns: The rendered representation of the requested entity.

		: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.
		"""
        if "key" in kwargs:
            key = kwargs["key"]
        elif len(args) >= 1:
            key = args[0]
        else:
            raise errors.NotAcceptable()
        if not len(key):
            raise errors.NotAcceptable()
        skel = self.viewSkel()
        if key == u"structure":
            # We dump just the structure of that skeleton, including it's default values
            if "canView" in dir(self):
                if not self.canView(skel):
                    raise errors.Unauthorized()
            else:
                if self.listFilter(self.viewSkel().all()) is None:
                    raise errors.Unauthorized()
        else:
            # We return a single entry for viewing
            if "canView" in dir(self):
                if not skel.fromDB(key):
                    raise errors.NotFound()
                if not self.canView(skel):
                    raise errors.Unauthorized()
            else:
                queryObj = self.viewSkel().all().mergeExternalFilter(
                    {"key": key})
                queryObj = self.listFilter(queryObj)  #Access control
                if queryObj is None:
                    raise errors.Unauthorized()
                skel = queryObj.getSkel()
                if not skel:
                    raise errors.NotFound()
            self.onItemViewed(skel)
        return self.render.view(skel)
Esempio n. 5
0
    def list(self, skelType, node, *args, **kwargs):
        """
		List the entries and directories of the given *skelType* under the given *node*.
		Any other supplied parameters are interpreted as filters for the elements displayed.

		.. seealso:: :func:`canList`, :func:`server.db.mergeExternalFilter`

		:param skelType: May either be "node" or "leaf".
		:type skelType: str
		:param node: URL-safe key of the parent.
		:type node: str

		:returns: The rendered list objects for the matching entries.

		:raises: :exc:`server.errors.Unauthorized`, if the current user does not have the required permissions.
		:raises: :exc:`server.errors.NotFound`, if *node* could not be found.
		:raises: :exc:`server.errors.NotAcceptable`, if anything else than "node" or "leaf" is provided to *skelType*.
		"""
        if skelType == "node":
            skel = self.viewNodeSkel()
        elif skelType == "leaf":
            skel = self.viewLeafSkel()
        else:
            raise errors.NotAcceptable()

        if skel is None:
            raise errors.NotAcceptable()

        if not self.canList(skelType, node):
            raise errors.Unauthorized()

        nodeSkel = self.viewNodeSkel()
        if not nodeSkel.fromDB(node):
            raise errors.NotFound()

        query = skel.all()

        if "search" in kwargs and kwargs["search"]:
            query.filter("parentrepo =", str(nodeSkel["key"]))
        else:
            query.filter("parentdir =", str(nodeSkel["key"]))

        query.mergeExternalFilter(kwargs)
        res = query.fetch()

        return self.render.list(res, node=str(nodeSkel["key"]))
Esempio n. 6
0
    def view(self, skelType, key, *args, **kwargs):
        """
		Prepares and renders a single entry for viewing.

		The entry is fetched by its *key* and its *skelType*.
		The function performs several access control checks on the requested entity before it is rendered.

		.. seealso:: :func:`canView`, :func:`onItemViewed`

		:returns: The rendered representation of the requested entity.

		:param skelType: May either be "node" or "leaf".
		:type skelType: str
		:param node: URL-safe key of the parent.
		:type node: str

		:raises: :exc:`server.errors.NotAcceptable`, when an incorrect *skelType* 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.
		"""

        if skelType == "node":
            skel = self.viewNodeSkel()
        elif skelType == "leaf":
            skel = self.viewLeafSkel()
        else:
            raise errors.NotAcceptable()
        if skel is None:
            raise errors.NotAcceptable()
        if not len(key):
            raise errors.NotAcceptable()
        if key == u"structure":
            # We dump just the structure of that skeleton, including it's default values
            if not self.canView(skelType, None):
                raise errors.Unauthorized()
        else:
            # We return a single entry for viewing
            if not skel.fromDB(key):
                raise errors.NotFound()
            if not self.canView(skelType, skel):
                raise errors.Unauthorized()
            self.onItemViewed(skel)
        return self.render.view(skel)
Esempio n. 7
0
    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()
Esempio n. 8
0
    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)
Esempio n. 9
0
    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))
Esempio n. 10
0
    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)
Esempio n. 11
0
	def continueAuthenticationFlow(self, caller, userKey):
		session.current["_mayBeUserKey"] = str(userKey)
		session.current.markChanged()
		for authProvider, secondFactor in self.validAuthenticationMethods:
			if isinstance(caller, authProvider):
				if secondFactor is None:
					# We allow sign-in without a second factor
					return self.authenticateUser(userKey)

				# This Auth-Request was issued from this authenticationProvider
				secondFactorProvider = self.secondFactorProviderByClass(secondFactor)

				if secondFactorProvider.canHandle(userKey):
					# We choose the first second factor provider which claims it can verify that user
					return secondFactorProvider.startProcessing(userKey)

		# Whoops.. This user logged in successfully - but we have no second factor provider willing to confirm it
		raise errors.NotAcceptable("There are no more authentication methods to try") # Sorry...
Esempio n. 12
0
	def add(self, skelType, node, *args, **kwargs):
		# We can't add files directly (they need to be uploaded
		if skelType != "node":
			raise errors.NotAcceptable()
		return super(File, self).add(skelType, node, *args, **kwargs)
Esempio n. 13
0
    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)))
Esempio n. 14
0
 def findAndCall(self, path, *args,
                 **kwargs):  #Do the actual work: process the request
     # Prevent Hash-collision attacks
     assert len(self.request.arguments()) < conf["viur.maxPostParamsCount"]
     # Fill the (surprisingly empty) kwargs dict with named request params
     tmpArgs = dict((k, self.request.get_all(k))
                    for k in self.request.arguments() if k is not None)
     for key in tmpArgs.keys()[:]:
         if len(tmpArgs[key]) == 0:
             continue
         if not key in kwargs.keys():
             if len(tmpArgs[key]) == 1:
                 kwargs[key] = tmpArgs[key][0]
             else:
                 kwargs[key] = tmpArgs[key]
         else:
             if isinstance(kwargs[key], list):
                 kwargs[key] = kwargs[key] + tmpArgs[key]
             else:
                 kwargs[key] = [kwargs[key]] + tmpArgs[key]
     del tmpArgs
     if "self" in kwargs.keys():  #self is reserved for bound methods
         raise errors.BadRequest()
     #Parse the URL
     path = urlparse.urlparse(path).path
     self.pathlist = [
         urlparse.unquote(x) for x in path.strip("/").split("/")
     ]
     caller = conf["viur.mainApp"]
     idx = 0  #Count how may items from *args we'd have consumed (so the rest can go into *args of the called func
     for currpath in self.pathlist:
         if "canAccess" in dir(caller) and not caller.canAccess():
             # We have a canAccess function guarding that object,
             # and it returns False...
             raise (errors.Unauthorized())
         idx += 1
         currpath = currpath.replace("-", "_").replace(".", "_")
         if currpath in dir(caller):
             caller = getattr(caller, currpath)
             if (("exposed" in dir(caller) and caller.exposed) or
                 ("internalExposed" in dir(caller)
                  and caller.internalExposed
                  and self.internalRequest)) and hasattr(
                      caller, '__call__'):
                 args = self.pathlist[idx:] + [
                     x for x in args
                 ]  #Prepend the rest of Path to args
                 break
         elif "index" in dir(caller):
             caller = getattr(caller, "index")
             if (("exposed" in dir(caller) and caller.exposed) or
                 ("internalExposed" in dir(caller)
                  and caller.internalExposed
                  and self.internalRequest)) and hasattr(
                      caller, '__call__'):
                 args = self.pathlist[idx - 1:] + [x for x in args]
                 break
             else:
                 raise (errors.NotFound(
                     "The path %s could not be found" % "/".join([("".join([
                         y for y in x if y.lower() in
                         "0123456789abcdefghijklmnopqrstuvwxyz"
                     ])) for x in self.pathlist[:idx]])))
         else:
             raise (errors.NotFound(
                 "The path %s could not be found" % "/".join([("".join([
                     y for y in x
                     if y.lower() in "0123456789abcdefghijklmnopqrstuvwxyz"
                 ])) for x in self.pathlist[:idx]])))
     if (not callable(caller)
             or ((not "exposed" in dir(caller) or not caller.exposed)) and
         (not "internalExposed" in dir(caller) or not caller.internalExposed
          or not self.internalRequest)):
         if "index" in dir( caller ) \
          and (callable( caller.index ) \
          and ( "exposed" in dir( caller.index ) and caller.index.exposed) \
          or ("internalExposed" in dir( caller.index ) and caller.index.internalExposed and self.internalRequest)):
             caller = caller.index
         else:
             raise (errors.MethodNotAllowed())
     # Check for forceSSL flag
     if not self.internalRequest \
      and "forceSSL" in dir( caller ) \
      and caller.forceSSL \
      and not self.request.host_url.lower().startswith("https://") \
      and not "Development" in os.environ['SERVER_SOFTWARE']:
         raise (errors.PreconditionFailed(
             "You must use SSL to access this ressource!"))
     # Check for forcePost flag
     if "forcePost" in dir(
             caller) and caller.forcePost and not self.isPostRequest:
         raise (errors.MethodNotAllowed(
             "You must use POST to access this ressource!"))
     self.args = []
     for arg in args:
         if isinstance(x, unicode):
             self.args.append(arg)
         else:
             try:
                 self.args.append(arg.decode("UTF-8"))
             except:
                 pass
     self.kwargs = kwargs
     # Check if this request should bypass the caches
     if self.request.headers.get("X-Viur-Disable-Cache"):
         from server import utils
         #No cache requested, check if the current user is allowed to do so
         user = utils.getCurrentUser()
         if user and "root" in user["access"]:
             logging.debug(
                 "Caching disabled by X-Viur-Disable-Cache header")
             self.disableCache = True
     try:
         if (conf["viur.debug.traceExternalCallRouting"]
                 and not self.internalRequest
             ) or conf["viur.debug.traceInternalCallRouting"]:
             logging.debug("Calling %s with args=%s and kwargs=%s" %
                           (str(caller), unicode(args), unicode(kwargs)))
         self.response.out.write(caller(*self.args, **self.kwargs))
     except TypeError as e:
         if self.internalRequest:  #We provide that "service" only for requests originating from outside
             raise
         #Check if the function got too few arguments and raise a NotAcceptable error
         tmpRes = {}
         argsOrder = list(
             caller.__code__.co_varnames)[1:caller.__code__.co_argcount]
         # Map default values in
         reversedArgsOrder = argsOrder[::-1]
         for defaultValue in list(caller.func_defaults or [])[::-1]:
             tmpRes[reversedArgsOrder.pop(0)] = defaultValue
         del reversedArgsOrder
         # Map args in
         setArgs = []  # Store a list of args already set by *args
         for idx in range(0, min(len(args), len(argsOrder))):
             setArgs.append(argsOrder[idx])
             tmpRes[argsOrder[idx]] = args[idx]
         # Last, we map the kwargs in
         for k, v in kwargs.items():
             if k in setArgs:  #This key has already been set by *args
                 raise (
                     errors.NotAcceptable()
                 )  #We reraise that exception as we got duplicate arguments
             tmpRes[k] = v
         # Last check, that every parameter is satisfied:
         if not all([x in tmpRes.keys() for x in argsOrder]):
             raise (errors.NotAcceptable())
         raise
Esempio n. 15
0
    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)