Example #1
0
 def storeEntry(self, e, key):
     if not self._checkKey(key, export=False):
         raise errors.Forbidden()
     entry = pickle.loads(e)
     for k in list(entry.keys())[:]:
         if isinstance(entry[k], str):
             entry[k] = entry[k].decode("UTF-8")
     if "key" in entry.keys():
         key = db.Key(encoded=entry["key"])
     elif "id" in entry.keys():
         key = db.Key(encoded=entry["id"])
     else:
         raise AttributeError()
     logging.error(key.kind())
     logging.error(key.id())
     logging.error(key.name())
     dbEntry = db.Entity(kind=key.kind(),
                         parent=key.parent(),
                         id=key.id(),
                         _app=key.app(),
                         name=key.name())  #maybe some more fixes here ?
     for k in entry.keys():
         if k != "key":
             val = entry[k]
             #if isinstance(val, dict) or isinstance(val, list):
             #	val = pickle.dumps( val )
             dbEntry[k] = val
     if dbEntry.key().id():
         # Ensure the Datastore knows that it's id is in use
         datastore._GetConnection()._reserve_keys([dbEntry.key()])
     db.Put(dbEntry)
Example #2
0
 def setKeyTxn(orderKey, idx):
     """Assigns the new order to the given order"""
     dbObj = db.Get(db.Key(orderKey))
     if not dbObj:
         return
     dbObj["idx"] = idx
     db.Put(dbObj)
Example #3
0
 def sofortStatus(self, *args, **kwargs):
     sortOrder = [
         "transaction", "user_id", "project_id", "sender_holder",
         "sender_account_number", "sender_bank_code", "sender_bank_name",
         "sender_bank_bic", "sender_iban", "sender_country_id",
         "recipient_holder", "recipient_account_number",
         "recipient_bank_code", "recipient_bank_name", "recipient_bank_bic",
         "recipient_iban", "recipient_country_id",
         "international_transaction", "amount", "currency_id", "reason_1",
         "reason_2", "security_criteria", "user_variable_0",
         "user_variable_1", "user_variable_2", "user_variable_3",
         "user_variable_4", "user_variable_5", "created"
     ]
     hashstr = "|".join([kwargs[key] for key in sortOrder] +
                        [conf["sofort"]["notificationpassword"]])
     if hashlib.sha512(
             hashstr.encode("utf-8")).hexdigest() != kwargs["hash"]:
         logging.error(
             "RECIVED INVALID HASH FOR sofort (%s!=%s)" % (hashlib.sha512(
                 hashstr.encode("utf-8")).hexdigest(), kwargs["hash"]))
         return ("INVALID HASH")
     order = db.Get(db.Key(kwargs["user_variable_0"]))
     if not order:
         logging.error("RECIVED UNKNOWN ORDER by sofort (%s)" %
                       (kwargs["user_variable_0"]))
         return ("UNKNOWN ORDER")
     if ("%.2f" % order["price"]) != kwargs["amount"]:
         logging.error("RECIVED INVALID AMOUNT PAYED sofort (%s!=%s)" %
                       (order["price"], kwargs["amount"]))
         return ("INVALID AMOUNT")
     self.orderHandler.setPayed(kwargs["user_variable_0"])
     return ("OKAY")
Example #4
0
    def storeEntry2(self, e, key):
        if not self._checkKey(key, export=False):
            raise errors.Forbidden()
        entry = pickle.loads(e.decode("HEX"))
        for k in list(entry.keys())[:]:
            if isinstance(entry[k], str):
                entry[k] = entry[k].decode("UTF-8")
        key = db.Key(encoded=utils.normalizeKey(entry["key"]))

        logging.info(key.kind())
        logging.info(key.id())
        logging.info(key.name())
        dbEntry = db.Entity(kind=key.kind(),
                            parent=key.parent(),
                            id=key.id(),
                            name=key.name())  #maybe some more fixes here ?
        for k in entry.keys():
            if k != "key":
                val = entry[k]
                dbEntry[k] = val
        db.Put(dbEntry)
        try:
            skel = skeletonByKind(key.kind())()
        except:
            logging.error("Unknown Skeleton - skipping")
        skel.fromDB(str(dbEntry.key()))
        skel.refresh()
        skel.toDB(clearUpdateTag=True)
