Beispiel #1
0
    async def post(self):
        group = self.model_by_id(GroupModel, "group_id")

        membership = MembershipModel()
        membership.user = self.current_user
        membership.group = group

        if group.requires_approval:
            await slack.group_message(
                group.slug, "New pending member: {}".format(
                    self.current_user.main_character.character_name))
            membership.pending = True
        else:
            for identity in self.current_user.slack_identities:
                member = await slack.user_email_to_id(identity.email)
                await slack.group_invite(group.slug, member)

            await slack.group_message(
                group.slug, "New member: {}".format(
                    self.current_user.main_character.character_name))

        session.add(membership)
        session.commit()

        sec_log.info("user {} joined group {}".format(membership.user,
                                                      membership.group))

        return self.redirect("/groups/join/success?membership_id={}".format(
            membership.id))
Beispiel #2
0
    async def post(self):
        code = self.get_argument("code", None)

        slackidentity = self.model_by_id(SlackIdentityModel,
                                         "slackidentity_id")

        if slackidentity.verification_code == code:
            slackidentity.verification_done = True

            session.add(slackidentity)
            session.commit()

            sec_log.info("slackidentity {} for {} verified".format(
                slackidentity, slackidentity.user))
            self.flash_success(
                self.locale.translate(
                    "SERVICES_VERIFY_SLACK_IDENTITY_SUCCESS_ALERT"))

            return self.redirect("/services?slackidentity_id={}".format(
                slackidentity.id))
        else:
            self.flash_error(
                self.locale.translate(
                    "SERVICES_VERIFY_SLACK_IDENTITY_FAILURE_ALERT"))
            return self.redirect("/services?slackidentity_id={}".format(
                slackidentity.id))
Beispiel #3
0
    async def post(self):
        group = self.model_by_id(GroupModel, "group_id")

        for membership in group.memberships:
            if membership.user == self.current_user:
                session.delete(membership)
                session.commit()

                for identity in self.current_user.slack_identities:
                    member = await slack.user_email_to_id(identity.email)
                    await slack.group_kick(group.slug, member)

                await slack.group_message(
                    group.slug, "Member left: {}".format(
                        self.current_user.main_character.character_name))

                break
        else:
            raise tornado.web.HTTPError(400)

        sec_log.info("user {} left group {}".format(membership.user,
                                                    membership.group))

        return self.redirect("/groups/leave/success?group_id={}".format(
            group.id))
Beispiel #4
0
    async def post(self):
        membership = self.model_by_id(MembershipModel, "membership_id")

        group_id = membership.group.id

        session.delete(membership)
        session.commit()

        self.flash_success(
            self.locale.translate("MEMBERSHIP_DENY_SUCCESS_ALERT"))
        self.redirect("/admin/groups/manage?group_id={}".format(group_id))
Beispiel #5
0
    async def post(self):
        slackidentity = self.model_by_id(SlackIdentityModel,
                                         "slackidentity_id")

        session.delete(slackidentity)
        session.commit()

        self.flash_success(
            self.locale.translate(
                "SERVICES_DELETE_SLACK_IDENTITY_SUCCESS_ALERT"))

        return self.redirect("/services")
Beispiel #6
0
    async def post(self):
        character = self.model_by_id(CharacterModel, "character_id")

        for char in self.current_user.characters:
            char.is_main = False

        character.is_main = True

        session.add(self.current_user)
        session.commit()

        return self.redirect("/characters/select_main/success")
