Example #1
0
def createNewUserIfNotExists():
	"""
		Create a new Admin user, if the userDB is empty
	"""
	userMod = getattr(conf["viur.mainApp"], "user", None)
	if (userMod # We have a user module
		and isinstance(userMod, User)
		and "addSkel" in dir(userMod)
		and "validAuthenticationMethods" in dir(userMod) #Its our user module :)
		and any([x[0] is UserPassword for x in userMod.validAuthenticationMethods])): #It uses UserPassword login
			if not db.Query(userMod.addSkel().kindName).get(): #There's currently no user in the database
				addSkel = skeletonByKind(userMod.addSkel().kindName)() # Ensure we have the full skeleton
				uname = "admin@%s.appspot.com" % app_identity.get_application_id()
				pw = utils.generateRandomString(13)
				addSkel["name"] = uname
				addSkel["status"] = 10  # Ensure its enabled right away
				addSkel["access"] = ["root"]
				addSkel["password"] = pw
				try:
					addSkel.toDB()
				except Exception as e:
					logging.error("Something went wrong when trying to add admin user %s with Password %s", (uname, pw))
					logging.exception(e)
					return
				logging.warning("ViUR created a new admin-user for you! Username: %s, Password: %s" % (uname, pw))
				utils.sendEMailToAdmins("Your new ViUR password",
				                        "ViUR created a new admin-user for you! Username: %s, Password: %s" % (uname, pw))
Example #2
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:
            utils.sendEMailToAdmins(
                "Export of kind %s finished" % module,
                "ViUR finished to export kind %s to %s.\n" % (module, target))
        except:  #OverQuota, whatever
            pass
Example #3
0
    def deferred(self, *args, **kwargs):
        """
			This catches one defered call and routes it to its destination
		"""
        from server import session
        from server import utils
        global _deferedTasks

        req = request.current.get().request
        if 'X-AppEngine-TaskName' not in req.headers:
            logging.critical(
                'Detected an attempted XSRF attack. The header "X-AppEngine-Taskname" was not set.'
            )
            raise errors.Forbidden()
        in_prod = (not req.environ.get("SERVER_SOFTWARE").startswith("Devel"))
        if in_prod and req.environ.get("REMOTE_ADDR") != "0.1.0.2":
            logging.critical(
                'Detected an attempted XSRF attack. This request did not originate from Task Queue.'
            )
            raise errors.Forbidden()
        # Check if the retry count exceeds our warning threshold
        retryCount = req.headers.get("X-Appengine-Taskretrycount", None)
        if retryCount:
            if int(retryCount) == self.retryCountWarningThreshold:
                utils.sendEMailToAdmins(
                    "Deferred task retry count exceeded warning threshold",
                    "Task %s will now be retried for the %sth time." %
                    (req.headers.get("X-Appengine-Taskname", ""), retryCount))
        cmd, data = json.loads(req.body)
        try:
            funcPath, args, kwargs, env = data
        except ValueError:  #We got an old call without an frozen environment
            env = None
            funcPath, args, kwargs = data
        if env:
            if "user" in env and env["user"]:
                session.current["user"] = env["user"]
            if "lang" in env and env["lang"]:
                request.current.get().language = env["lang"]
            if "custom" in env and conf["viur.tasks.customEnvironmentHandler"]:
                # Check if we need to restore additional enviromental data
                assert isinstance(conf["viur.tasks.customEnvironmentHandler"], tuple) \
                 and len(conf["viur.tasks.customEnvironmentHandler"])==2 \
                 and callable(conf["viur.tasks.customEnvironmentHandler"][1]), \
                 "Your customEnvironmentHandler must be a tuple of two callable if set!"
                conf["viur.tasks.customEnvironmentHandler"][1](env["custom"])
        if cmd == "rel":
            caller = conf["viur.mainApp"]
            pathlist = [x for x in funcPath.split("/") if x]
            for currpath in pathlist:
                if currpath not in dir(caller):
                    logging.error(
                        "ViUR missed a deferred task! Could not resolve the path %s. Failed segment was %s",
                        funcPath, currpath)
                    return
                caller = getattr(caller, currpath)
            try:
                caller(*args, **kwargs)
            except PermanentTaskFailure:
                pass
            except Exception as e:
                logging.exception(e)
                raise errors.RequestTimeout()  #Task-API should retry
        elif cmd == "unb":
            if not funcPath in _deferedTasks:
                logging.error("Ive missed a defered task! %s(%s,%s)" %
                              (funcPath, str(args), str(kwargs)))
            try:
                _deferedTasks[funcPath](*args, **kwargs)
            except PermanentTaskFailure:
                pass
            except Exception as e:
                logging.exception(e)
                raise errors.RequestTimeout()  #Task-API should retry
