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