Beispiel #7
0
def refresh_character_ship(self, character_id, recurring=60):
    """Refresh a characters current ship."""
    try:
        character = session.query(CharacterModel).filter(
            CharacterModel.id == character_id).one()

        job_log.debug("user.refresh_character_ship {}".format(
            character.character_name))

        try:
            type_id = esi_characters.ship(character.character_id,
                                          access_token=character.access_token)
        except (InvalidToken, ExpiredToken):
            try:
                refresh_access_token(character)
                type_id = esi_characters.ship(
                    character.character_id,
                    access_token=character.access_token)
            except:
                return job_log.warn(
                    "removing user.refresh_character_ship {}".format(
                        character.character_name))

        if type_id is not None:
            item_id = type_id["ship_item_id"]
            type_id = type_id["ship_type_id"]

            eve_type = EVETypeModel.from_id(type_id)

            if len(character.ship_history
                   ) and character.ship_history[-1].eve_type == eve_type:
                # backoff
                if recurring <= 600:
                    recurring = recurring + 60
            else:
                recurring = 60

                eve_log.warn("{} boarded {}".format(character.character_name,
                                                    eve_type.eve_name))

                history_entry = CharacterShipHistory(character, eve_type)
                history_entry.eve_item_id = item_id

                session.add(history_entry)

            session.commit()

        if recurring:
            refresh_character_ship.apply_async(args=(character_id, recurring),
                                               countdown=recurring)
    except requests.exceptions.ConnectionError as e:
        self.retry(exc=e)
Beispiel #8
0
def refresh_character_corporation(self, character_id, recurring=3600):
    try:
        character = session.query(CharacterModel).filter(
            CharacterModel.id == character_id).one()

        job_log.debug("user.refresh_character_corporation {}".format(
            character.character_name))

        corporation_id = esi_characters.detail(character.character_id)

        if corporation_id is not None:
            corporation_id = corporation_id["corporation_id"]

            corporation = EVECorporationModel.from_id(corporation_id)

            if not len(character.corporation_history):
                # This character has no corp history at all
                session_entry = CharacterCorporationHistory(
                    character, corporation)
                session_entry.join_date = datetime.now(
                )  # XXX fetch this from the actual join date?
                session.add(session_entry)
                session.commit()
            elif len(
                    character.corporation_history
            ) and character.corporation_history[-1].corporation is corporation:
                # Character is still in the same corporation as the last time we checked, we need to do nothing
                pass
            elif len(character.corporation_history
                     ) and character.corporation_history[
                         -1].corporation is not corporation:
                # Character changed corporation, close the last one and create a new one
                previously = character.corporation_history[-1]
                previously.exit_date = datetime.now()

                currently = CharacterCorporationHistory(character, corporation)
                currently.join_date = datetime.now()

                session.add(currently)
                session.add(previously)

                session.commit()

                eve_log.warn("{} changed corporations {} -> {}".format(
                    character, previously.corporation, currently.corporation))

        if recurring:
            refresh_character_corporation.apply_async(args=(character_id,
                                                            recurring),
                                                      countdown=recurring)
    except requests.exceptions.ConnectionError as e:
        self.retry(exc=e)
Beispiel #9
0
def refresh_character_location(self, character_id, recurring=30):
    """Refresh a characters current location."""

    try:
        character = session.query(CharacterModel).filter(
            CharacterModel.id == character_id).one()

        job_log.debug("user.refresh_character_location {}".format(
            character.character_name))

        try:
            system_id = esi_characters.location(
                character.character_id, access_token=character.access_token)
        except (InvalidToken, ExpiredToken):
            try:
                refresh_access_token(character)
                system_id = esi_characters.location(
                    character.character_id,
                    access_token=character.access_token)
            except:
                return job_log.warn(
                    "removing user.refresh_character_ship {}".format(
                        character.character_name))

        if system_id is not None:
            system_id = system_id["solar_system_id"]
            system = EVESolarSystemModel.from_id(system_id)

            if len(character.location_history
                   ) and system.id == character.location_history[-1].system_id:
                # backoff
                if recurring < 300:
                    recurring = recurring + 30
            else:
                recurring = 30

                history_entry = CharacterLocationHistory(character, system)
                eve_log.warn("{} moved to {}".format(character.character_name,
                                                     system.eve_name))
                session.add(history_entry)

        session.commit()

        if recurring:
            refresh_character_location.apply_async(args=(character_id,
                                                         recurring),
                                                   countdown=recurring)
    except requests.exceptions.ConnectionError as e:
        self.retry(exc=e)
Beispiel #10
0
    async def post(self):
        membership = self.model_by_id(MembershipModel, "membership_id")

        group_id = membership.group.id

        for identity in membership.user.slack_identities:
            member = await slack.user_email_to_id(identity.email)
            await slack.group_kick(membership.group.slug, member)

        session.delete(membership)
        session.commit()

        self.flash_success(
            self.locale.translate("MEMBERSHIP_DENY_SUCCESS_ALERT"))
        self.redirect("/admin/groups/manage?group_id={}".format(group_id))
