Пример #1
0
def exportItems(module, target, importKey, startCursor, endCursor):
    Skel = skeletonByKind(module)
    query = Skel().all().cursor(startCursor, endCursor)

    for item in query.run(250):
        flatItem = DbTransfer.genDict(item)
        formFields = {
            "e": pickle.dumps(flatItem).encode("HEX"),
            "key": importKey
        }
        result = urlfetch.fetch(
            url=target,
            payload=urllib.urlencode(formFields),
            method=urlfetch.POST,
            headers={'Content-Type': 'application/x-www-form-urlencoded'})

    if startCursor == endCursor:
        try:
            email.sendEMailToAdmins(
                "Export of kind %s finished" % module,
                "ViUR finished to export kind %s to %s.\n" % (module, target))
        except:  # OverQuota, whatever
            pass
Пример #2
0
    def renderBoneStructure(self, bone):
        """
		Renders the structure of a bone.

		This function is used by `renderSkelStructure`.
		can be overridden and super-called from a custom renderer.

		:param bone: The bone which structure should be rendered.
		:type bone: Any bone that inherits from :class:`server.bones.base.baseBone`.

		:return: A dict containing the rendered attributes.
		:rtype: dict
		"""

        # Base bone contents.
        ret = {
            "descr": str(bone.descr),
            "type": bone.type,
            "required": bone.required,
            "params": bone.params,
            "visible": bone.visible,
            "readonly": bone.readOnly,
            "unique": bone.unique.method.value if bone.unique else False
        }

        if bone.type == "relational" or bone.type.startswith("relational."):
            if isinstance(bone, bones.hierarchyBone):
                boneType = "hierarchy"
            elif isinstance(bone, bones.treeItemBone):
                boneType = "treeitem"
            elif isinstance(bone, bones.treeDirBone):
                boneType = "treedir"
            else:
                boneType = "relational"
            ret.update({
                "type":
                "%s.%s" % (boneType, bone.kind),
                "module":
                bone.module,
                "multiple":
                bone.multiple,
                "format":
                bone.format,
                "using":
                self.renderSkelStructure(bone.using()) if bone.using else None,
                "relskel":
                self.renderSkelStructure(
                    RefSkel.fromSkel(skeletonByKind(bone.kind), *bone.refKeys))
            })

        elif bone.type == "record" or bone.type.startswith("record."):
            ret.update({
                "multiple": bone.multiple,
                "format": bone.format,
                "using": self.renderSkelStructure(bone.using())
            })

        elif bone.type == "select" or bone.type.startswith("select."):
            ret.update({
                "values": [(k, str(v)) for k, v in bone.values.items()],
                "multiple": bone.multiple,
            })

        elif bone.type == "date" or bone.type.startswith("date."):
            ret.update({"date": bone.date, "time": bone.time})

        elif bone.type == "numeric" or bone.type.startswith("numeric."):
            ret.update({
                "precision": bone.precision,
                "min": bone.min,
                "max": bone.max
            })

        elif bone.type == "text" or bone.type.startswith("text."):
            ret.update({
                "validHtml": bone.validHtml,
                "languages": bone.languages
            })

        elif bone.type == "str" or bone.type.startswith("str."):
            ret.update({
                "multiple": bone.multiple,
                "languages": bone.languages
            })

        return ret