Example #5
0
    def assignBillSequence(self, orderKey):
        """
			Assigns an unique order-order to the given order.
		"""
        def getKeyTxn(kindName, orderKey):
            """Generates and returns a new, unique Key"""
            seqObj = db.GetOrInsert(kindName,
                                    "viur_bill_sequences",
                                    count=1000)
            idx = seqObj["count"]
            seqObj["count"] += 1
            db.Put(seqObj)
            return str(idx)

        def setKeyTxn(orderKey, idx):
            """Assigns the new order to the given order"""
            dbObj = db.Get(db.Key(orderKey))
            if not dbObj:
                return
            dbObj["idx"] = idx
            db.Put(dbObj)

        dbObj = db.Get(db.Key(orderKey))
        if not dbObj:
            return

        idx = db.RunInTransaction(getKeyTxn,
                                  self.viewSkel().kindName, orderKey)
        db.RunInTransaction(setKeyTxn, orderKey, idx)
        self.billSequenceAvailable(orderKey)
Example #6
0
        def txn(orderKey, state, removeState):
            dbObj = db.Get(db.Key(orderKey))
            if not dbObj:
                return

            dbObj["state_%s" % state] = "1" if not removeState else "0"
            dbObj["changedate"] = datetime.now()
            db.Put(dbObj)
Example #7
0
 def txnDelete(key, skel):
     dbObj = db.Get(db.Key(
         key))  # Fetch the raw object as we might have to clear locks
     for boneName, bone in skel.items():
         # Ensure that we delete any value-lock objects remaining for this entry
         if bone.unique:
             try:
                 logging.error("x1")
                 logging.error(dbObj.keys())
                 if "%s.uniqueIndexValue" % boneName in dbObj.keys():
                     logging.error("x2")
                     db.Delete(
                         db.Key.from_path(
                             "%s_%s_uniquePropertyIndex" %
                             (skel.kindName, boneName),
                             dbObj["%s.uniqueIndexValue" % boneName]))
             except db.EntityNotFoundError:
                 raise
                 pass
     # Delete the blob-key lock object
     try:
         lockObj = db.Get(db.Key.from_path("viur-blob-locks", str(key)))
     except:
         lockObj = None
     if lockObj is not None:
         if lockObj["old_blob_references"] is None and lockObj[
                 "active_blob_references"] is None:
             db.Delete(lockObj)  # Nothing to do here
         else:
             if lockObj["old_blob_references"] is None:
                 # No old stale entries, move active_blob_references -> old_blob_references
                 lockObj["old_blob_references"] = lockObj[
                     "active_blob_references"]
             elif lockObj["active_blob_references"] is not None:
                 # Append the current references to the list of old & stale references
                 lockObj["old_blob_references"] += lockObj[
                     "active_blob_references"]
             lockObj["active_blob_references"] = [
             ]  # There are no active ones left
             lockObj["is_stale"] = True
             lockObj["has_old_blob_references"] = True
             db.Put(lockObj)
     db.Delete(db.Key(key))
Example #8
0
def normalizeKey(key):
    """
		Normalizes a datastore key (replacing _application with the current one)

		:param key: Key to be normalized.

		:return: Normalized key in string representation.
	"""
    if key is None:
        return None

    key = db.Key(encoded=str(key))

    if key.parent():
        parent = db.Key(encoded=normalizeKey(key.parent()))
    else:
        parent = None

    return str(db.Key.from_path(key.kind(), key.id_or_name(), parent=parent))
Example #9
0
 def fromShortKey(key):
     if isinstance(key, basestring):
         try:
             key = db.Key(encoded=key)
         except:
             key = unicode(key)
             if key.isdigit():
                 key = long(key)
             key = db.Key.from_path(skel.kindName, key)
     assert isinstance(key, db.Key)
     return (key)
Example #10
0
 def getSofortURL(self, orderID):
     order = db.Get(db.Key(orderID))
     hashstr = "%s|%s|||||%.2f|EUR|%s||%s||||||%s" % (
         conf["sofort"]["userid"], conf["sofort"]["projectid"],
         float(order["price"]), str(order.key()), str(
             order.key()), conf["sofort"]["projectpassword"])
     hash = hashlib.sha512(hashstr.encode("UTF-8")).hexdigest()
     returnURL = "https://www.sofortueberweisung.de/payment/start?user_id=%s&project_id=%s&amount=%.2f&currency_id=EUR&reason_1=%s&user_variable_0=%s&hash=%s" % (
         conf["sofort"]["userid"], conf["sofort"]["projectid"],
         float(order["price"]), str(order.key()), str(order.key()), hash)
     return (returnURL)