Beispiel #11
0
def refresh_character_skills(character_id, recurring=14400):
    character = session.query(CharacterModel).filter(
        CharacterModel.id == character_id).one()

    job_log.debug("user.refresh_character_skills {}".format(
        character.character_name))

    try:
        skills = esi_characters.skills(character.character_id,
                                       access_token=character.access_token)
    except InvalidToken:
        refresh_access_token(character)
        skills = esi_characters.skills(character.character_id,
                                       access_token=character.access_token)

    if "skills" in skills:
        skills = skills["skills"]

        for skill in skills:
            skill_id = skill["skill_id"]

            eveskill = EVESkillModel.from_id(skill_id)

            session.add(eveskill)

            skill_level = skill["current_skill_level"]
            skill_points = skill["skillpoints_in_skill"]

            characterskill = session.query(CharacterSkillModel).filter(
                CharacterSkillModel.character_id == character.id,
                CharacterSkillModel.eve_skill_id == eveskill.id).one_or_none()

            if characterskill is None:
                characterskill = CharacterSkillModel(character)
                characterskill.eve_skill = eveskill

            # XXX notify change?
            characterskill.level = skill_level
            characterskill.points = skill_points

            session.add(characterskill)

        session.commit()

    if recurring:
        refresh_character_corporation.apply_async(args=(character_id,
                                                        recurring),
                                                  countdown=recurring)
Beispiel #12
0
    async def post(self):
        # XXX check if already exists
        group = GroupModel()

        group.name = self.get_argument("group_name")
        group.slug = self.get_argument("group_slug")
        group.description = self.get_argument("group_description")
        group.has_slack = self.get_argument("group_has_slack")
        group.requires_approvial = self.get_argument("group_requires_approval")

        session.add(group)
        session.commit()

        self.flash_success(self.locale.translate("GROUP_ADD_SUCCESS_ALERT"))

        self.redirect("/admin/groups")
Beispiel #13
0
    async def post(self):
        slack_id = self.get_argument("slack_id", None)

        if not slack_id:
            raise tornado.web.HTTPError(400)

        slackidentity = SlackIdentityModel(slack_id.lower())
        slackidentity.user = self.current_user

        session.add(slackidentity)
        session.commit()

        sec_log.info("slackidentity {} added to {}".format(
            slackidentity, slackidentity.user))

        return self.redirect(
            "/services/add_slack_identity/success?slackidentity_id={id}".
            format(id=slackidentity.id))
Beispiel #14
0
def refresh_access_token(character):
    """Use a characters refresh token to request a new access token."""
    if character.refresh_token is None:
        app_log.warn("no refresh token for {}".format(character))
        return

    app_log.debug("refreshing access token for {}".format(
        character.character_name))

    client = tornado.httpclient.HTTPClient()
    request = tornado.httpclient.HTTPRequest(
        "https://login.eveonline.com/oauth/token",
        method="POST",
        headers={
            "Authorization": "Basic {}".format(sso_auth),
            "Content-Type": "application/json",
            "User-Agent": "Hard Knocks Inc. Authentication System"
        },
        body=json.dumps({
            "grant_type": "refresh_token",
            "refresh_token": character.refresh_token
        }))

    try:
        response = client.fetch(request)
        response = json.loads(response.body.decode("utf-8"))

        character.access_token = response["access_token"]

        session.add(character)
        session.commit()

        app_log.debug("got new access token for {}".format(character))
    except tornado.httpclient.HTTPError:
        app_log.info(
            "failed retrieving new access token for {}".format(character))

        character.access_token = None
        character.refresh_token = None

        session.add(character)
        session.commit()

        raise Exception("")  # XXX proper type
Beispiel #15
0
def refresh_group_members(group_id, recurring=60):
    """Refresh a group and kick any members that are not internal."""

    group = session.query(GroupModel).filter(GroupModel.id == group_id).one()

    job_log.debug("group.refresh_group_members {}".format(group))

    for membership in group.memberships:
        if not membership.user.is_internal:
            job_log.warn(
                "group.refresh_group_members removing {} from {} no_internal".
                format(membership.user, group))

            session.delete(membership)
            session.commit()

    if recurring:
        refresh_group_members.apply_async(args=(group_id, recurring),
                                          countdown=recurring)
