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))
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
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
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)
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