Example #11
0
    def _rewriteQuery(self, name, skel, dbFilter, rawFilter):
        """
			Rewrites a datastore query to operate on "viur-relations" instead of the original kind.
			This is needed to perform relational queries on n:m relations.
		"""
        origFilter = dbFilter.datastoreQuery
        origSortOrders = dbFilter.getOrders()
        if isinstance(origFilter, db.MultiQuery):
            raise NotImplementedError(
                "Doing a relational Query with multiple=True and \"IN or !=\"-filters is currently unsupported!"
            )
        dbFilter.datastoreQuery = type(dbFilter.datastoreQuery)(
            "viur-relations")  #skel.kindName+"_"+self.kind+"_"+name
        dbFilter.filter("viur_src_kind =", skel.kindName)
        dbFilter.filter("viur_dest_kind =", self.kind)
        dbFilter.filter("viur_src_property", name)
        if dbFilter._origCursor:  #Merge the cursor in again (if any)
            dbFilter.cursor(dbFilter._origCursor)
        if origFilter:
            for k, v in origFilter.items():  #Merge old filters in
                #Ensure that all non-relational-filters are in parentKeys
                if k == "__key__":
                    # We must process the key-property separately as its meaning changes as we change the datastore kind were querying
                    if isinstance(v, list) or isinstance(v, tuple):
                        logging.warning(
                            "Invalid filtering! Doing an relational Query on %s with multiple key= filters is unsupported!"
                            % (name))
                        raise RuntimeError()
                    if not isinstance(v, db.Key):
                        v = db.Key(v)
                    dbFilter.ancestor(v)
                    continue
                if not (k if "." not in k else
                        k.split(".")[0]) in self.parentKeys:
                    logging.warning(
                        "Invalid filtering! %s is not in parentKeys of RelationalBone %s!"
                        % (k, name))
                    raise RuntimeError()
                dbFilter.filter("src.%s" % k, v)
        orderList = []
        for k, d in origSortOrders:  #Merge old sort orders in
            if not k in self.parentKeys:
                logging.warning(
                    "Invalid filtering! %s is not in parentKeys of RelationalBone %s!"
                    % (k, name))
                raise RuntimeError()
            orderList.append(("src.%s" % k, d))
        if orderList:
            dbFilter.order(*orderList)
        return (name, skel, dbFilter, rawFilter)
Example #12
0
    def filterHook(self, name, query, param, value):  #FIXME
        """
			Hook installed by buildDbFilter.
			This rewrites all filters added to the query after buildDbFilter has been run to match the
			layout of our viur-relations index.
			Also performs sanity checks wherever this query is possible at all.
		"""
        if param.startswith("src.") or param.startswith(
                "dest.") or param.startswith("viur_"):
            #This filter is already valid in our relation
            return (param, value)
        if param.startswith("%s." % name):
            #We add a constrain filtering by properties of the referenced entity
            refKey = param.replace("%s." % name, "")
            if " " in refKey:  #Strip >, < or = params
                refKey = refKey[:refKey.find(" ")]
            if refKey not in self.refKeys:
                logging.warning(
                    "Invalid filtering! %s is not in refKeys of RelationalBone %s!"
                    % (refKey, name))
                raise RuntimeError()
            if self.multiple:
                return (param.replace("%s." % name, "dest."), value)
            else:
                return (param, value)
        else:
            #We filter by a property of this entity
            if not self.multiple:
                #Not relational, not multiple - nothing to do here
                return (param, value)
            #Prepend "src."
            srcKey = param
            if " " in srcKey:
                srcKey = srcKey[:srcKey.find(" ")]  #Cut <, >, and =
            if srcKey == "__key__":  #Rewrite key= filter as its meaning has changed
                if isinstance(value, list) or isinstance(value, tuple):
                    logging.warning(
                        "Invalid filtering! Doing an relational Query on %s with multiple key= filters is unsupported!"
                        % (name))
                    raise RuntimeError()
                if not isinstance(value, db.Key):
                    value = db.Key(value)
                query.ancestor(value)
                return (None)
            if srcKey not in self.parentKeys:
                logging.warning(
                    "Invalid filtering! %s is not in parentKeys of RelationalBone %s!"
                    % (srcKey, name))
                raise RuntimeError()
            return ("src.%s" % param, value)