Example #4
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 #5
0
def buildApp(config, renderers, default=None, *args, **kwargs):
    """
		Creates the application-context for the current instance.

		This function converts the classes found in the *modules*-module,
		and the given renders into the object found at ``conf["viur.mainApp"]``.

		Every class found in *modules* becomes

		- instanced
		- get the corresponding renderer attached
		- will be attached to ``conf["viur.mainApp"]``

		:param config: Usually the module provided as *modules* directory within the application.
		:type config: module | object
		:param renders: Usually the module *server.renders*, or a dictionary renderName => renderClass.
		:type renders: module | dict
		:param default: Name of the renderer, which will form the root of the application.\
		This will be the renderer, which wont get a prefix, usually jinja2. \
		(=> /user instead of /jinja2/user)
		:type default: str
	"""
    class ExtendableObject(object):
        pass

    if isinstance(renderers, dict):
        rendlist = renderers
    else:  # build up the dict from server.render
        rendlist = {}
        for key in dir(renderers):
            if not "__" in key:
                rendlist[key] = {}
                rendsublist = getattr(renderers, key)
                for subkey in dir(rendsublist):
                    if not "__" in subkey:
                        rendlist[key][subkey] = getattr(rendsublist, subkey)

    if "index" in dir(config):
        res = config.index()
    else:
        res = ExtendableObject()

    config._tasks = TaskHandler

    for moduleName in dir(config):  # iterate over all modules
        if moduleName == "index":
            continue

        for renderName in list(rendlist.keys(
        )):  # look, if a particular render should be built
            if renderName in dir( getattr( config, moduleName ) ) \
             and getattr( getattr( config, moduleName ) , renderName )==True:
                modulePath = "%s/%s" % ("/" + renderName if renderName !=
                                        default else "", moduleName)
                obj = getattr(config, moduleName)(moduleName, modulePath)
                if moduleName in rendlist[
                        renderName]:  # we have a special render for this
                    obj.render = rendlist[renderName][moduleName](parent=obj)
                else:  # Attach the default render
                    obj.render = rendlist[renderName]["default"](parent=obj)
                setattr(obj, "_moduleName", moduleName)
                if renderName == default:  #default or render (sub)namespace?
                    setattr(res, moduleName, obj)
                else:
                    if not renderName in dir(res):
                        setattr(res, renderName, ExtendableObject())
                    setattr(getattr(res, renderName), moduleName, obj)

    if not isinstance(renderers, dict):  # Apply Renderers postProcess Filters
        for renderName in list(rendlist.keys()):
            rend = getattr(renderers, renderName)
            if "_postProcessAppObj" in dir(rend):
                if renderName == default:
                    res = rend._postProcessAppObj(res)
                else:
                    if (renderName in dir(res)):
                        setattr(
                            res, renderName,
                            rend._postProcessAppObj(getattr(res, renderName)))
    else:
        for renderName in list(rendlist.keys()):
            rend = rendlist[renderName]
            if "_postProcessAppObj" in list(rend.keys()):
                if renderName == default:
                    res = rend["_postProcessAppObj"](res)
                else:
                    if renderName in dir(res):
                        setattr(
                            res, renderName,
                            rend["_postProcessAppObj"](getattr(
                                res, renderName)))

    if conf["viur.exportPassword"] is not None or conf[
            "viur.importPassword"] is not None:
        # Enable the Database ex/import API
        from server.dbtransfer import DbTransfer
        if conf["viur.importPassword"]:
            logging.critical(
                "The Import-API is enabled! Never do this on production systems!"
            )
            from server import utils
            try:
                utils.sendEMailToAdmins(
                    "Active Database import API",
                    "ViUR just started a new Instance with an ENABLED DATABASE IMPORT API! You have been warned."
                )
            except:  #OverQuota, whatever
                pass  #Dont render this instance unusable
        elif conf["viur.exportPassword"]:
            logging.warning(
                "The Export-API is enabled. Everyone having that key can read the whole database!"
            )

        setattr(res, "dbtransfer", DbTransfer())
    if conf["viur.debug.traceExternalCallRouting"] or conf[
            "viur.debug.traceInternalCallRouting"]:
        from server import utils
        try:
            utils.sendEMailToAdmins(
                "Debug mode enabled",
                "ViUR just started a new Instance with calltracing enabled! This will log sensitive information!"
            )
        except:  # OverQuota, whatever
            pass  # Dont render this instance unusable
    if default in rendlist and "renderEmail" in dir(
            rendlist[default]["default"]()):
        conf["viur.emailRenderer"] = rendlist[default]["default"]().renderEmail
    elif "html" in list(rendlist.keys()):
        conf["viur.emailRenderer"] = rendlist["html"]["default"]().renderEmail

    return res