Пример #3
0
 def login(self, skey="", token="", *args, **kwargs):
     # FIXME: Check if already logged in
     if not conf.get("viur.user.google.clientID"):
         raise errors.PreconditionFailed(
             "Please configure 'viur.user.google.clientID' in your conf!")
     if not skey or not token:
         currentRequest.get().response.headers["Content-Type"] = "text/html"
         if currentRequest.get().response.headers.get(
                 "cross-origin-opener-policy") == "same-origin":
             # We have to allow popups here
             currentRequest.get().response.headers[
                 "cross-origin-opener-policy"] = "same-origin-allow-popups"
         # Fixme: Render with Jinja2?
         tplStr = open(
             os.path.join(utils.coreBasePath,
                          "viur/core/template/vi_user_google_login.html"),
             "r").read()
         tplStr = tplStr.replace("{{ clientID }}",
                                 conf["viur.user.google.clientID"])
         extendCsp({
             "script-src":
             ["sha256-JpzaUIxV/gVOQhKoDLerccwqDDIVsdn1JclA6kRNkLw="],
             "style-src":
             ["sha256-FQpGSicYMVC5jxKGS5sIEzrRjSJmkxKPaetUc7eamqc="]
         })
         return tplStr
     if not securitykey.validate(skey, useSessionKey=True):
         raise errors.PreconditionFailed()
     userInfo = id_token.verify_oauth2_token(
         token, requests.Request(), conf["viur.user.google.clientID"])
     if userInfo['iss'] not in {
             'accounts.google.com', 'https://accounts.google.com'
     }:
         raise ValueError('Wrong issuer.')
     # Token looks valid :)
     uid = userInfo['sub']
     email = userInfo['email']
     addSkel = skeletonByKind(self.userModule.addSkel().kindName
                              )  # Ensure that we have the full skeleton
     userSkel = addSkel().all().filter("uid =", uid).getSkel()
     if not userSkel:
         # We'll try again - checking if there's already an user with that email
         userSkel = addSkel().all().filter("name.idx =",
                                           email.lower()).getSkel()
         if not userSkel:  # Still no luck - it's a completely new user
             if not self.registrationEnabled:
                 if userInfo.get("hd") and userInfo["hd"] in conf[
                         "viur.user.google.gsuiteDomains"]:
                     print("User is from domain - adding account")
                 else:
                     logging.warning("Denying registration of %s", email)
                     raise errors.Forbidden(
                         "Registration for new users is disabled")
             userSkel = addSkel()  # We'll add a new user
         userSkel["uid"] = uid
         userSkel["name"] = email
         isAdd = True
     else:
         isAdd = False
     now = utils.utcNow()
     if isAdd or (now -
                  userSkel["lastlogin"]) > datetime.timedelta(minutes=30):
         # Conserve DB-Writes: Update the user max once in 30 Minutes
         userSkel["lastlogin"] = now
         # if users.is_current_user_admin():
         #	if not userSkel["access"]:
         #		userSkel["access"] = []
         #	if not "root" in userSkel["access"]:
         #		userSkel["access"].append("root")
         #	userSkel["gaeadmin"] = True
         # else:
         #	userSkel["gaeadmin"] = False
         assert userSkel.toDB()
     return self.userModule.continueAuthenticationFlow(
         self, userSkel["key"])
Пример #4
0
def ensureDerived(key: db.KeyClass, srcKey, deriveMap: Dict[str, Any]):
    """
	Ensure that pending thumbnails or other derived Files are build
	:param key: DB-Key of the file-object on which we should update the derivemap
	:param srcKey: Prefix for a (hopefully) stable key to prevent rebuilding derives over and over again
	:param deriveMap: List of DeriveDicts we should build/update
	"""
    from viur.core.skeleton import skeletonByKind, updateRelations
    deriveFuncMap = conf["viur.file.derivers"]
    skel = skeletonByKind("file")()
    if not skel.fromDB(key):
        logging.info("File-Entry went missing in ensureDerived")
        return
    if not skel["derived"]:
        logging.info("No Derives for this file")
        skel["derived"] = {}
    skel["derived"]["deriveStatus"] = skel["derived"].get("deriveStatus") or {}
    skel["derived"]["files"] = skel["derived"].get("files") or {}
    resDict = {
    }  # Will contain new or updated resultDicts that will be merged into our file
    for calleeKey, params in deriveMap.items():
        fullSrcKey = "%s_%s" % (srcKey, calleeKey)
        paramsHash = sha256(str(params).encode(
            "UTF-8")).hexdigest()  # Hash over given params (dict?)
        if skel["derived"]["deriveStatus"].get(fullSrcKey) != paramsHash:
            if calleeKey not in deriveFuncMap:
                logging.warning("File-Deriver %s not found - skipping!" %
                                calleeKey)
                continue
            callee = deriveFuncMap[calleeKey]
            callRes = callee(skel, skel["derived"]["files"], params)
            if callRes:
                assert isinstance(
                    callRes,
                    list), "Old (non-list) return value from deriveFunc"
                resDict[fullSrcKey] = {"version": paramsHash, "files": {}}
                for fileName, size, mimetype, customData in callRes:
                    resDict[fullSrcKey]["files"][fileName] = {
                        "size": size,
                        "mimetype": mimetype,
                        "customData": customData
                    }

    def updateTxn(key, resDict):
        obj = db.Get(key)
        if not obj:  # File-object got deleted during building of our derives
            return
        obj["derived"] = obj.get("derived") or {}
        obj["derived"]["deriveStatus"] = obj["derived"].get(
            "deriveStatus") or {}
        obj["derived"]["files"] = obj["derived"].get("files") or {}
        for k, v in resDict.items():
            obj["derived"]["deriveStatus"][k] = v["version"]
            for fileName, fileDict in v["files"].items():
                obj["derived"]["files"][fileName] = fileDict
        db.Put(obj)

    if resDict:  # Write updated results back and queue updateRelationsTask
        db.RunInTransaction(updateTxn, key, resDict)
        # Queue that updateRelations call at least 30 seconds into the future, so that other ensureDerived calls from
        # the same fileBone have the chance to finish, otherwise that updateRelations Task will call postSavedHandler
        # on that fileBone again - re-queueing any ensureDerivedCalls that have not finished yet.
        updateRelations(key, time() + 1, "derived", _countdown=30)