Example #13
0
    def calculateOrderSum(self, step, orderKey, *args, **kwargs):
        """
		Calculates the final price for this order.
		This function *must* be called before any attempt is made to start a payment process.


		:param step: Current step within the ordering process
		:type step: int

		:param orderKey: order to calculate the price for
		:type orderKey: str
		"""
        price = sum([x[3] for x in self.getBillItems(orderKey)])
        orderObj = db.Get(db.Key(str(orderKey)))
        orderObj["price"] = price
        db.Put(orderObj)
Example #14
0
    def startProcessing(self, step, orderID):
        def setTokenTxn(key, token):
            order = db.Get(key)
            if not order:
                return
            order["paypal_token"] = urllib.unquote(token)
            db.Put(order)

        paypal = PayPal.PayPalHandler()
        key = db.Key(orderID)
        order = db.Get(key)
        if not order:
            return
        token = paypal.SetExpressCheckout("%.2f" % order["price"])
        db.RunInTransaction(setTokenTxn, key, token)
        raise (errors.Redirect(paypal.getPayURL(token)))
Example #15
0
 def relSkelFromKey(key):
     if not isinstance(key, db.Key):
         key = db.Key(encoded=key)
     if not key.kind() == self.kind:
         logging.error(
             "I got a key, which kind doesn't match my type! (Got: %s, my type %s)"
             % (key.kind(), self.kind))
         return None
     entity = db.Get(key)
     if not entity:
         logging.error("Key %s not found" % str(key))
         return None
     relSkel = RefSkel.fromSkel(skeletonByKind(self.kind),
                                *self.refKeys)
     relSkel.unserialize(entity)
     return relSkel
Example #16
0
    def fromDB(self, key):
        """
			Load entity with *key* from the data store into the Skeleton.

			Reads all available data of entity kind *kindName* and the key *key*
			from the data store into the Skeleton structure's bones. Any previous
			data of the bones will discard.

			To store a Skeleton object to the data store, see :func:`~server.skeleton.Skeleton.toDB`.

			:param key: A :class:`server.DB.Key`, :class:`server.DB.Query`, or string,\
			from which the data shall be fetched.
			:type key: server.DB.Key | DB.Query | str

			:returns: True on success; False if the given key could not be found.
			:rtype: bool

		"""
        if isinstance(key, basestring):
            try:
                key = db.Key(key)
            except db.BadKeyError:
                key = unicode(key)
                if key.isdigit():
                    key = long(key)
                elif not len(key):
                    raise ValueError("fromDB called with empty key!")
                key = db.Key.from_path(self.kindName, key)
        if not isinstance(key, db.Key):
            raise ValueError(
                "fromDB expects an db.Key instance, an string-encoded key or a long as argument, got \"%s\" instead"
                % key)
        if key.kind() != self.kindName:  # Wrong Kind
            return (False)
        try:
            dbRes = db.Get(key)
        except db.EntityNotFoundError:
            return (False)
        if dbRes is None:
            return (False)
        self.setValues(dbRes)
        key = str(dbRes.key())
        self["key"] = key
        return (True)
Example #17
0
    def getStates(self, orderKey):
        """
			Returns the states currently set for the given order.

			:param orderKey: Key of the order
			:type orderKey: str

			:returns: States of the given order.
			:rtype: list of str
		"""
        dbObj = db.Get(db.Key(orderKey))
        res = []

        if not dbObj:
            return res

        for state in self.states:
            stateName = "state_%s" % state

            if stateName in dbObj and str(dbObj[stateName]) == "1":
                res.append(state)

        return res
Example #18
0
def shortKey(key):
    try:
        return str(db.Key(encoded=key).id_or_name())
    except:
        return key