Beispiel #16
0
    async def _add(self):
        character_id, character_scopes, access_token, refresh_token, account_hash = await self._sso_response(
        )

        # See if we already have this character
        character = session.query(CharacterModel).filter(
            CharacterModel.character_id == character_id).first()

        if character:  # XXX add new scopes
            if character.user == self.current_user:
                character.access_token = access_token
                character.refresh_token = refresh_token
                character.account_hash = account_hash

                # For our scopes we see if they already exist, if they
                # don't we create them and hang them on the character
                character.update_scopes(character_scopes)
            else:
                sec_log.warn(
                    "user {} tried to add {} but belongs to {}".format(
                        self.current_user, character, character.user))
                raise tornado.web.HTTPError(403)
        else:
            character = await self._create(character_id, character_scopes,
                                           access_token, refresh_token,
                                           account_hash)

        # Append the character to the currently logged in character
        self.current_user.characters.append(character)
        self.current_user.chg_date = datetime.now()

        session.add(self.current_user)
        session.commit()

        sec_log.info("added %s for %s" % (character, character.user))

        queue_user.setup_character(character)

        self.flash_success(
            self.locale.translate("CHARACTER_ADD_SUCCESS_ALERT"))

        self.redirect("/characters")
Beispiel #17
0
    async def post(self):
        group = self.model_by_id(GroupModel, "group_id")

        for membership in group.memberships:
            if membership.user == self.current_user:
                session.delete(membership)
                session.commit()

                break
        else:
            raise tornado.web.HTTPError(400)

        sec_log.info("user {} left group {}".format(membership.user,
                                                    membership.group))

        # XXX move to task
        #await slack.group_upkeep(group)

        return self.redirect("/groups/leave/success?group_id={}".format(
            group.id))
Beispiel #18
0
    async def post(self):
        group = self.model_by_id(GroupModel, "group_id")

        membership = MembershipModel()
        membership.user = self.current_user
        membership.group = group

        if group.requires_approval:
            membership.pending = True

        session.add(membership)
        session.commit()

        sec_log.info("user {} joined group {}".format(membership.user,
                                                      membership.group))

        # XXX move to task
        #await slack.group_upkeep(group)

        return self.redirect("/groups/join/success?membership_id={}".format(
            membership.id))
Beispiel #19
0
def refresh_character_ship(character_id, recurring=60):
    """Refresh a characters current ship."""
    character = session.query(CharacterModel).filter(
        CharacterModel.id == character_id).one()

    job_log.debug("user.refresh_character_ship {}".format(
        character.character_name))

    try:
        type_id = esi_characters.ship(character.character_id,
                                      access_token=character.access_token)
    except InvalidToken:
        refresh_access_token(character)
        type_id = esi_characters.ship(character.character_id,
                                      access_token=character.access_token)

    if type_id is not None:
        item_id = type_id["ship_item_id"]
        type_id = type_id["ship_type_id"]

        eve_type = EVETypeModel.from_id(type_id)

        if len(character.ship_history
               ) and character.ship_history[-1].eve_type == eve_type:
            pass
        else:
            eve_log.info("{} boarded {}".format(character.character_name,
                                                eve_type.eve_name))

            history_entry = CharacterShipHistory(character, eve_type)
            history_entry.eve_item_id = item_id

            session.add(history_entry)

        session.commit()

    if recurring:
        refresh_character_ship.apply_async(args=(character_id, recurring),
                                           countdown=recurring)
