def set_current_settlement(self, settlement_id=None, update_mins=True): """ Tries (hard) to set the following attributes of a sesh: - self.current_settlement - self.session["current_settlement"] - self.Settlement. The best way is to use the 'settlement_id' kwarg and feed an ObjectId object. If you haven't got one of those, this func will back off to the current session's mdb object and try to set it from there. The API asset for the current settlement is also retrieved here prior to initializing self.Settlement (which requires an API asset, obvi). """ # first, if our mdb session document is None, don't do this at all if self.session is None: self.logger.error("[%s] 'session' attribute is None! Cannot set current settlement!" % (self.User)) return None elif self.get_current_view() in ["dashboard","panel"]: self.logger.warn("[%s] session tried to set a 'current_settlement' and doesn't need one! Current view: '%s'. Returning None..." % (self.User, self.get_current_view())) return None # next, if we're doing this manually, i.e. forcing a new current # settlement for a view change or whatever, do it now: if settlement_id is not None: self.session["current_settlement"] = settlement_id # now, if we've got a 'current_settlement' key, normalize it to ObjectId # to prevent funny business. back off to the session object attrib and # the session["current_asset"] (in that order). if "current_settlement" in self.session.keys(): self.session["current_settlement"] = ObjectId(self.session["current_settlement"]) elif hasattr(self, "current_settlement"): self.session["current_settlement"] = ObjectId(self.current_settlement) elif "current_asset" in self.session.keys() and "current_settlement" not in self.session.keys(): self.session["current_settlement"] = ObjectId(self.session["current_asset"]) self.logger.warn("[%s] set 'current_settlement' from 'current_asset' key!") else: self.logger.critical("[%s] unable to set 'current_settlement' for session!" % (self.User)) # now do the attrib if we've managed to get a settlement object set if "current_settlement" in self.session.keys(): self.current_settlement = self.session["current_settlement"] # now, f*****g finally, set self.Settlement if "current_settlement" in self.session.keys() and hasattr(self, "current_settlement"): s_id = self.session["current_settlement"] self.Settlement = assets.Settlement(settlement_id=s_id, session_object=self, update_mins=update_mins) else: raise Exception("[%s] session could not set current settlement!" % (self.User)) user_current_settlement = self.User.user.get("current_settlement", None) if user_current_settlement != self.session["current_settlement"]: self.logger.info("[%s] changing current settlement to %s" % (self.User, self.session["current_settlement"])) self.User.user["current_settlement"] = self.session["current_settlement"] self.User.save() mdb.sessions.save(self.session)
def render_user_asset_sheet(self, collection=None): """ Uses session attributes to render the sheet for the user asset currently set to be session["current_asset"]. Only works for Survivor Sheets and Settlement Sheets so far. """ output = "ERROR!" user_asset = mdb[collection].find_one({"_id": self.session["current_asset"]}) if user_asset is not None: if collection == "settlements": self.set_current_settlement(user_asset["_id"]) S = assets.Settlement(settlement_id = user_asset["_id"], session_object=self) elif collection == "survivors": self.set_current_settlement(user_asset["settlement"]) S = assets.Survivor(survivor_id = user_asset["_id"], session_object=self) else: self.logger.error("[%s] user assets from '%s' colletion don't have Sheets!" % (self.User,collection)) output = S.render_html_form() return output
def render_html(self): """ Renders the whole panel. """ try: World = api.route_to_dict("world") W = World["world"] meta = World["meta"] except Exception as e: return "World could not be loaded! %s" % e daemon_block = '<table class="admin_panel_right_child">' daemon_block += '<tr><th colspan="2">World Daemon</th></tr>' for k, v in World["world_daemon"].iteritems(): if type(v) == dict: raw = v["$date"] dt = datetime.fromtimestamp(raw/1000) daemon_block += '<tr><td>%s</td><td>%s</td></tr>' % (k,dt) else: daemon_block += '<tr><td>%s</td><td>%s</td></tr>' % (k,v) daemon_block += "</table>" response_block = '<table class="admin_panel_right_child">' response_block += '<tr><th colspan="4">Response Times</th></tr>' response_block += '<tr><td><i>View</i></td><td><i>#</i></td><td><i>Avg.</i></td><td><i>Max</i></td></tr>' for r in get_response_times(): response_block += "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>" % (r["_id"],r["count"],r["avg_time"],r["max_time"]) response_block += "</table>" admins_block = '<table class="admin_panel_right_child">' admins_block += '<tr><th colspan="2">Administrators</th></tr>' admins = mdb.users.find({"admin":{"$exists":True}}) for a in admins: admins_block += '<tr><td>%s</td><td>%s</td></tr>' % (a["login"],a["_id"]) admins_block += '</table>' stat_block = '<table class="admin_panel_right_child">' stat_block += '<tr><th colspan="2">Environment</th></tr>' stat_block += '<tr><td>Host</td><td>%s</td></tr>' % socket.getfqdn() stat_block += '<tr><td>Application version</td><td>%s</td></tr>' % settings.get("application","version") stat_block += '<tr><td>Release</td><td>%s</td></tr>' % get_latest_update_string() stat_block += '<tr><td>API URL</td><td>%s</td></tr>' % api.get_api_url() stat_block += '<tr><td>API admin panel</td><td><a href="%sadmin">%sadmin</a></td></tr>' % (api.get_api_url(), api.get_api_url()) stat_block += '<tr><td>API Version</td><td>%s</td></tr>' % meta["api"]["version"] stat_block += '</table>' output = html.panel.headline.safe_substitute( response_times = response_block, world_daemon = daemon_block, recent_users_count = self.recent_users.count(), users = W["total_users"]["value"], sessions = mdb.sessions.find().count(), settlements = mdb.settlements.find().count(), total_survivors = W["total_survivors"]["value"], live_survivors = W["live_survivors"]["value"], dead_survivors = W["dead_survivors"]["value"], complete_death_records = mdb.the_dead.find({"complete": {"$exists": True}}).count(), latest_fatality = world.api_survivor_to_html(W["latest_fatality"]), latest_settlement = world.api_settlement_to_html(W["latest_settlement"]), latest_kill = world.api_monster_to_html(W["latest_kill"]), current_hunt = world.api_current_hunt(W["current_hunt"]), admin_stats = stat_block, admins = admins_block, ) for user in self.recent_users: User = assets.User(user_id=user["_id"], session_object=self.Session) # create settlement summaries settlements = mdb.settlements.find({"created_by": User.user["_id"]}).sort("name") settlement_strings = [] for s in settlements: S = assets.Settlement(settlement_id=s["_id"], session_object=self.Session, update_mins=False) settlement_strings.append(S.render_admin_panel_html()) output += html.panel.user_status_summary.safe_substitute( user_name = User.user["login"], u_id = User.user["_id"], ua = User.user["latest_user_agent"], latest_sign_in = User.user["latest_sign_in"].strftime(ymdhms), latest_sign_in_mins = (datetime.now() - User.user["latest_sign_in"]).seconds // 60, session_length = (User.user["latest_activity"] - User.user["latest_sign_in"]).seconds // 60, latest_activity = User.user["latest_activity"].strftime(ymdhms), latest_activity_mins = (datetime.now() - User.user["latest_activity"]).seconds // 60, latest_action = User.user["latest_action"], settlements = "<br/>".join(settlement_strings), survivor_count = mdb.survivors.find({"created_by": User.user["_id"]}).count(), user_created_on = User.user["created_on"].strftime(ymd), user_created_on_days = (datetime.now() - User.user["created_on"]).days ) output += "<hr/>" log_lines = self.get_last_n_log_lines(50) zebra = False for l in reversed(log_lines): if zebra: output += html.panel.log_line.safe_substitute(line=l, zebra=zebra) zebra = False else: output += html.panel.log_line.safe_substitute(line=l) zebra = "grey" output += html.meta.hide_full_page_loader return output
def set_current_settlement(self, settlement_id=None): """ Tries (hard) to set the following attributes of a sesh: - self.current_settlement - self.session["current_settlement"] - self.Settlement The best way is to use the 'settlement_id' kwarg and feed an ObjectId object. If you haven't got one of those, this func will back off to the current session's mdb object and try to set it from there. The API asset for the current settlement is also retrieved here prior to initializing self.Settlement (which requires an API asset, obvi). """ # # init / sanity checks # # first, if our self.session dict is None, don't do this at all if self.session is None: self.logger.warn( "[%s] 'session' attribute is None! Cannot set current settlement!" % (self.User)) return None elif self.get_current_view() in [ "dashboard", "panel", 'new_settlement' ]: msg = "[%s] '%s' view doesn't need a 'current_settlement' attr!" % ( self.User, self.get_current_view()) # self.logger.warn(msg) self.session['current_settlement'] = None return None # next, if we're doing this manually, i.e. forcing a new current # settlement for a view change or whatever, do it now: if settlement_id is not None: self.session["current_settlement"] = settlement_id # # synchronize the current_settlement across all objects in play # # here we check the session dictionary or the session attributes and # make sure that they're both set and synchronized # 1.) set the self attrib from the dict key/value if self.session.get('current_settlement', None) is not None: self.current_settlement = self.session["current_settlement"] # 2.) or set the dict key/value from the self attrib elif hasattr( self, "current_settlement") and self.current_settlement is not None: self.session["current_settlement"] = self.current_settlement # 3.) finally, validate the sync. if self.session.get('current_settlement', None) is None or not hasattr( self, 'current_settlement'): err_msg = "[%s] unable to set 'current_settlement' attrib for session!" % ( self.User) raise Exception(err_msg) # next, check the user. Make sure they're synchronized as well if self.User.user.get('current_settlement', None) != self.current_settlement: self.logger.info("[%s] changing current settlement to %s" % (self.User, self.session["current_settlement"])) self.User.user["current_settlement"] = self.session[ "current_settlement"] self.User.save() # next, set self.Settlement (finally) and save self.Settlement = assets.Settlement( settlement_id=self.current_settlement, session_object=self) self.save()
def process_params(self, user_action=None): """ All cgi.FieldStorage() params passed to this object on init need to be processed. This does ALL OF THEM at once. """ # # dashboard-based, user operation params # if "update_user_preferences" in self.params: self.User.update_preferences(self.params) user_action = "updated user preferences" if "change_password" in self.params: if "password" in self.params and "password_again" in self.params: self.User.update_password(self.params["password"].value, self.params["password_again"].value) user_action = "updated password" else: user_action = "failed to update password" # do error reporting if "error_report" in self.params and "body" in self.params: self.report_error() # # change view operations, incl. with/without an asset # # change to a generic view without an asset if "change_view" in self.params: target_view = self.params["change_view"].value user_action = self.change_current_view(target_view) # change to a view of an asset for p in ["view_campaign", "view_settlement", "view_survivor"]: if p in self.params: user_action = self.change_current_view_to_asset(p) # these are our two asset removal methods: this is as DRY as I think we # can get with this stuff, since both require unique handling if "remove_settlement" in self.params: s_id = ObjectId(self.params["remove_settlement"].value) self.set_current_settlement(s_id) S = assets.Settlement(settlement_id=s_id, session_object=self) S.remove() user_action = "removed settlement %s" % S self.change_current_view("dashboard") if "remove_survivor" in self.params: # we actually have to get the survivor from the MDB to set the # current settlement before we can initialize the survivor and # use its remove() method. s_id = ObjectId(self.params["remove_survivor"].value) s_doc = mdb.survivors.find_one({"_id": s_id}) self.set_current_settlement(s_doc["settlement"]) S = assets.Survivor(survivor_id=s_id, session_object=self) S.remove() user_action = "removed survivor %s from %s" % (S, S.Settlement) self.change_current_view("view_campaign", asset_id=S.survivor["settlement"]) # user and campaign exports if "export_user_data" in self.params: export_type = self.params["export_user_data"].value if "asset_id" in self.params and self.User.is_admin(): user_object = assets.User(user_id=self.params["asset_id"].value, session_object=self) filename = "%s_%s.kdm-manager_export.%s" % (datetime.now().strftime(ymd), user_object.user["login"], export_type.lower()) payload = user_object.dump_assets(dump_type=export_type) else: payload = self.User.dump_assets(dump_type=export_type) filename = "%s_%s.kdm-manager_export.%s" % (datetime.now().strftime(ymd), self.User.user["login"], export_type.lower()) self.User.mark_usage("exported user data (%s)" % export_type) self.logger.debug("[%s] '%s' export complete. Rendering export via HTTP..." % (self.User, export_type)) html.render(str(payload), http_headers="Content-Disposition: attachment; filename=%s\n" % (filename)) if "export_campaign" in self.params: export_type = self.params["export_campaign"].value C = assets.Settlement(settlement_id=ObjectId(self.params["asset_id"].value), session_object=self) payload, length = C.export(export_type) filename = "%s_-_%s.%s" % (datetime.now().strftime(ymd), C.settlement["name"], export_type.lower()) self.User.mark_usage("exported campaign data as %s" % export_type) self.logger.debug("[%s] '%s' export complete. Rendering export via HTTP..." % (self.User, export_type)) html.render(payload, http_headers="Content-type: application/octet-stream;\r\nContent-Disposition: attachment; filename=%s\r\nContent-Title: %s\r\nContent-Length: %i\r\n" % (filename, filename, length)) # # settlement operations - everything below uses user_asset_id # which is to say that all forms that submit these params use # the asset_id=mdb_id convention. user_asset_id = None if "asset_id" in self.params: user_asset_id = ObjectId(self.params["asset_id"].value) # create new user assets if "new" in self.params: # # new survivor creation via API call # if self.params["new"].value == "survivor": self.set_current_settlement(user_asset_id) POST_params = {"settlement": self.Settlement.settlement["_id"]} incoming_form_params = ["name","sex","survivor_avatar","father","mother","email","public"] for p in incoming_form_params: if p in self.params and self.params[p].value not in ["",u""]: if "string:" in self.params[p].value: oid = self.params[p].value.split("string:")[1] POST_params[p] = oid else: POST_params[p] = self.params[p].value else: pass response = api.post_JSON_to_route("/new/survivor", payload=POST_params, Session=self) if response.status_code == 200: s_id = ObjectId(response.json()["sheet"]["_id"]["$oid"]) self.change_current_view("view_survivor", asset_id=s_id) S = assets.Survivor(s_id, session_object=self) user_action = "created survivor %s in %s" % (S, self.Settlement) else: msg = "An API error caused survivor creation to fail! API response was: %s - %s" % (response.status_code, response.reason) self.logger.error("[%s] new survivor creation failed!" % self.User) self.logger.error("[%s] %s" % (self.User, msg)) raise RuntimeError(msg) # # new settlement creation via API call # if self.params["new"].value == "settlement": params = {} params["campaign"] = self.params["campaign"].value # try to get a name or default to None if "name" in self.params: params["name"] = self.params["name"].value else: params["name"] = None # try to get expansions/survivors params or default to [] for p in ["expansions", "survivors", "specials"]: if p not in self.params: params[p] = [] elif p in self.params and isinstance(self.params[p], cgi.MiniFieldStorage): params[p] = [self.params[p].value] elif p in self.params and type(self.params[p]) == list: params[p] = [i.value for i in self.params[p]] else: msg = "Invalid form parameter! '%s' is unknown type: '%s'" % (p, type(self.params[p]).__name__) self.logger.error("[%s] invalid param key '%s' was %s. Params: %s" % (self.User, p, type(self.params[p]), self.params)) raise AttributeError(msg) # hit the route; check the response response = api.post_JSON_to_route("/new/settlement", payload=params, Session=self) if response.status_code == 200: s_id = ObjectId(response.json()["sheet"]["_id"]["$oid"]) self.set_current_settlement(s_id) S = assets.Settlement(s_id, session_object=self) user_action = "created settlement %s" % self.Settlement self.change_current_view("view_campaign", S.settlement["_id"]) S.save() elif response.status_code == 405: self.change_current_view('dashboard') else: msg = "An API error caused settlement creation to fail! API response was: %s - %s" % (response.status_code, response.reason) self.logger.error("[%s] new settlement creation failed!" % self.User) self.logger.error("[%s] %s" % (self.User, msg)) raise RuntimeError(msg) # bulk add if "bulk_add_survivors" in self.params: self.set_current_settlement(user_asset_id) S = assets.Settlement(settlement_id=user_asset_id, session_object=self) male = int(self.params["male_survivors"].value) female = int(self.params["female_survivors"].value) for tup in [("M", male), ("F",female)]: letter, sex = tup for i in range(sex): POST_params = {"settlement": self.Settlement.settlement["_id"], "sex": letter, "public": True,} response = api.post_JSON_to_route("/new/survivor", payload=POST_params, Session=self) if response.status_code == 200: pass else: msg = "An API error caused survivor creation to fail! API response was: %s - %s" % (response.status_code, response.reason) self.logger.error("[%s] new survivor creation failed!" % self.User) self.logger.error("[%s] %s" % (self.User, msg)) raise RuntimeError(msg) user_action = "added %s male and %s survivors to %s" % (male, female, self.Settlement) self.change_current_view("view_campaign", user_asset_id) # modify if "modify" in self.params: if self.params["modify"].value == "settlement": s = mdb.settlements.find_one({"_id": ObjectId(user_asset_id)}) self.set_current_settlement(s["_id"]) S = assets.Settlement(settlement_id=s["_id"], session_object=self) S.modify(self.params) user_action = "modified settlement %s" % self.Settlement if self.params["modify"].value == "survivor": update_mins = True if "norefresh" in self.params: update_mins = False s = mdb.survivors.find_one({"_id": ObjectId(user_asset_id)}) self.set_current_settlement(s["settlement"], update_mins) S = assets.Survivor(survivor_id=s["_id"], session_object=self) S.modify(self.params) user_action = "modified survivor %s of %s" % (S, self.Settlement) self.User.mark_usage(user_action)
def process_params(self, user_action=None): """ All cgi.FieldStorage() params passed to this object on init need to be processed. This does ALL OF THEM at once. """ # # dashboard-based, user operation params # # do error reporting if "error_report" in self.params and "body" in self.params: self.report_error() # # change view operations, incl. with/without an asset # # change to a generic view without an asset if "change_view" in self.params: target_view = self.params["change_view"].value user_action = self.change_current_view(target_view) # change to a view of an asset for p in ["view_campaign", "view_settlement", "view_survivor"]: if p in self.params: user_action = self.change_current_view_to_asset(p) # these are our two asset removal methods: this is as DRY as I think we # can get with this stuff, since both require unique handling if "remove_settlement" in self.params: s_id = ObjectId(self.params["remove_settlement"].value) self.set_current_settlement(s_id) S = assets.Settlement(settlement_id=s_id, session_object=self) S.remove() user_action = "removed settlement %s" % S self.change_current_view("dashboard") if "remove_survivor" in self.params: # we actually have to get the survivor from the MDB to set the # current settlement before we can initialize the survivor and # use its remove() method. s_id = ObjectId(self.params["remove_survivor"].value) s_doc = mdb.survivors.find_one({"_id": s_id}) self.set_current_settlement(s_doc["settlement"]) S = assets.Survivor(survivor_id=s_id, session_object=self) S.remove() user_action = "removed survivor %s from %s" % (S, S.Settlement) self.change_current_view("view_campaign", asset_id=S.survivor["settlement"]) # # settlement operations - everything below uses user_asset_id # which is to say that all forms that submit these params use # the asset_id=mdb_id convention. user_asset_id = None if "asset_id" in self.params: user_asset_id = ObjectId(self.params["asset_id"].value) # # we support new settlement creation in the legacy webapp. # if "new" in self.params: self.logger.info("POST params include 'new' attribute! %s" % self.params) params = {} params["campaign"] = self.params["campaign"].value # try to get a name or default to None if "name" in self.params: params["name"] = self.params["name"].value else: params["name"] = None # try to get expansions/survivors params or default to [] for p in ["expansions", "survivors", "specials"]: if p not in self.params: params[p] = [] elif p in self.params and isinstance(self.params[p], cgi.MiniFieldStorage): params[p] = [self.params[p].value] elif p in self.params and type(self.params[p]) == list: params[p] = [i.value for i in self.params[p]] else: msg = "Invalid form parameter! '%s' is unknown type: '%s'" % ( p, type(self.params[p]).__name__) self.logger.error( "[%s] invalid param key '%s' was %s. Params: %s" % (self.User, p, type(self.params[p]), self.params)) raise AttributeError(msg) # hit the route; check the response response = api.post_JSON_to_route("/new/settlement", payload=params, Session=self) if response.status_code == 200: s_id = ObjectId(response.json()["sheet"]["_id"]["$oid"]) self.set_current_settlement(s_id) S = assets.Settlement(s_id, session_object=self) user_action = "created settlement %s" % self.Settlement self.change_current_view("view_campaign", S.settlement["_id"]) S.save() elif response.status_code == 405: self.change_current_view('dashboard') else: msg = "An API error caused settlement creation to fail! API response was: %s - %s" % ( response.status_code, response.reason) self.logger.error("[%s] new settlement creation failed!" % self.User) self.logger.error("[%s] %s" % (self.User, msg)) raise RuntimeError(msg) # # modify - not supported in the legacy webapp as of 2018-01-26 # if "modify" in self.params: self.logger.error("'modify' in legacy webapp POST params!") self.logger.error(self.params) raise Exception( 'Attempt to modify user asset via legacy webapp! Incoming params: %s' % self.params) self.User.mark_usage(user_action) self.get_current_view()