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))
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))
async def post(self): membership = self.model_by_id(MembershipModel, "membership_id") membership.pending = 0 session.add(membership) session.commit() self.flash_success( self.locale.translate("MEMBERSHIP_ALLOW_SUCCESS_ALERT")) self.redirect("/admin/groups/manage?group_id={}".format( membership.group.id))
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")
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)
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)
async def post(self): membership = self.model_by_id(MembershipModel, "membership_id") membership.pending = 0 for identity in membership.user.slack_identities: member = await slack.user_email_to_id(identity.email) await slack.group_invite(membership.group.slug, member) session.add(membership) session.commit() self.flash_success( self.locale.translate("MEMBERSHIP_ALLOW_SUCCESS_ALERT")) self.redirect("/admin/groups/manage?group_id={}".format( membership.group.id))
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)
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")
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))
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
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")
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))
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)
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)
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)
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)
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")