Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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()
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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()