Example #19
0
		def txnUpdate(key, mergeFrom, clearUpdateTag):
			blobList = set()
			skel = type(mergeFrom)()
			# Load the current values from Datastore or create a new, empty db.Entity
			if not key:
				dbObj = db.Entity(skel.kindName)
				oldBlobLockObj = None
			else:
				k = db.Key(key)
				assert k.kind() == skel.kindName, "Cannot write to invalid kind!"
				try:
					dbObj = db.Get(k)
				except db.EntityNotFoundError:
					dbObj = db.Entity(k.kind(), id=k.id(), name=k.name(), parent=k.parent())
				else:
					skel.setValues(dbObj)
				try:
					oldBlobLockObj = db.Get(db.Key.from_path("viur-blob-locks", str(k)))
				except:
					oldBlobLockObj = None

			# Remember old hashes for bones that must have an unique value
			oldUniqeValues = {}
			for boneName, boneInstance in skel.items():
				if boneInstance.unique:
					if "%s.uniqueIndexValue" % boneName in dbObj:
						oldUniqeValues[boneName] = dbObj["%s.uniqueIndexValue" % boneName]

			## Merge the values from mergeFrom in
			for key, bone in skel.items():
				if key in mergeFrom:
					bone.mergeFrom(skel.valuesCache, key, mergeFrom)
			for key, _bone in skel.items():
				dbObj = _bone.serialize(skel.valuesCache, key, dbObj)
				blobList.update(_bone.getReferencedBlobs(self.valuesCache, key))

			if clearUpdateTag:
				dbObj["viur_delayed_update_tag"] = 0  # Mark this entity as Up-to-date.
			else:
				dbObj[
					"viur_delayed_update_tag"] = time()  # Mark this entity as dirty, so the background-task will catch it up and update its references.
			dbObj = skel.preProcessSerializedData(dbObj)
			try:
				ourKey = str(dbObj.key())
			except:  # Its not an update but an insert, no key yet
				ourKey = None
			# Lock hashes from bones that must have unique values
			newUniqeValues = {}
			for boneName, boneInstance in skel.items():
				if boneInstance.unique:
					# Check if the property is really unique
					newUniqeValues[boneName] = boneInstance.getUniquePropertyIndexValue(
						self.valuesCache, boneName)
					if newUniqeValues[boneName] is not None:
						try:
							lockObj = db.Get(db.Key.from_path(
								"%s_%s_uniquePropertyIndex" % (skel.kindName, boneName),
								newUniqeValues[boneName]))

							if lockObj["references"] != ourKey:
								# This value has been claimed, and that not by us

								raise ValueError(
									"The unique value '%s' of bone '%s' has been recently claimed!" %
										(self.valuesCache[boneName], boneName))

						except db.EntityNotFoundError:  # No lockObj found for that value, we can use that
							pass
						dbObj["%s.uniqueIndexValue" % boneName] = newUniqeValues[boneName]
					else:
						if "%s.uniqueIndexValue" % boneName in dbObj:
							del dbObj["%s.uniqueIndexValue" % boneName]
			if not skel.searchIndex:
				# We generate the searchindex using the full skel, not this (maybe incomplete one)
				tags = []
				for key, _bone in skel.items():
					if _bone.searchable:
						tags += [tag for tag in _bone.getSearchTags(self.valuesCache, key) if
						         (tag not in tags and len(tag) < 400)]
				dbObj["viur_tags"] = tags
			db.Put(dbObj)  # Write the core entry back
			# Now write the blob-lock object
			blobList = skel.preProcessBlobLocks(blobList)
			if blobList is None:
				raise ValueError(
					"Did you forget to return the bloblist somewhere inside getReferencedBlobs()?")
			if None in blobList:
				raise ValueError("None is not a valid blobKey.")
			if oldBlobLockObj is not None:
				oldBlobs = set(oldBlobLockObj["active_blob_references"] if oldBlobLockObj[
					                                                           "active_blob_references"] is not None else [])
				removedBlobs = oldBlobs - blobList
				oldBlobLockObj["active_blob_references"] = list(blobList)
				if oldBlobLockObj["old_blob_references"] is None:
					oldBlobLockObj["old_blob_references"] = [x for x in removedBlobs]
				else:
					tmp = set(oldBlobLockObj["old_blob_references"] + [x for x in removedBlobs])
					oldBlobLockObj["old_blob_references"] = [x for x in (tmp - blobList)]
				oldBlobLockObj["has_old_blob_references"] = oldBlobLockObj[
					                                            "old_blob_references"] is not None and len(
					oldBlobLockObj["old_blob_references"]) > 0
				oldBlobLockObj["is_stale"] = False
				db.Put(oldBlobLockObj)
			else:  # We need to create a new blob-lock-object
				blobLockObj = db.Entity("viur-blob-locks", name=str(dbObj.key()))
				blobLockObj["active_blob_references"] = list(blobList)
				blobLockObj["old_blob_references"] = []
				blobLockObj["has_old_blob_references"] = False
				blobLockObj["is_stale"] = False
				db.Put(blobLockObj)
			for boneName, boneInstance in skel.items():
				if boneInstance.unique:
					# Update/create/delete missing lock-objects
					if boneName in oldUniqeValues and oldUniqeValues[boneName] != \
						newUniqeValues[boneName]:
						# We had an old lock and its value changed
						try:
							# Try to delete the old lock
							oldLockObj = db.Get(db.Key.from_path(
								"%s_%s_uniquePropertyIndex" % (skel.kindName, boneName),
								oldUniqeValues[boneName]))
							if oldLockObj["references"] != ourKey:
								# We've been supposed to have that lock - but we don't.
								# Don't remove that lock as it now belongs to a different entry
								logging.critical(
									"Detected Database corruption! A Value-Lock had been reassigned!")
							else:
								# It's our lock which we don't need anymore
								db.Delete(db.Key.from_path(
									"%s_%s_uniquePropertyIndex" % (
									skel.kindName, boneName),
									oldUniqeValues[boneName]))
						except db.EntityNotFoundError as e:
							logging.critical(
								"Detected Database corruption! Could not delete stale lock-object!")
					if newUniqeValues[boneName] is not None:
						# Lock the new value
						newLockObj = db.Entity(
							"%s_%s_uniquePropertyIndex" % (skel.kindName, boneName),
							name=newUniqeValues[boneName])
						newLockObj["references"] = str(dbObj.key())
						db.Put(newLockObj)
			return (str(dbObj.key()), dbObj, skel)