Beispiel #20
0
def refresh_character_location(character_id, recurring=30):
    """Refresh a characters current location."""

    character = session.query(CharacterModel).filter(
        CharacterModel.id == character_id).one()

    job_log.debug("user.refresh_character_location {}".format(
        character.character_name))

    try:
        system_id = esi_characters.location(
            character.character_id, access_token=character.access_token)
    except InvalidToken:
        refresh_access_token(character)
        system_id = esi_characters.location(
            character.character_id, access_token=character.access_token)

    if system_id is not None:
        system_id = system_id["solar_system_id"]
        system = EVESolarSystemModel.from_id(system_id)

        if len(character.location_history
               ) and system.id is character.location_history[-1].system_id:
            # don't update location history if the user is still in the same system
            pass
        else:
            history_entry = CharacterLocationHistory(character, system)
            eve_log.info("{} moved to {}".format(character.character_name,
                                                 system.eve_name))
            session.add(history_entry)

    session.commit()

    if recurring:
        refresh_character_location.apply_async(args=(character_id, recurring),
                                               countdown=recurring)
Beispiel #21
0
def refresh_character_skills(self, character_id, recurring=14400):
    try:
        character = session.query(CharacterModel).filter(
            CharacterModel.id == character_id).one()

        job_log.debug("user.refresh_character_skills {}".format(
            character.character_name))

        try:
            skills = esi_characters.skills(character.character_id,
                                           access_token=character.access_token)
        except (InvalidToken, ExpiredToken):
            try:
                refresh_access_token(character)
                skills = esi_characters.skills(
                    character.character_id,
                    access_token=character.access_token)
            except:
                return job_log.warn(
                    "removing user.refresh_character_ship {}".format(
                        character.character_name))

        if skills and "skills" in skills:  # XXX why can skills be None here?
            skills = skills["skills"]

            for skill in skills:
                skill_id = skill["skill_id"]

                eveskill = EVESkillModel.from_id(skill_id)

                session.add(eveskill)
                session.commit()

                skill_level = skill["current_skill_level"]
                skill_points = skill["skillpoints_in_skill"]

                characterskills = session.query(CharacterSkillModel).filter(
                    CharacterSkillModel.character_id == character.id).filter(
                        CharacterSkillModel.eve_skill_id == eveskill.id).all()

                # XXX why?
                for characterskill in characterskills:
                    session.delete(characterskill)

                session.commit()

                characterskill = CharacterSkillModel(character)
                characterskill.eve_skill = eveskill
                characterskill.level = skill_level
                characterskill.points = skill_points

                session.add(characterskill)

            session.commit()

        if recurring:
            refresh_character_skills.apply_async(args=(character_id,
                                                       recurring),
                                                 countdown=recurring)
    except requests.exceptions.ConnectionError as e:
        self.retry(exc=e)
Beispiel #22
0
 def prepare(self):
     session.commit()
Beispiel #23
0
    async def _login(self):
        character_id, character_scopes, access_token, refresh_token, account_hash = await self._sso_response(
        )

        # See if we already have this character
        character = session.query(CharacterModel).filter(
            CharacterModel.character_id == character_id).first()

        # The character already exists so we log in to the corresponding user
        # and redirect to the success page
        if character:
            if character.account_hash != account_hash:
                sec_log.critical(
                    "account hash for {} changed denying login".format(
                        character))
                raise tornado.web.HTTPError(400)

            sec_log.info("logged in {} through {}".format(
                character.user, character))
            self.set_current_user(character.user)

            login = UserLoginModel()
            login.user = character.user
            login.pub_date = datetime.now()
            login.ip_address = self.request.remote_ip

            session.add(login)
            session.commit()

            return self.redirect("/login/success")
        else:
            # We don't have an account with this character on it yet. Let's
            # fetch the character information from the XML API and fill it
            # into a model, tie it up to a fresh new user and log it in
            character = await self._create(character_id, character_scopes,
                                           access_token, refresh_token,
                                           account_hash)
            character.is_main = True
            character.pub_date = datetime.now()

            user = UserModel()
            user.characters.append(character)
            user.pub_date = datetime.now()
            user.chg_date = datetime.now()

            session.add(user)
            session.commit()

            self.set_current_user(user)

            sec_log.info("created %s through %s" % (character.user, character))

            login = UserLoginModel()
            login.user = character.user
            login.pub_date = datetime.now()
            login.ip_address = self.request.remote_ip

            session.add(login)
            session.commit()

            queue_user.setup_character(character)

            # Redirect to another page with some more information for the
            # user of what is going on
            return self.redirect("/login/created")