def is_char_banned(char: Character) -> Tuple[bool, str]: try: corp_id, alli_id = outgate.character.get_affiliations( char.get_eve_id()) # if he is on whitelist let him pass char_banned = char.banned corp_banned = is_charid_banned(corp_id) alli_banned = is_charid_banned(alli_id) if is_charid_whitelisted(char.get_eve_id()): return False, "" if char_banned: return True, "Character" if is_charid_whitelisted(corp_id): return False, "" if corp_banned: return True, "Corporation" if is_charid_whitelisted(alli_id): return False, "" if alli_banned: return True, "Alliance" return False, "" except Exception: logger.error("Failed to check if %d was banned", char.get_eve_id(), exc_info=1) return False, ""
def create_new_character(eve_id: int, char_name: str) -> Character: char = Character() char.id = eve_id char.eve_name = char_name char.newbro = True db.session.add(char) db.session.commit() return char
def make_json_character(dbcharacter: Character, scramble_names: bool = False, include_names_from: Optionalcharids = None): return { 'id': dbcharacter.get_eve_id() if not scramble_names or ( include_names_from is not None and dbcharacter.get_eve_id() in include_names_from) else None, 'name': dbcharacter.get_eve_name() if not scramble_names or ( include_names_from is not None and dbcharacter.get_eve_id() in include_names_from) else 'Name Hidden', 'newbro': dbcharacter.is_new }
def is_char_banned(char: Character) -> Tuple[bool, str]: try: if is_charid_whitelisted(char.get_eve_id()): return False, "" if char.banned: return True, "Character" corp_id, alli_id = outgate.character.get_affiliations( char.get_eve_id()) if banned_by_default: if is_charid_whitelisted(corp_id): return False, "" if is_charid_banned(corp_id): return True, "Corporation" if is_charid_whitelisted(alli_id): return False, "" return True, "Everyone Banned by default" else: corp_banned = is_charid_banned(corp_id) alli_banned = is_charid_banned(alli_id) if is_charid_whitelisted(corp_id): return False, "" if corp_banned: return True, "Corporation" if is_charid_whitelisted(alli_id): return False, "" if alli_banned: return True, "Alliance" return False, "" except ApiException as e: logger.info( "Failed to check if %d was banned, because of Api error, code=%d msg=%s", char.get_eve_id(), e.code, e.msg) return False, "" except Exception: logger.error("Failed to check if %d was banned", char.get_eve_id(), exc_info=1) return False, ""
def account_self_edit(): acc_id = current_user.id char_name = request.form['default_char_name'] char_name = char_name.strip() if char_name == "": char_name = None acc = db.session.query(Account).filter(Account.id == acc_id).first() if acc is None: return flask.abort(400) if char_name is not None: char_info = outgate.character.get_info_by_name(char_name) if char_info is None: flash("Character with name {char_name} could not be found!") else: char_id = char_info.id # find out if there is a character like that in the database character = db.session.query(Character).filter( Character.id == char_id).first() if character is None: # lets make sure we have the correct name (case) char_info: APICacheCharacterInfo = outgate.character.get_info( char_id) character = Character() character.eve_name = char_info.characterName character.id = char_id # check if character is linked to this account link = db.session.query(linked_chars) \ .filter((linked_chars.c.id == acc_id) & (linked_chars.c.char_id == char_id)).first() if link is None: acc.characters.append(character) db.session.flush() if acc.current_char != char_id: # remove all the access tokens if acc.ssoToken is not None: db.session.delete(acc.ssoToken) acc.current_char = char_id db.session.commit() return redirect(url_for('.account_self'), code=303)
def login_account_by_username_or_character(char: Character, owner_hash: str, token: SSOToken) -> Response: """ Handle login, when accounts should be loggedin by username matching the character name :param char: Character we got the authentication for :param owner_hash: current owner_hash of the character :param token: sso token for the character :return: a Response that should be delivered to the client """ # see if there is an fc account connected # noinspection PyPep8 acc = db.session.query( Account).filter((Account.username == char.get_eve_name()) & (Account.disabled == False)).first() if acc is not None: # accs are allowed to ignore bans logger.debug(f"Account with username %s found. Logging in as %s", char.get_eve_name(), acc) return login_account(acc, token) logger.debug(f"No Account with username %s found. Logging in as %s", char.get_eve_name(), char) return login_character(char, owner_hash, token)
def login_character(char: Character, owner_hash: str, token: SSOToken) -> Response: """ Login a character and update the owner_hash/invalidate all existing sessions if the owner_hash changed This also checks if the character is banned before letting him login :param char: the Character to login :param owner_hash: the owner_hash to check and update :param token: sso token for the character :return: a redirect to the next page the client should visite """ # update owner_hash if different # if the owner_hash is empty or None, this ist he first timet he character is accessed if char.owner_hash is None or char.owner_hash == '': char.owner_hash = owner_hash db.session.commit() # if the hash is there but different the owner changed we need to invalidate sessions and update elif char.owner_hash != owner_hash: char.owner_hash = owner_hash invalidate_all_sessions_for_given_user(char) db.session.commit() tokens = char.get_sso_tokens_with_scopes(['publicData']) for tkn in tokens: revoke(refresh_token=tkn.refresh_token) logger.debug('Revoked %s', tkn) db.session.delete(tkn) db.session.flush() char.add_sso_token(token) db.session.commit() logger.info( f"Logging character eve_name={char.get_eve_name()} id={char.get_eve_id()} in" ) is_banned, reason = is_char_banned(char) if is_banned: logger.info( f"Character is banned eve_name={char.get_eve_name()} id={char.get_eve_id()}" ) flask.abort(401, 'You are banned, because your ' + reason + " is banned!") login_user(char, remember=True) logger.debug("Member Login by %s successful", char.get_eve_name()) return redirect(url_for("index"))
char_name = "--" list_eveids = [] while char_name: char_name = input("Enter Character to associate with this account:") char_name = char_name.strip() if not char_name: break char_info: Optional[APICacheCharacterInfo] = outgate.character.get_info_by_name(char_name) char_id = char_info.id # assign this too because his name could have had wrong case char_name = char_info.characterName character: Character = db.session.query(Character).get(char_id) if character is None: character = Character() character.eve_name = char_name character.id = char_id print("Added "+character.__repr__()) list_eveids.append(char_id) acc.characters.append(character) db.session.commit() is_valid = False char_id = None while not is_valid: char_id = int(input("Enter charid to set as active char out of "+", ".join([str(i) for i in list_eveids])+":")) for posid in list_eveids: if posid == char_id:
def login_accounts_by_alts_or_character(char: Character, owner_hash: str, token: SSOToken) -> Response: """ Handle login, when an account should be loggedin by a connected alt who has no owner_hash or the owner_hash matches the current one If no matching account is found or more then one account is found, login as user and use flash for a message :param char: Character we got the authentication for :param owner_hash: current owner_hash of the character :param token: sso token for the character :return: a Response that should be delivered to the client """ # lets check if there is any accounts connected logger.info(f"{len(char.accounts)} accounts connected with this character") account_count = len(char.accounts) # if there is no account connected, login as character if account_count == 0: return login_character(char, owner_hash, token) if account_count > 0: # if we never had a owner hash lets set it # it doesn't matter since we need to auth all characters for existing accounts if char.owner_hash is None or char.owner_hash == "": logger.debug( "Character owner_hash is empty, %s is accessed for the first time." " Setting owner_hash to %s", char, owner_hash) char.owner_hash = owner_hash db.session.commit() # character changed owner, so not eligible for account login anymore if char.owner_hash != owner_hash: logger.debug( "Character owner_hash for %s did not match." " Invalidating all sessions and removing character as alt from all accounts.", char) flask.flash( gettext("You character seemed to have changed owner." + " You where removed as eligible character " + "for account login."), 'danger') invalidate_all_sessions_for_given_user(char) if len(char.accounts) > 0: # TODO: send signal here that an alt is removed from this account for acc in char.accounts: send_alt_link_removed(login_accounts_by_alts_or_character, None, acc.id, char.id) char.accounts = [] db.session.commit() return login_character(char, owner_hash, token) else: logger.debug("Character owner_hash for %s did match", char) if len( char.accounts ) > 1: # this character is connected with more then 1 account logger.error( "%s connected to multiple accounts, logging in as character.", char) flask.flash( gettext( "Your character %(eve_name)s is connected" " to more than one Waitlist Account," " please contact an Administrator." " Meanwhile, you are logged in as" " a normal character.", eve_name=char.get_eve_name()), "danger") return login_character(char, owner_hash, token) else: # connected exactly one account since > 0 and not > 1 logger.debug("%s connected to one account", char) acc = char.accounts[0] if acc.disabled: # this account is disabled -> login as character logger.debug( "The Account %s is disabled logging in a character", acc) return login_character(char, owner_hash, token) # set no character as active char for the account # we will set the login char further in the progress # or we will send to reauth if there is no proper api token acc.current_char = char.id return login_account(acc, token) else: # not connected to an account return login_character(char, owner_hash, token)
def accounts(): if request.method == "POST": acc_name = request.form['account_name'] acc_roles = request.form.getlist('account_roles') char_name = request.form['default_char_name'] char_name = char_name.strip() note = request.form['change_note'].strip() char_info = outgate.character.get_info_by_name(char_name) if char_info is None: flash(f"A Character named {char_name} does not exist!") else: char_id = char_info.id acc = Account() acc.username = acc_name acc.login_token = get_random_token(16) if len(acc_roles) > 0: db_roles = db.session.query(Role).filter( or_(Role.name == name for name in acc_roles)).all() for role in db_roles: acc.roles.append(role) db.session.add(acc) # find out if there is a character like that in the database character = db.session.query(Character).filter( Character.id == char_id).first() if character is None: char_info: APICacheCharacterInfo = outgate.character.get_info( char_id) character = Character() character.eve_name = char_info.characterName character.id = char_id acc.characters.append(character) db.session.flush() acc.current_char = char_id db.session.commit() send_account_created(accounts, acc.id, current_user.id, acc_roles, 'Creating account. ' + note) roles = db.session.query(Role).order_by(Role.name).all() accs = db.session.query(Account).order_by(asc(Account.disabled)).order_by( Account.username).all() mails = { 'resident': [sget_resident_mail(), sget_resident_topic()], 'tbadge': [sget_tbadge_mail(), sget_tbadge_topic()], 'other': [sget_other_mail(), sget_other_topic()] } return render_template("settings/accounts.html", roles=roles, accounts=accs, mails=mails)
def account_edit(): acc_id = int(request.form['account_id']) acc_name = request.form['account_name'] note = request.form['change_note'].strip() acc_roles = request.form.getlist('account_roles') char_name = request.form['default_char_name'] char_name = char_name.strip() if char_name == "": char_name = None acc = db.session.query(Account).filter(Account.id == acc_id).first() if acc is None: return flask.abort(400) if acc.username != acc_name: acc.username = acc_name # if there are roles, add new ones, remove the ones that aren't there if len(acc_roles) > 0: roles_new = {} for r in acc_roles: roles_new[r] = True # db_roles = session.query(Role).filter(or_(Role.name == name for name in acc_roles)).all() roles_to_remove = [] for role in acc.roles: if role.name in roles_new: del roles_new[ role.name] # remove because it is already in the db else: # remove the roles because it not submitted anymore # only remove admin if current user is an admin if role.name == StaticRoles.ADMIN and not perm_manager.get_permission( StaticPermissions.ADMIN).can(): continue roles_to_remove.append(role) # mark for removal for role in roles_to_remove: acc.roles.remove(role) # if it is not an admin remove admin role from new roles if not perm_manager.get_permission('admin').can(): if 'admin' in roles_new: del roles_new['admin'] # add remaining roles if len(roles_new) > 0: new_db_roles = db.session.query(Role).filter( or_(Role.name == name for name in roles_new)) for role in new_db_roles: acc.roles.append(role) if len(roles_new) > 0 or len(roles_to_remove) > 0: send_roles_changed(account_edit, acc.id, current_user.id, [x for x in roles_new], [x.name for x in roles_to_remove], note) else: # make sure all roles are removed roles_to_remove = [] for role in acc.roles: # only remove admin if current user is an admin if role.name == StaticRoles.ADMIN and not perm_manager.get_permission( StaticPermissions.ADMIN).can(): continue roles_to_remove.append(role) if len(roles_to_remove) > 0: for role in roles_to_remove: acc.roles.remove(role) db.session.flush() send_roles_changed(account_edit, acc.id, current_user.id, [], [x.name for x in roles_to_remove], note) if char_name is not None: char_info = outgate.character.get_info_by_name(char_name) if char_info is None: flash(f"Character with name {char_name} could not be found!") else: char_id = char_info.id # find out if there is a character like that in the database character = db.session.query(Character).filter( Character.id == char_id).first() if character is None: # lets make sure we have the correct name (case) char_info: APICacheCharacterInfo = outgate.character.get_info( char_id) character = Character() character.eve_name = char_info.characterName character.id = char_id # check if character is linked to this account link = db.session.query(linked_chars) \ .filter((linked_chars.c.id == acc_id) & (linked_chars.c.char_id == char_id)).first() if link is None: acc.characters.append(character) db.session.flush() acc.current_char = char_id db.session.commit() return redirect(url_for('.accounts'), code=303)