Пример #5
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:
                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)
Пример #6
0
    def login(self, skey="", token="", *args, **kwargs):
        # FIXME: Check if already logged in
        if not conf.get("viur.user.google.clientID"):
            raise errors.PreconditionFailed()
        if not skey or not token:
            request.current.get(
            ).response.headers["Content-Type"] = "text/html"
            # Fixme: Render with Jinja2?
            tplStr = open("server/template/vi_user_google_login.html",
                          "r").read()
            tplStr = tplStr.replace("{{ clientID }}",
                                    conf["viur.user.google.clientID"])
            return tplStr
        if not securitykey.validate(skey, useSessionKey=True):
            raise errors.PreconditionFailed()
        userInfo = id_token.verify_oauth2_token(
            token, requests.Request(), conf["viur.user.google.clientID"])
        if userInfo['iss'] not in {
                'accounts.google.com', 'https://accounts.google.com'
        }:
            raise ValueError('Wrong issuer.')
        # Token looks valid :)
        uid = userInfo['sub']
        email = userInfo['email']
        addSkel = skeletonByKind(self.userModule.addSkel().kindName
                                 )  # Ensure that we have the full skeleton
        userSkel = addSkel().all().filter("uid =", uid).getSkel()
        if not userSkel:
            # We'll try again - checking if there's already an user with that email
            userSkel = addSkel().all().filter("name.idx =",
                                              email.lower()).getSkel()
            if not userSkel:  # Still no luck - it's a completely new user
                if not self.registrationEnabled:
                    if userInfo.get("hd") and userInfo["hd"] in conf[
                            "viur.user.google.gsuiteDomains"]:
                        print("User is from domain - adding account")
                    else:
                        logging.warning("Denying registration of %s", email)
                        raise errors.Forbidden(
                            "Registration for new users is disabled")
                userSkel = addSkel()  # We'll add a new user
            userSkel["uid"] = uid
            userSkel["name"] = email
            isAdd = True
        else:
            isAdd = False
        now = datetime.datetime.now()
        if isAdd or (now -
                     userSkel["lastlogin"]) > datetime.timedelta(minutes=30):
            # Conserve DB-Writes: Update the user max once in 30 Minutes
            userSkel["lastlogin"] = now
            #if users.is_current_user_admin():
            #	if not userSkel["access"]:
            #		userSkel["access"] = []
            #	if not "root" in userSkel["access"]:
            #		userSkel["access"].append("root")
            #	userSkel["gaeadmin"] = True
            #else:
            #	userSkel["gaeadmin"] = False
            assert userSkel.toDB()
        return self.userModule.continueAuthenticationFlow(
            self, (userSkel.kindName, userSkel["key"]))

        if users.get_current_user():

            currentUser = users.get_current_user()
            uid = currentUser.user_id()

        raise errors.Redirect(
            users.create_login_url(self.modulePath + "/login"))
Пример #7
0
			def refreshTxn():
				skel = skeletonByKind(refreshKey.kind)()
				if not skel.fromDB(refreshKey):
					return
				skel.refresh()
				skel.toDB(clearUpdateTag=True)