Example #20
0
    def fromClient(self, valuesCache, name, data):
        """
			Reads a value from the client.
			If this value is valid for this bone,
			store this value and return None.
			Otherwise our previous value is
			left unchanged and an error-message
			is returned.

			:param name: Our name in the skeleton
			:type name: String
			:param data: *User-supplied* request-data
			:type data: Dict
			:returns: None or String
		"""
        #from server.skeleton import RefSkel, skeletonByKind

        oldValues = valuesCache.get(name, None)
        valuesCache[name] = []
        tmpRes = {}

        clientPrefix = "%s." % name

        for k, v in data.items():
            if k.startswith(clientPrefix) or k == name:
                if k == name:
                    k = k.replace(name, "", 1)
                else:
                    k = k.replace(clientPrefix, "", 1)

                if "." in k:
                    try:
                        idx, bname = k.split(".", 1)
                        idx = int(idx)
                    except ValueError:
                        # We got some garbarge as input; don't try to parse it
                        continue

                elif k.isdigit() and self.using is None:
                    idx = int(k)
                    bname = "key"
                elif self.using is None and not self.multiple:
                    idx = 0
                    bname = "key"
                else:
                    continue

                if not idx in tmpRes:
                    tmpRes[idx] = {}

                if bname in tmpRes[idx]:
                    if isinstance(tmpRes[idx][bname], list):
                        tmpRes[idx][bname].append(v)
                    else:
                        tmpRes[idx][bname] = [tmpRes[idx][bname], v]
                else:
                    tmpRes[idx][bname] = v

        tmpList = [(k, v) for k, v in tmpRes.items() if "key" in v]
        tmpList.sort(key=lambda k: k[0])
        tmpList = [{
            "reltmp": v,
            "dest": {
                "key": v["key"]
            }
        } for k, v in tmpList]
        errorDict = {}
        forceFail = False
        if not tmpList and self.required:
            return "No value selected!"
        for r in tmpList[:]:
            # Rebuild the referenced entity data
            isEntryFromBackup = False  #If the referenced entry has been deleted, restore information from
            entry = None

            try:
                entry = db.Get(db.Key(r["dest"]["key"]))
            except:  #Invalid key or something like thatmnn

                logging.info(
                    "Invalid reference key >%s< detected on bone '%s'",
                    r["dest"]["key"], name)
                if isinstance(oldValues, dict):
                    if oldValues["dest"]["key"] == str(r["dest"]["key"]):
                        refSkel = self._refSkelCache
                        refSkel.setValuesCache(oldValues["dest"])
                        entry = refSkel.serialize()
                        isEntryFromBackup = True
                elif isinstance(oldValues, list):
                    for dbVal in oldValues:
                        if dbVal["dest"]["key"] == str(r["dest"]["key"]):
                            refSkel = self._refSkelCache
                            refSkel.setValuesCache(dbVal["dest"])
                            entry = refSkel.serialize()
                            isEntryFromBackup = True
                if not isEntryFromBackup:
                    if not self.multiple:  #We can stop here :/
                        return ("Invalid entry selected")
                    else:
                        tmpList.remove(r)
                        continue

            if not entry or (
                    not isEntryFromBackup
                    and not entry.key().kind() == self.kind
            ):  #Entry does not exist or has wrong type (is from another module)
                if entry:
                    logging.error(
                        "I got a key, which kind doesn't match my type! (Got: %s, my type %s)"
                        % (entry.key().kind(), self.kind))
                tmpList.remove(r)
                continue

            tmp = {
                k: entry[k]
                for k in entry.keys()
                if (k in self.refKeys
                    or any([k.startswith("%s." % x) for x in self.refKeys]))
            }
            tmp["key"] = r["dest"]["key"]
            relSkel = self._refSkelCache
            relSkel.setValuesCache({})
            relSkel.unserialize(tmp)
            r["dest"] = relSkel.getValuesCache()

            # Rebuild the refSkel data
            if self.using is not None:
                refSkel = self._usingSkelCache
                refSkel.setValuesCache({})
                if not refSkel.fromClient(r["reltmp"]):
                    for k, v in refSkel.errors.items():
                        errorDict["%s.%s.%s" % (name, tmpList.index(r), k)] = v
                        forceFail = True
                r["rel"] = refSkel.getValuesCache()
            else:
                r["rel"] = None
            del r["reltmp"]

        if self.multiple:
            cleanList = []
            for item in tmpList:
                err = self.isInvalid(item)
                if err:
                    errorDict["%s.%s" % (name, tmpList.index(item))] = err
                else:
                    cleanList.append(item)
            if not cleanList:
                errorDict[name] = "No value selected"
            valuesCache[name] = tmpList
        else:
            if tmpList:
                val = tmpList[0]
            else:
                val = None
            err = self.isInvalid(val)
            if not err:
                valuesCache[name] = val
                if val is None:
                    errorDict[name] = "No value selected"
        if len(errorDict.keys()):
            return ReadFromClientError(errorDict, forceFail)
