Пример #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([issubclass(x[0], UserPassword) for x in userMod.validAuthenticationMethods])):  # It uses UserPassword login
		if not db.Query(userMod.addSkel().kindName).getEntry():  # There's currently no user in the database
			addSkel = skeletonByKind(userMod.addSkel().kindName)()  # Ensure we have the full skeleton
			uname = "admin@%s.appspot.com" % utils.projectID
			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))
Пример #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
Пример #3
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 viur.core.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
    resolverDict = {}
    for moduleName in dir(config):  # iterate over all modules
        if moduleName == "index":
            mapModule(res, "index", resolverDict)
            continue
        moduleClass = getattr(config, moduleName)
        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 = moduleClass(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 renderName != default:
                    if not renderName in resolverDict:
                        resolverDict[renderName] = {}
                    targetResoveRender = resolverDict[renderName]
                else:
                    targetResoveRender = resolverDict
                mapModule(obj, moduleName, targetResoveRender)
                # Apply Renderers postProcess Filters
                if "_postProcessAppObj" in rendlist[renderName]:
                    rendlist[renderName]["_postProcessAppObj"](
                        targetResoveRender)
        if "seoLanguageMap" in dir(moduleClass):
            conf["viur.languageModuleMap"][
                moduleName] = moduleClass.seoLanguageMap
    conf["viur.mainResolver"] = resolverDict
    if conf["viur.exportPassword"] is not None or conf[
            "viur.importPassword"] is not None:
        # Enable the Database ex/import API
        from viur.core.dbtransfer import DbTransfer
        if conf["viur.importPassword"]:
            logging.critical(
                "The Import-API is enabled! Never do this on production systems!"
            )
            from viur.core 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())
        mapModule(res.dbtransfer, "dbtransfer", resolverDict)
        #resolverDict["dbtransfer"]
    if conf["viur.debug.traceExternalCallRouting"] or conf[
            "viur.debug.traceInternalCallRouting"]:
        from viur.core 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
Пример #4
0
    def deferred(self, *args, **kwargs):
        """
			This catches one deferred call and routes it to its destination
		"""
        global _deferedTasks, _appengineServiceIPs

        req = currentRequest.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()
        if req.environ.get(
                "HTTP_X_APPENGINE_USER_IP") not in _appengineServiceIPs:
            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, object_hook=jsonDecodeObjectHook)
        funcPath, args, kwargs, env = data
        if env:
            if "user" in env and env["user"]:
                currentSession.get()["user"] = env["user"]
            if "lang" in env and env["lang"]:
                currentRequest.get().language = env["lang"]
            if "transactionMarker" in env:
                marker = db.Get(
                    db.Key("viur-transactionmarker", env["transactionMarker"]))
                if not marker:
                    logging.info(
                        "Dropping task, transaction %s did not apply" %
                        env["transactionMarker"])
                    return
                else:
                    logging.info("Executing task, transaction %s did succeed" %
                                 env["transactionMarker"])
            if "custom" in env and conf["viur.tasks.customEnvironmentHandler"]:
                # Check if we need to restore additional environmental 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("ViUR missed a deferred task! %s(%s,%s)",
                              funcPath, args, kwargs)
            try:
                _deferedTasks[funcPath](*args, **kwargs)
            except PermanentTaskFailure:
                pass
            except Exception as e:
                logging.exception(e)
                raise errors.RequestTimeout()  # Task-API should retry
Пример #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)