Example #21
0
 def postDeletedHandler(self, skel, key, id):
     db.Delete([
         x for x in db.Query("viur-relations").ancestor(db.Key(id)).run(
             keysOnly=True)
     ])
Example #22
0
    def postSavedHandler(self, valuesCache, boneName, skel, key, dbfields):
        if not valuesCache[boneName]:
            values = []
        elif isinstance(valuesCache[boneName], dict):
            values = [dict((k, v) for k, v in valuesCache[boneName].items())]
        else:
            values = [
                dict((k, v) for k, v in x.items())
                for x in valuesCache[boneName]
            ]

        parentValues = {}

        for parentKey in dbfields.keys():
            if parentKey in self.parentKeys or any(
                [parentKey.startswith(x + ".") for x in self.parentKeys]):
                parentValues[parentKey] = dbfields[parentKey]

        dbVals = db.Query("viur-relations").ancestor(
            db.Key(key))  #skel.kindName+"_"+self.kind+"_"+key
        dbVals.filter("viur_src_kind =", skel.kindName)
        dbVals.filter("viur_dest_kind =", self.kind)
        dbVals.filter("viur_src_property =", boneName)

        for dbObj in dbVals.iter():
            try:
                if not dbObj["dest.key"] in [x["dest"]["key"] for x in values
                                             ]:  #Relation has been removed
                    db.Delete(dbObj.key())
                    continue
            except:  #This entry is corrupt
                db.Delete(dbObj.key())
            else:  # Relation: Updated
                data = [
                    x for x in values if x["dest"]["key"] == dbObj["dest.key"]
                ][0]
                if self.indexed:  #We dont store more than key and kinds, and these dont change
                    #Write our (updated) values in
                    refSkel = self._refSkelCache
                    refSkel.setValuesCache(data["dest"])
                    for k, v in refSkel.serialize().items():
                        dbObj["dest." + k] = v
                    for k, v in parentValues.items():
                        dbObj["src." + k] = v
                    if self.using is not None:
                        usingSkel = self._usingSkelCache
                        usingSkel.setValuesCache(data["rel"])
                        for k, v in usingSkel.serialize().items():
                            dbObj["rel." + k] = v
                    dbObj["viur_delayed_update_tag"] = time()
                    db.Put(dbObj)
                values.remove(data)

        # Add any new Relation
        for val in values:
            dbObj = db.Entity(
                "viur-relations",
                parent=db.Key(key))  #skel.kindName+"_"+self.kind+"_"+key

            if not self.indexed:  #Dont store more than key and kinds, as they aren't used anyway
                dbObj["dest.key"] = val["dest"]["key"]
                dbObj["src.key"] = key
            else:
                refSkel = self._refSkelCache
                refSkel.setValuesCache(val["dest"])
                for k, v in refSkel.serialize().items():
                    dbObj["dest." + k] = v
                for k, v in parentValues.items():
                    dbObj["src." + k] = v
                if self.using is not None:
                    usingSkel = self._usingSkelCache
                    usingSkel.setValuesCache(val["rel"])
                    for k, v in usingSkel.serialize().items():
                        dbObj["rel." + k] = v

            dbObj["viur_delayed_update_tag"] = time()
            dbObj[
                "viur_src_kind"] = skel.kindName  #The kind of the entry referencing
            #dbObj[ "viur_src_key" ] = str( key ) #The key of the entry referencing
            dbObj[
                "viur_src_property"] = boneName  #The key of the bone referencing
            #dbObj[ "viur_dest_key" ] = val["key"]
            dbObj["viur_dest_kind"] = self.kind
            db.Put(dbObj)
Example #23
0
def iterImport(module, target, exportKey, cursor=None, amount=0):
    """
		Processes 100 Entries and calls the next batch
	"""
    urlfetch.set_default_fetch_deadline(20)

    payload = {"module": module, "key": exportKey}
    if cursor:
        payload.update({"cursor": cursor})

    result = urlfetch.fetch(
        url=target,
        payload=urllib.urlencode(payload),
        method=urlfetch.POST,
        headers={'Content-Type': 'application/x-www-form-urlencoded'})

    if result.status_code == 200:
        res = pickle.loads(result.content.decode("HEX"))
        skel = skeletonByKind(module)()
        logging.info("%s: %d new entries fetched, total %d entries fetched" %
                     (module, len(res["values"]), amount))

        if len(res["values"]) == 0:
            try:
                utils.sendEMailToAdmins(
                    "Import of kind %s finished with %d entities" %
                    (module, amount), "ViUR finished to import %d entities of "
                    "kind %s from %s.\n" % (amount, module, target))
            except:  #OverQuota, whatever
                logging.error("Unable to send Email")

            return

        for entry in res["values"]:
            for k in list(entry.keys())[:]:
                if isinstance(entry[k], str):
                    entry[k] = entry[k].decode("UTF-8")

            if not "key" in entry.keys():
                entry["key"] = entry["id"]

            key = db.Key(encoded=utils.normalizeKey(entry["key"]))

            # Special case: Convert old module root nodes!!!
            if module.endswith(
                    "_rootNode") and key.name() and "_modul_" in key.name():
                name = key.name().replace("_modul_", "_module_")
            else:
                name = key.name()

            dbEntry = db.Entity(kind=key.kind(),
                                parent=key.parent(),
                                id=key.id(),
                                name=name)

            for k in entry.keys():
                if k == "key":
                    continue

                dbEntry[k] = entry[k]

                # Special case: Convert old module root nodes!!!
                if (isinstance(skel, (HierarchySkel, TreeLeafSkel))
                        and k in ["parentdir", "parententry", "parentrepo"]
                        and entry[k]):

                    key = db.Key(encoded=str(entry[k]))
                    if key.parent():
                        parent = db.Key(
                            encoded=utils.normalizeKey(key.parent()))
                    else:
                        parent = None

                    if key.id_or_name() and "_modul_" in str(key.id_or_name()):
                        name = key.id_or_name().replace("_modul_", "_module_")
                    else:
                        name = key.id_or_name()

                    dbEntry[k] = str(
                        db.Key.from_path(key.kind(), name, parent=parent))

            db.Put(dbEntry)
            skel.fromDB(str(dbEntry.key()))
            skel.refresh()
            skel.toDB(clearUpdateTag=True)
            amount += 1

        iterImport(module, target, exportKey, res["cursor"], amount)
Example #24
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)))