From a641bd2b65045c162e60cfe52ed21aaddce28fcd Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 10 Dec 2015 14:47:30 +0000 Subject: [PATCH 01/35] Fixes #220 Characters uppdate only when API key does not incur errors for #219 --- celerytask/tasks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 8b220a51..34c126e0 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -312,6 +312,7 @@ def run_api_refresh(): oldcorp_id = 0 if EveManager.get_character_by_id(authserviceinfo.main_char_id): oldcorp_id = EveCharacter.objects.get(character_id=authserviceinfo.main_char_id).corporation_id + oldcorp_name = EveCharacter.objects.get(character_id=authserviceinfo.main_char_id).corporation_name logger.debug("Determined user %s current main corp id %s" % (user, oldcorp_id)) for api_key_pair in api_key_pairs: logger.debug("Running update on api key %s" % api_key_pair.api_id) @@ -367,7 +368,7 @@ def run_api_refresh(): logger.debug("API key %s has failed validation; it and its characters will be deleted." % api_key_pair.api_id) EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id) EveManager.delete_api_key_pair(api_key_pair.api_id, user.id) - else: + elif still_valid == True: if api_key_pair.error_count != 0: logger.info("Clearing error count for api %s as it passed validation" % api_key_pair.api_id) api_key_pair.error_count = 0 @@ -420,8 +421,7 @@ def run_api_refresh(): elif corp.corporation_id != oldcorp_id: #changed corps, both corps auth'd, need to change group assignment logger.debug("User %s main character changed corp from id %s to %s, both meet membership requirements. Updating corp group." % (user, oldcorp_id, corp.corporation_id)) - oldcorp = EveCorporationInfo.objects.get(corporation_id=oldcorp_id) - remove_user_from_group(user, generate_corp_group_name(oldcorp.corporation_name)) + remove_user_from_group(user, generate_corp_group_name(oldcorp_name)) add_user_to_group(user, generate_corp_group_name(character.corporation_name)) #reset services to force new mumble names and group assignments deactivate_services(user) From d4b9186c61ee14dda6a3d9054c01c19eaa00b258 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Fri, 11 Dec 2015 12:50:30 +0000 Subject: [PATCH 02/35] API form validates by member and characters Functions to determine membership level of user and eve characters --- celerytask/tasks.py | 99 ++++++++++++++++++++++++++++ eveonline/forms.py | 54 +++++++-------- eveonline/views.py | 6 +- services/managers/eve_api_manager.py | 23 +++++++ 4 files changed, 150 insertions(+), 32 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 8b220a51..5c776c4c 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -260,6 +260,105 @@ def remove_from_databases(user, groups, syncgroups): logger.debug("User %s has discord uid %s - updating groups." % (user, authserviceinfo.discord_uid)) update_discord_groups(user) +def make_member(user): + logger.debug("Ensuring user %s has member permissions and groups." % user) + # ensure member is not blue right now + if check_if_user_has_permission(user, 'blue_member'): + logger.info("Removing user %s blue permission to transition to member" % user) + remove_member_permission(user, 'blue_member') + blue_group, c = Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP) + if blue_group in user.groups.all(): + logger.info("Removing user %s blue group" % user) + user.groups.remove(blue_group) + # make member + if check_if_user_has_permission(user, 'member') is False: + logger.info("Adding user %s member permission" % user) + add_member_permission(user, 'member') + member_group, c = Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP) + if member_group in user.groups.all() is False: + logger.info("Adding user %s to member group" % user) + user.groups.add(member_group) + auth, c = AuthServicesInfo.objects.get_or_create(user=user) + if auth.is_blue: + logger.info("Marking user %s as non-blue" % user) + auth.is_blue = False + auth.save() + if auth.main_character_id: + if EveCharacter.objects.filter(character_id=auth.main_character_id).exists(): + char = EveCharacter.objects.get(character_id=auth.main_character_id) + corpname = generate_corp_group_name(char.corporation_name) + corp_group, c = Group.objects.get_or_create(name=corpname) + if not corp_group in user.groups.all(): + logger.info("Adding user %s to corp group %s" % (user, corp_group)) + user.groups.add(corp_group) + for g in user.groups.all(): + if str.startswith(g.name, "Corp_"): + if g != corp_group: + logger.info("Removing user %s from old corpgroup %s" % (user, g)) + user.groups.remove(g) + +def make_blue(user): + logger.debug("Ensuring user %s has blue permissions and groups." % user) + # ensure user is not a member + if check_if_user_has_permission(user, 'member'): + logger.info("Removing user %s member permission to transition to blue" % user) + remove_member_permission(user, 'blue_member') + member_group, c = Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP) + if member_group in user.groups.all(): + logger.info("Removing user %s member group" % user) + user.groups.remove(member_group) + # make blue + if check_if_user_has_permission(user, 'blue_member') is False: + logger.info("Adding user %s blue permission" % user) + add_member_permission(user, 'blue_member') + blue_group, c = Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP) + if blue_group in user.groups.all() is False: + logger.info("Adding user %s to blue group" % user) + user.groups.add(blue_group) + auth, c = AuthServicesInfo.objects.get_or_create(user=user) + if auth.is_blue is False: + logger.info("Marking user %s as blue" % user) + auth.is_blue = True + auth.save() + for g in user.groups.all(): + if str.startswith(g.name, 'Corp_'): + logger.info("Removing blue user %s from corp group %s" % (user, g)) + user.groups.remove(g) + +def determine_membership_by_character(char): + if settings.IS_CORP: + if char.corporation_id == settings.CORP_ID: + logger.debug("User %s main character %s in owning corp id %s" % (user, char, char.corporation_id)) + return "MEMBER" + else: + if char.alliance_id == settings.ALLIANCE_ID: + logger.debug("User %s main character %s in owning alliance id %s" % (user, char, char.alliance_id)) + return "MEMBER" + if EveCorporation.objects.filter(corporation_id=char.corporation_id).exists() is False: + logger.debug("No corp model for user %s main character %s corp id %s. Unable to check standings. Non-member." % (user, char, char.corporation_id)) + return False + else: + corp = EveCorporation.objects.get(corporation_id=char.corporation_id) + if corp.is_blue: + logger.debug("User %s main character %s member of blue corp %s" % (user, char, corp)) + return "BLUE" + else: + logger.debug("User %s main character %s member of non-blue corp %s. Non-member." % (user, char, corp)) + return False + +def determine_membership_by_user(user): + logger.debug("Determining membership of user %s" % user) + auth, c = AuthServicesInfo.objects.get_or_create(user=user) + if auth.main_character_id: + if EveCharacter.objects.filter(character_id=auth.main_character_id).exists(): + char = EveCharacter.objects.get(character_id=auth.main_character_id) + return determine_membership_by_character(char) + else: + logger.debug("Character model matching user %s main character id %s does not exist. Non-member." % (user, auth.main_character_id)) + return False + else: + logger.debug("User %s has no main character set. Non-member." % user) + return False # Run every minute @periodic_task(run_every=crontab(minute="*/1")) diff --git a/eveonline/forms.py b/eveonline/forms.py index 5eddf39f..4fbbcbe1 100644 --- a/eveonline/forms.py +++ b/eveonline/forms.py @@ -3,49 +3,43 @@ from django.conf import settings from services.managers.eve_api_manager import EveApiManager from eveonline.managers import EveManager +from eveonline.models import EveCharacter + +from celerytask.tasks import determine_membership_by_character import logging logger = logging.getLogger(__name__) class UpdateKeyForm(forms.Form): + def __init__(self, user_state=None, *args, **kwargs): + super(UpdateKeyForm, self).__init__(args, kwargs) + self.user_state=user_state + api_id = forms.CharField(max_length=254, required=True, label="Key ID") api_key = forms.CharField(max_length=254, required=True, label="Verification Code") - is_blue = forms.BooleanField(label="Blue to corp/alliance", required=False) def clean(self): if EveManager.check_if_api_key_pair_exist(self.cleaned_data['api_id']): logger.debug("UpdateKeyForm failed cleaning as API id %s already exists." % self.cleaned_data['api_id']) raise forms.ValidationError(u'API key already exist') - check_blue = False - try: - check_blue = self.cleaned_data['is_blue'] - except: - pass - - if check_blue: - if settings.BLUE_API_ACCOUNT: - if not EveApiManager.check_api_is_type_account(self.cleaned_data['api_id'], - self.cleaned_data['api_key']): - logger.debug("UpdateKeyForm failed cleaning as API id %s does not meet blue api key account requirement." % self.cleaned_data['api_id']) - raise forms.ValidationError(u'API not of type account') - - if not EveApiManager.check_blue_api_is_full(self.cleaned_data['api_id'], - self.cleaned_data['api_key']): - logger.debug("UpdateKeyForm failed cleaning as API id %s does not meet minimum blue api access mask requirement." % self.cleaned_data['api_id']) - raise forms.ValidationError(u'API supplied is too restricted. Minimum access mask is ' + str(settings.BLUE_API_MASK)) - - else: - if settings.MEMBER_API_ACCOUNT: - if not EveApiManager.check_api_is_type_account(self.cleaned_data['api_id'], - self.cleaned_data['api_key']): - logger.debug("UpdateKeyForm failed cleaning as API id %s does not meet member api key account requirement." % self.cleaned_data['api_id']) - raise forms.ValidationError(u'API not of type account') - - if not EveApiManager.check_api_is_full(self.cleaned_data['api_id'], - self.cleaned_data['api_key']): - logger.debug("UpdateKeyForm failed cleaning as API id %s does not meet minimum member api access mask requirement." % self.cleaned_data['api_id']) - raise forms.ValidationError(u'API supplied is too restricted. Minimum access mask is ' + str(settings.MEMBER_API_MASK)) + chars = EveApiManager.get_characters_from_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']).result + states = [] + states.append(self.user_state) + for char in chars: + evechar = EveCharacter() + evechar.character_name = chars[char]['name'] + evechar.corporation_id = chars[char]['corp']['id'] + evechar.alliance_id = chars[char]['alliance']['id'] + state = determine_membership_by_character(evechar) + logger.debug("API ID %s character %s has state %s" % (self.cleaned_data['api_id'], evechar, state) + states.append(state) + if 'MEMBER' in states: + if EveApiManager.validate_member_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: + raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s" % (settings.MEMBER_API_ACCOUNT, settings.MEMBER_API_MASK) + if 'BLUE' in states: + if EveApiManager.validate_blue_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: + raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s" % (settings.BLUE_API_ACCOUNT, settings.BLUE_API_MASK) return self.cleaned_data diff --git a/eveonline/views.py b/eveonline/views.py index fc9ed613..1d3db1a9 100755 --- a/eveonline/views.py +++ b/eveonline/views.py @@ -20,6 +20,7 @@ from eveonline.models import EveCorporationInfo from eveonline.models import EveCharacter from eveonline.models import EveApiKeyPair from authentication.models import AuthServicesInfo +from celerytask.tasks import determine_membership_by_user import logging @@ -46,8 +47,9 @@ def disable_blue_member(user): @login_required def add_api_key(request): logger.debug("add_api_key called by user %s" % request.user) + user_state = determine_membership_by_user(request.user) if request.method == 'POST': - form = UpdateKeyForm(request.POST) + form = UpdateKeyForm(request.POST, user_state=user_state) logger.debug("Request type POST with form valid: %s" % form.is_valid()) if form.is_valid(): EveManager.create_api_keypair(form.cleaned_data['api_id'], @@ -64,7 +66,7 @@ def add_api_key(request): logger.debug("Form invalid: returning to form.") else: logger.debug("Providing empty update key form for user %s" % request.user) - form = UpdateKeyForm() + form = UpdateKeyForm(user_state=user_state) context = {'form': form, 'apikeypairs': EveManager.get_api_key_pairs(request.user.id)} return render_to_response('registered/addapikey.html', context, context_instance=RequestContext(request)) diff --git a/services/managers/eve_api_manager.py b/services/managers/eve_api_manager.py index ce5650c4..6d6f75d3 100644 --- a/services/managers/eve_api_manager.py +++ b/services/managers/eve_api_manager.py @@ -267,3 +267,26 @@ class EveApiManager(): return False logger.warn("Exception prevented verification of corp id %s existance. Assuming false." % corp_id) return False + + @staticmethod + def validate_member_api(api_id, api_key): + if settings.MEMBER_API_ACCOUNT: + if EveApiManager.check_if_api_is_type_account(api_id, api_key) is not True: + logger.debug("Api id %s is not type account as required for members - failed validation." % api_id) + return False + + if EveApiManager.check_api_is_full(api_id, api_key) is not True: + logger.debug("Api id %s does not meet member access mask requirements - failed validation." % api_id) + return False + return True + + @staticmethod + def validate_blue_api(api_id, api_key): + if settings.BLUE_API_ACCOUNT: + if EveApiManager.check_if_api_is_type_account(api_id, api_key) is not True: + logger.debug("Api id %s is not type account as required for blues - failed validation." % api_id) + return False + if EveApiManager.check_blue_api_is_full(api_id, api_key) is not True: + logger.debug("Api id %s does not meet minimum blue access mask requirements - failed validation." % api_id) + return False + return True From 696483baa66b90ed87a206bb6c4aa411e9da2e63 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Fri, 11 Dec 2015 13:28:51 +0000 Subject: [PATCH 03/35] Updated API refresh to assign states properly Corrected form comments --- celerytask/tasks.py | 297 +++++++++++++++----------------------------- eveonline/forms.py | 6 +- 2 files changed, 102 insertions(+), 201 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 1d621f5e..75fe51e9 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -31,31 +31,15 @@ import logging logger = logging.getLogger(__name__) -def disable_alliance_member(user, char_id): - logger.debug("Disabling alliance member %s" % user) - remove_member_permission(user, 'member') - remove_user_from_group(user, settings.DEFAULT_AUTH_GROUP) - remove_user_from_group(user, - generate_corp_group_name( - EveManager.get_character_by_id(char_id).corporation_name)) +def disable_member(user, char_id): + logger.debug("Disabling member %s" % user) + if user.user_permissions.all().exists(): + logger.info("Clearning user %s permission to deactivate user." % user) + user.user_permissions.clear() + if user.groups.all().exists(): + logger.info("Clearing user %s groups to deactivate user." % user) + user.groups.clear() deactivate_services(user) - logger.info("Disabled alliance member %s" % user) - -def disable_expired_member(user): - logger.debug("Disabling expired member %s" % user) - deactivate_services(user) - user.user_permissions.clear() - user.groups.clear() - user.save() - logger.info("Disabled expired member %s" % user) - -def disable_blue_member(user): - logger.debug("Disabling blue member %s" % user) - remove_member_permission(user, 'blue_member') - remove_user_from_group(user, settings.DEFAULT_BLUE_GROUP) - deactivate_services(user) - AuthServicesInfoManager.update_is_blue(False, user) - logger.info("Disabled blue member %s" % user) def is_teamspeak3_active(): return settings.ENABLE_AUTH_TEAMSPEAK3 or settings.ENABLE_BLUE_TEAMSPEAK3 @@ -283,9 +267,9 @@ def make_member(user): logger.info("Marking user %s as non-blue" % user) auth.is_blue = False auth.save() - if auth.main_character_id: - if EveCharacter.objects.filter(character_id=auth.main_character_id).exists(): - char = EveCharacter.objects.get(character_id=auth.main_character_id) + if auth.main_char_id: + if EveCharacter.objects.filter(character_id=auth.main_char_id).exists(): + char = EveCharacter.objects.get(character_id=auth.main_char_id) corpname = generate_corp_group_name(char.corporation_name) corp_group, c = Group.objects.get_or_create(name=corpname) if not corp_group in user.groups.all(): @@ -349,9 +333,9 @@ def determine_membership_by_character(char): def determine_membership_by_user(user): logger.debug("Determining membership of user %s" % user) auth, c = AuthServicesInfo.objects.get_or_create(user=user) - if auth.main_character_id: - if EveCharacter.objects.filter(character_id=auth.main_character_id).exists(): - char = EveCharacter.objects.get(character_id=auth.main_character_id) + if auth.main_char_id: + if EveCharacter.objects.filter(character_id=auth.main_char_id).exists(): + char = EveCharacter.objects.get(character_id=auth.main_char_id) return determine_membership_by_character(char) else: logger.debug("Character model matching user %s main character id %s does not exist. Non-member." % (user, auth.main_character_id)) @@ -402,178 +386,95 @@ def run_api_refresh(): logger.debug("User %s has api key pairs %s" % (user, api_key_pairs)) if api_key_pairs: valid_key = False - authserviceinfo = AuthServicesInfo.objects.get(user=user) - + authserviceinfo, c = AuthServicesInfo.objects.get_or_create(user=user) logger.debug("User %s has api keys. Proceeding to refresh." % user) - if authserviceinfo.main_char_id: - if authserviceinfo.main_char_id != "": - #preserve old corp ID for corp change test on members - oldcorp_id = 0 - if EveManager.get_character_by_id(authserviceinfo.main_char_id): - oldcorp_id = EveCharacter.objects.get(character_id=authserviceinfo.main_char_id).corporation_id - oldcorp_name = EveCharacter.objects.get(character_id=authserviceinfo.main_char_id).corporation_name - logger.debug("Determined user %s current main corp id %s" % (user, oldcorp_id)) - for api_key_pair in api_key_pairs: - logger.debug("Running update on api key %s" % api_key_pair.api_id) - if EveApiManager.api_key_is_valid(api_key_pair.api_id, api_key_pair.api_key): - #check to ensure API key meets min spec - logger.info("Determined api key %s is still active." % api_key_pair.api_id) - still_valid = True - if authserviceinfo.is_blue: - if settings.BLUE_API_ACCOUNT: - type = EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key) - if type == None: - api_key_pair.error_count += 1 - api_key_pair.save() - logger.info("API key %s incurred an error checking if type account. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) - still_valid = None - elif type == False: - logger.info("Determined api key %s for blue user %s is no longer type account as requred." % (api_key_pair.api_id, user)) - still_valid = False - full = EveApiManager.check_blue_api_is_full(api_key_pair.api_id, api_key_pair.api_key) - if full == None: - api_key_pair.error_count += 1 - api_key_pair.save() - logger.info("API key %s incurred an error checking if meets mask requirements. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) - still_valid = None - elif full == False: - logger.info("Determined api key %s for blue user %s no longer meets minimum access mask as required." % (api_key_pair.api_id, user)) - still_valid = False - else: - if settings.MEMBER_API_ACCOUNT: - type = EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key) - if type == None: - api_key_pair.error_count += 1 - api_key_pair.save() - logger.info("API key %s incurred an error checking if type account. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) - still_valid = None - elif type == False: - logger.info("Determined api key %s for user %s is no longer type account as required." % (api_key_pair.api_id, user)) - still_valid = False - full = EveApiManager.check_api_is_full(api_key_pair.api_id, api_key_pair.api_key) - if full == None: - api_key_pair.error_count += 1 - api_key_pair.save() - logger.info("API key %s incurred an error checking if meets mask requirements. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) - still_valid = None - elif full == False: - logger.info("Determined api key %s for user %s no longer meets minimum access mask as required." % (api_key_pair.api_id, user)) - still_valid = False - if still_valid == None: - if api_key_pair.error_count >= 3: - logger.info("API key %s has incurred 3 or more errors. Assuming invalid." % api_key_pair.api_id) - still_valid = False - if still_valid == False: - logger.debug("API key %s has failed validation; it and its characters will be deleted." % api_key_pair.api_id) - EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id) - EveManager.delete_api_key_pair(api_key_pair.api_id, user.id) - elif still_valid == True: - if api_key_pair.error_count != 0: - logger.info("Clearing error count for api %s as it passed validation" % api_key_pair.api_id) - api_key_pair.error_count = 0 - api_key_pair.save() - logger.info("Determined api key %s still meets requirements." % api_key_pair.api_id) - # Update characters - characters = EveApiManager.get_characters_from_api(api_key_pair.api_id, - api_key_pair.api_key) - EveManager.update_characters_from_list(characters) - new_character = False - for char in characters.result: - # Ensure we have a model for all characters on key - if not EveManager.check_if_character_exist(characters.result[char]['name']): - new_character = True - logger.debug("API key %s has a new character on the account: %s" % (api_key_pair.api_id, characters.result[char]['name'])) - if new_character: - logger.debug("Creating new character %s from api key %s" % (characters.result[char]['name'], api_key_pair.api_id)) - EveManager.create_characters_from_list(characters, user, api_key_pair.api_key) - valid_key = True - else: - logger.debug("API key %s is no longer active; it and its characters will be deleted." % api_key_pair.api_id) - EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id) - EveManager.delete_api_key_pair(api_key_pair.api_id, user.id) - - if valid_key: - # Check our main character - character = EveManager.get_character_by_id(authserviceinfo.main_char_id) - logger.debug("User %s has valid api key, checking main character %s" % (user, character)) - if character is not None and EveManager.check_if_corporation_exists_by_id(character.corporation_id): - corp = EveManager.get_corporation_info_by_id(character.corporation_id) - main_corp_id = EveManager.get_charater_corporation_id_by_id(authserviceinfo.main_char_id) - main_alliance_id = EveManager.get_charater_alliance_id_by_id(authserviceinfo.main_char_id) - logger.debug("User %s main character %s has corp %s with alliance id %s" % (user, character, corp, main_alliance_id)) - if (settings.IS_CORP and main_corp_id == settings.CORP_ID) or (not settings.IS_CORP and main_alliance_id == settings.ALLIANCE_ID): - logger.debug("User %s corp or alliance meets membership requirements. Ensuring has required permissions and groups." % user) - if not check_if_user_has_permission(user, "member"): - #transition from none or blue to member - if check_if_user_has_permission(user, "blue_member"): - #strip blue status - logger.debug("Removing user %s blue permission and group to prepare for member transition." % user) - remove_member_permission(user, "blue_member") - remove_user_from_group(user, settings.DEFAULT_BLUE_GROUP) - AuthServicesInfoManager.update_is_blue(False, user) - #add to auth group - add_member_permission(user, "member") - add_user_to_group(user, settings.DEFAULT_AUTH_GROUP) - #add to required corp group - add_user_to_group(user, generate_corp_group_name(character.corporation_name)) - logger.info("User %s transitioned to full member during api refresh." % user) - elif corp.corporation_id != oldcorp_id: - #changed corps, both corps auth'd, need to change group assignment - logger.debug("User %s main character changed corp from id %s to %s, both meet membership requirements. Updating corp group." % (user, oldcorp_id, corp.corporation_id)) - remove_user_from_group(user, generate_corp_group_name(oldcorp_name)) - add_user_to_group(user, generate_corp_group_name(character.corporation_name)) - #reset services to force new mumble names and group assignments - deactivate_services(user) - logger.info("User %s transferred corps from member to member. Reassigned groups." % user) - elif corp is not None: - logger.debug("User %s main corp %s does not meet membership requirements." % (user, corp)) - if corp.is_blue is not True: - if check_if_user_has_permission(user, "member"): - #transition from member to nobody - disable_alliance_member(user, authserviceinfo.main_char_id) - logger.info("User %s no longer member: main has left member corp/alliance." % user) - elif check_if_user_has_permission(user, "blue_member"): - #transition from blue to nobody - disable_blue_member(user) - logger.info("User %s no longer blue: main has left blue entities." % user) - else: - #stay nobody, make sure no services - deactivate_services(user) - logger.debug("Ensured non-member %s has no services." % user) - else: - if check_if_user_has_permission(user, "member"): - #remove auth member to prepare for member to blue transition - disable_alliance_member(user, authserviceinfo.main_char_id) - logger.debug("Removed user %s member group/permissions to transition to blue." % user) - if not check_if_user_has_permission(user, "blue_member"): - #perform nobody to blue transition - add_member_permission(user, "blue_member") - add_user_to_group(user, settings.DEFAULT_BLUE_GROUP) - AuthServicesInfoManager.update_is_blue(True, user) - logger.info("User %s transitioned to blue member during api refresh." % user) - - else: - # disable accounts with missing corp model (not blue or member) - if check_if_user_has_permission(user, "member"): - disable_alliance_member(user, authserviceinfo.main_char_id) - logger.info("User %s disabled (previously member) as unable to check missing corp model." % user) - elif check_if_user_has_permission(user, "blue_member"): - disable_blue_member(user) - logger.info("User %s disabled (previously blue) as unable to check missing corp model." % user) - else: - deactivate_services(user) - logger.debug("Ensured non-member %s has no services." % user) - else: - # nuke it, the hard way - disable_expired_member(user) - logger.info("User %s disabled due to missing main character or corp model." % user) + for api_key_pair in api_key_pairs: + logger.debug("Running update on api key %s" % api_key_pair.api_id) + if EveApiManager.api_key_is_valid(api_key_pair.api_id, api_key_pair.api_key): + #check to ensure API key meets min spec + logger.info("Determined api key %s is still active." % api_key_pair.api_id) + still_valid = True + if authserviceinfo.is_blue: + if settings.BLUE_API_ACCOUNT: + type = EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key) + if type == None: + api_key_pair.error_count += 1 + api_key_pair.save() + logger.info("API key %s incurred an error checking if type account. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) + still_valid = None + elif type == False: + logger.info("Determined api key %s for blue user %s is no longer type account as requred." % (api_key_pair.api_id, user)) + still_valid = False + full = EveApiManager.check_blue_api_is_full(api_key_pair.api_id, api_key_pair.api_key) + if full == None: + api_key_pair.error_count += 1 + api_key_pair.save() + logger.info("API key %s incurred an error checking if meets mask requirements. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) + still_valid = None + elif full == False: + logger.info("Determined api key %s for blue user %s no longer meets minimum access mask as required." % (api_key_pair.api_id, user)) + still_valid = False else: - # disable accounts with invalid keys - disable_expired_member(user) - logger.info("User %s has no valid api keys and has been disabled." % user) - + if settings.MEMBER_API_ACCOUNT: + type = EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key) + if type == None: + api_key_pair.error_count += 1 + api_key_pair.save() + logger.info("API key %s incurred an error checking if type account. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) + still_valid = None + elif type == False: + logger.info("Determined api key %s for user %s is no longer type account as required." % (api_key_pair.api_id, user)) + still_valid = False + full = EveApiManager.check_api_is_full(api_key_pair.api_id, api_key_pair.api_key) + if full == None: + api_key_pair.error_count += 1 + api_key_pair.save() + logger.info("API key %s incurred an error checking if meets mask requirements. Error count is now %s" % (api_key_pair.api_id, api_key_pair.error_count)) + still_valid = None + elif full == False: + logger.info("Determined api key %s for user %s no longer meets minimum access mask as required." % (api_key_pair.api_id, user)) + still_valid = False + if still_valid == None: + if api_key_pair.error_count >= 3: + logger.info("API key %s has incurred 3 or more errors. Assuming invalid." % api_key_pair.api_id) + still_valid = False + if still_valid == False: + logger.debug("API key %s has failed validation; it and its characters will be deleted." % api_key_pair.api_id) + EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id) + EveManager.delete_api_key_pair(api_key_pair.api_id, user.id) + elif still_valid == True: + if api_key_pair.error_count != 0: + logger.info("Clearing error count for api %s as it passed validation" % api_key_pair.api_id) + api_key_pair.error_count = 0 + api_key_pair.save() + logger.info("Determined api key %s still meets requirements." % api_key_pair.api_id) + # Update characters + characters = EveApiManager.get_characters_from_api(api_key_pair.api_id, api_key_pair.api_key) + EveManager.update_characters_from_list(characters) + new_character = False + for char in characters.result: + # Ensure we have a model for all characters on key + if not EveManager.check_if_character_exist(characters.result[char]['name']): + new_character = True + logger.debug("API key %s has a new character on the account: %s" % (api_key_pair.api_id, characters.result[char]['name'])) + if new_character: + logger.debug("Creating new character %s from api key %s" % (characters.result[char]['name'], api_key_pair.api_id)) + EveManager.create_characters_from_list(characters, user, api_key_pair.api_key) + # Check our main character + if EveCharacter.objects.filter(character_id=authserviceinfo.main_char_id).exists() is False: + logger.info("User %s main character id %s missing model. Clearning main character." % (user, authserviceinfo.main_char_id)) + authserviceinfo.main_char_id = '' + authserviceinfo.save() else: logger.warn("User %s has no main character id, unable to validate membership.") + state = determine_membership_by_user(user) + logger.debug("Assigning user %s to state %s" % (user, state)) + if state == "MEMBER": + make_member(user) + elif state == "BLUE": + make_blue(user) + else: + disable_member(user) # Run Every 2 hours diff --git a/eveonline/forms.py b/eveonline/forms.py index 4fbbcbe1..8b4d0590 100644 --- a/eveonline/forms.py +++ b/eveonline/forms.py @@ -33,13 +33,13 @@ class UpdateKeyForm(forms.Form): evechar.corporation_id = chars[char]['corp']['id'] evechar.alliance_id = chars[char]['alliance']['id'] state = determine_membership_by_character(evechar) - logger.debug("API ID %s character %s has state %s" % (self.cleaned_data['api_id'], evechar, state) + logger.debug("API ID %s character %s has state %s" % (self.cleaned_data['api_id'], evechar, state)) states.append(state) if 'MEMBER' in states: if EveApiManager.validate_member_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: - raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s" % (settings.MEMBER_API_ACCOUNT, settings.MEMBER_API_MASK) + raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s' % (settings.MEMBER_API_ACCOUNT, settings.MEMBER_API_MASK)) if 'BLUE' in states: if EveApiManager.validate_blue_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: - raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s" % (settings.BLUE_API_ACCOUNT, settings.BLUE_API_MASK) + raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s' % (settings.BLUE_API_ACCOUNT, settings.BLUE_API_MASK)) return self.cleaned_data From cce940f9a2e1b1162434749bec362b1a4616505a Mon Sep 17 00:00:00 2001 From: Adarnof Date: Fri, 11 Dec 2015 14:02:15 +0000 Subject: [PATCH 04/35] Corrected form validation Corrected logging comments --- celerytask/tasks.py | 36 +++++++++++++++++++++++----------- eveonline/forms.py | 48 +++++++++++++++++++++++---------------------- eveonline/views.py | 42 ++++++--------------------------------- 3 files changed, 56 insertions(+), 70 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 75fe51e9..559cd4ad 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -1,6 +1,7 @@ from django.conf import settings from celery.task import periodic_task from django.contrib.auth.models import User +from django.contrib.auth.models import Group from models import SyncGroupCache from celery.task.schedules import crontab @@ -31,7 +32,7 @@ import logging logger = logging.getLogger(__name__) -def disable_member(user, char_id): +def disable_member(user): logger.debug("Disabling member %s" % user) if user.user_permissions.all().exists(): logger.info("Clearning user %s permission to deactivate user." % user) @@ -276,7 +277,7 @@ def make_member(user): logger.info("Adding user %s to corp group %s" % (user, corp_group)) user.groups.add(corp_group) for g in user.groups.all(): - if str.startswith(g.name, "Corp_"): + if str.startswith(str(g.name), "Corp_"): if g != corp_group: logger.info("Removing user %s from old corpgroup %s" % (user, g)) user.groups.remove(g) @@ -305,29 +306,29 @@ def make_blue(user): auth.is_blue = True auth.save() for g in user.groups.all(): - if str.startswith(g.name, 'Corp_'): + if str.startswith(str(g.name), 'Corp_'): logger.info("Removing blue user %s from corp group %s" % (user, g)) user.groups.remove(g) def determine_membership_by_character(char): if settings.IS_CORP: if char.corporation_id == settings.CORP_ID: - logger.debug("User %s main character %s in owning corp id %s" % (user, char, char.corporation_id)) + logger.debug("Character %s in owning corp id %s" % (char, char.corporation_id)) return "MEMBER" else: if char.alliance_id == settings.ALLIANCE_ID: - logger.debug("User %s main character %s in owning alliance id %s" % (user, char, char.alliance_id)) + logger.debug("Character %s in owning alliance id %s" % (char, char.alliance_id)) return "MEMBER" - if EveCorporation.objects.filter(corporation_id=char.corporation_id).exists() is False: - logger.debug("No corp model for user %s main character %s corp id %s. Unable to check standings. Non-member." % (user, char, char.corporation_id)) + if EveCorporationInfo.objects.filter(corporation_id=char.corporation_id).exists() is False: + logger.debug("No corp model for character %s corp id %s. Unable to check standings. Non-member." % (char, char.corporation_id)) return False else: - corp = EveCorporation.objects.get(corporation_id=char.corporation_id) + corp = EveCorporationInfo.objects.get(corporation_id=char.corporation_id) if corp.is_blue: - logger.debug("User %s main character %s member of blue corp %s" % (user, char, corp)) + logger.debug("Character %s member of blue corp %s" % (char, corp)) return "BLUE" else: - logger.debug("User %s main character %s member of non-blue corp %s. Non-member." % (user, char, corp)) + logger.debug("Character %s member of non-blue corp %s. Non-member." % (char, corp)) return False def determine_membership_by_user(user): @@ -338,12 +339,21 @@ def determine_membership_by_user(user): char = EveCharacter.objects.get(character_id=auth.main_char_id) return determine_membership_by_character(char) else: - logger.debug("Character model matching user %s main character id %s does not exist. Non-member." % (user, auth.main_character_id)) + logger.debug("Character model matching user %s main character id %s does not exist. Non-member." % (user, auth.main_char_id)) return False else: logger.debug("User %s has no main character set. Non-member." % user) return False +def set_state(user): + state = determine_membership_by_user(user) + if state == "MEMBER": + make_member(user) + elif state == "BLUE": + make_blue(user) + else: + disable_member(user) + # Run every minute @periodic_task(run_every=crontab(minute="*/1")) def run_databaseUpdate(): @@ -460,6 +470,10 @@ def run_api_refresh(): if new_character: logger.debug("Creating new character %s from api key %s" % (characters.result[char]['name'], api_key_pair.api_id)) EveManager.create_characters_from_list(characters, user, api_key_pair.api_key) + else: + logger.debug("API key %s is no longer valid; it and its characters will be deleted." % api_key_pair.api_id) + EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id) + EveManager.delete_api_key_pair(api_key_pair.api_id, user.id) # Check our main character if EveCharacter.objects.filter(character_id=authserviceinfo.main_char_id).exists() is False: logger.info("User %s main character id %s missing model. Clearning main character." % (user, authserviceinfo.main_char_id)) diff --git a/eveonline/forms.py b/eveonline/forms.py index 8b4d0590..a4fb4c17 100644 --- a/eveonline/forms.py +++ b/eveonline/forms.py @@ -12,34 +12,36 @@ import logging logger = logging.getLogger(__name__) class UpdateKeyForm(forms.Form): - def __init__(self, user_state=None, *args, **kwargs): - super(UpdateKeyForm, self).__init__(args, kwargs) - self.user_state=user_state + user_state = None api_id = forms.CharField(max_length=254, required=True, label="Key ID") api_key = forms.CharField(max_length=254, required=True, label="Verification Code") def clean(self): - if EveManager.check_if_api_key_pair_exist(self.cleaned_data['api_id']): - logger.debug("UpdateKeyForm failed cleaning as API id %s already exists." % self.cleaned_data['api_id']) - raise forms.ValidationError(u'API key already exist') + super(UpdateKeyForm, self).clean() - chars = EveApiManager.get_characters_from_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']).result - states = [] - states.append(self.user_state) - for char in chars: - evechar = EveCharacter() - evechar.character_name = chars[char]['name'] - evechar.corporation_id = chars[char]['corp']['id'] - evechar.alliance_id = chars[char]['alliance']['id'] - state = determine_membership_by_character(evechar) - logger.debug("API ID %s character %s has state %s" % (self.cleaned_data['api_id'], evechar, state)) - states.append(state) + if 'api_id' in self.cleaned_data and 'api_key' in self.cleaned_data: + logger.debug("Form has id and key") + if EveManager.check_if_api_key_pair_exist(self.cleaned_data['api_id']): + logger.debug("UpdateKeyForm failed cleaning as API id %s already exists." % self.cleaned_data['api_id']) + raise forms.ValidationError(u'API key already exist') - if 'MEMBER' in states: - if EveApiManager.validate_member_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: - raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s' % (settings.MEMBER_API_ACCOUNT, settings.MEMBER_API_MASK)) - if 'BLUE' in states: - if EveApiManager.validate_blue_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: - raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s' % (settings.BLUE_API_ACCOUNT, settings.BLUE_API_MASK)) + chars = EveApiManager.get_characters_from_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']).result + states = [] + states.append(self.user_state) + for char in chars: + evechar = EveCharacter() + evechar.character_name = chars[char]['name'] + evechar.corporation_id = chars[char]['corp']['id'] + evechar.alliance_id = chars[char]['alliance']['id'] + state = determine_membership_by_character(evechar) + logger.debug("API ID %s character %s has state %s" % (self.cleaned_data['api_id'], evechar, state)) + states.append(state) + + if 'MEMBER' in states: + if EveApiManager.validate_member_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: + raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s' % (settings.MEMBER_API_ACCOUNT, settings.MEMBER_API_MASK)) + if 'BLUE' in states: + if EveApiManager.validate_blue_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: + raise forms.ValidationError(u'API does not meet requirements: account: %s mask: %s' % (settings.BLUE_API_ACCOUNT, settings.BLUE_API_MASK)) return self.cleaned_data diff --git a/eveonline/views.py b/eveonline/views.py index 1d3db1a9..c4b35463 100755 --- a/eveonline/views.py +++ b/eveonline/views.py @@ -21,6 +21,7 @@ from eveonline.models import EveCharacter from eveonline.models import EveApiKeyPair from authentication.models import AuthServicesInfo from celerytask.tasks import determine_membership_by_user +from celerytask.tasks import set_state import logging @@ -49,7 +50,8 @@ def add_api_key(request): logger.debug("add_api_key called by user %s" % request.user) user_state = determine_membership_by_user(request.user) if request.method == 'POST': - form = UpdateKeyForm(request.POST, user_state=user_state) + form = UpdateKeyForm(request.POST) + form.user_state=user_state logger.debug("Request type POST with form valid: %s" % form.is_valid()) if form.is_valid(): EveManager.create_api_keypair(form.cleaned_data['api_id'], @@ -66,7 +68,8 @@ def add_api_key(request): logger.debug("Form invalid: returning to form.") else: logger.debug("Providing empty update key form for user %s" % request.user) - form = UpdateKeyForm(user_state=user_state) + form = UpdateKeyForm() + form.user_state = user_state context = {'form': form, 'apikeypairs': EveManager.get_api_key_pairs(request.user.id)} return render_to_response('registered/addapikey.html', context, context_instance=RequestContext(request)) @@ -117,41 +120,8 @@ def characters_view(request): def main_character_change(request, char_id): logger.debug("main_character_change called by user %s for character id %s" % (request.user, char_id)) if EveManager.check_if_character_owned_by_user(char_id, request.user): - previousmainid = AuthServicesInfoManager.get_auth_service_info(request.user).main_char_id AuthServicesInfoManager.update_main_char_Id(char_id, request.user) - # Check if character is in the alliance - character_info = EveManager.get_character_by_id(char_id) - corporation_info = EveManager.get_corporation_info_by_id(character_info.corporation_id) - logger.debug("User %s changing main character to %s in corp %s" % (request.user, character_info, corporation_info)) - if (settings.IS_CORP and EveManager.get_charater_corporation_id_by_id(char_id) == settings.CORP_ID) or (not settings.IS_CORP and EveManager.get_charater_alliance_id_by_id(char_id) == settings.ALLIANCE_ID): - add_member_permission(request.user, 'member') - add_user_to_group(request.user, settings.DEFAULT_AUTH_GROUP) - add_user_to_group(request.user, - generate_corp_group_name(EveManager.get_character_by_id(char_id).corporation_name)) - logger.info("User %s transitioned to full member by chaning main character to %s" % (request.user, character_info)) - - elif corporation_info != None: - if corporation_info.is_blue: - add_member_permission(request.user, 'blue_member') - add_user_to_group(request.user, settings.DEFAULT_BLUE_GROUP) - AuthServicesInfoManager.update_is_blue(True, request.user) - logger.info("User %s transitioned to blue by changing main character to %s" % (request.user, character_info)) - else: - if check_if_user_has_permission(request.user, 'member'): - disable_member(request.user, previousmainid) - - if check_if_user_has_permission(request.user, 'blue_member'): - disable_blue_member(request.user) - logger.info("User %s disabled as new main character %s not member nor blue." % (request.user, character_info)) - else: - # TODO: disable serivces - if check_if_user_has_permission(request.user, 'member'): - disable_member(request.user, previousmainid) - - if check_if_user_has_permission(request.user, 'blue_member'): - disable_blue_member(request.user) - logger.info("User %s disabled as new main character %s does not have corp model to check." % (request.user, character_info)) - + set_state(request.user) return HttpResponseRedirect("/characters") return HttpResponseRedirect("/characters") From 6bd99d10e708f26ca90dec6272684ae26c1a2dd8 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Fri, 11 Dec 2015 14:12:46 +0000 Subject: [PATCH 05/35] Updates key requirements on api add form for account --- stock/templates/registered/addapikey.html | 27 +++++++++-------------- util/context_processors.py | 6 +++-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/stock/templates/registered/addapikey.html b/stock/templates/registered/addapikey.html index 5059a1a0..eba2a93c 100644 --- a/stock/templates/registered/addapikey.html +++ b/stock/templates/registered/addapikey.html @@ -15,31 +15,26 @@

- Full API Key is required for auth services + Member API keys require access mask {{MEMBER_API_MASK}} or greater for services.

- + {% if MEMBER_API_ACCOUNT %} +

+ Member API keys need to be account-wide. +

+ {% endif %}

Create a full API key

- {% if IS_CORP %} +

+ Blue API keys require access mask {{BLUE_API_MASK}} or greater for services. +

+ {% if BLUE_API_ACCOUNT %}

- NOTE: If you are part of the corp do not check "Blue", this is for people who are blue to the - corp - but are not in it. Blue access is limited. -

- {% else %} -

- NOTE: If you are part of the alliance do not check "Blue", this is for people who are blue to the - alliance - but are not in it. Blue access is limited. + BLUE API keys need to be account-wide.

{% endif %} - -

Do not change the accessmask or deselect options or it will not work -

-

Create diff --git a/util/context_processors.py b/util/context_processors.py index 9367da57..7bd85386 100755 --- a/util/context_processors.py +++ b/util/context_processors.py @@ -21,10 +21,12 @@ def jabber_url(request): return {'JABBER_URL': settings.JABBER_URL} def member_api_mask(request): - return {'MEMBER_API_MASK': settings.MEMBER_API_MASK} + return {'MEMBER_API_MASK': settings.MEMBER_API_MASK, + 'MEMBER_API_ACCOUNT': settings.MEMBER_API_ACCOUNT} def blue_api_mask(request): - return {'BLUE_API_MASK': settings.BLUE_API_MASK} + return {'BLUE_API_MASK': settings.BLUE_API_MASK, + 'BLUE_API_ACCOUNT': settings.BLUE_API_ACCOUNT} def domain_url(request): return {'DOMAIN': settings.DOMAIN, 'MUMBLE_URL': settings.MUMBLE_URL, From 786e573a0a145a4adb45a3d0e9b1a0a5655d65b9 Mon Sep 17 00:00:00 2001 From: Ydmir Date: Fri, 15 Jan 2016 09:23:40 +0100 Subject: [PATCH 06/35] Added initial corputils functionality, for auditing members in corporation mode. --- .idea/allianceauth.iml | 11 +- alliance_auth/urls.py | 9 +- corputils/__init__.py | 0 corputils/admin.py | 0 corputils/models.py | 0 corputils/tests.py | 0 corputils/views.py | 52 ++++ eveonline/views.py | 1 + hrapplications/views.py | 344 +++++++++++----------- services/managers/eve_api_manager.py | 25 +- stock/templates/public/base.html | 9 +- stock/templates/registered/corputils.html | 102 +++++++ 12 files changed, 367 insertions(+), 186 deletions(-) create mode 100644 corputils/__init__.py create mode 100644 corputils/admin.py create mode 100644 corputils/models.py create mode 100644 corputils/tests.py create mode 100644 corputils/views.py create mode 100644 stock/templates/registered/corputils.html diff --git a/.idea/allianceauth.iml b/.idea/allianceauth.iml index 199266bc..a89267e9 100755 --- a/.idea/allianceauth.iml +++ b/.idea/allianceauth.iml @@ -6,21 +6,16 @@

  • - Corporation Stats
  • + {% if IS_CORP %} +
  • + Corporation Stats +
  • + {% endif %} {% endif %} {% if perms.auth.group_management %} diff --git a/stock/templates/registered/corputils.html b/stock/templates/registered/corputils.html new file mode 100644 index 00000000..eea074e6 --- /dev/null +++ b/stock/templates/registered/corputils.html @@ -0,0 +1,102 @@ + + + + + {% extends "public/base.html" %} +{% block title %}Alliance Auth{% endblock %} +{% block page_title %}Corporation Stats{% endblock page_title %} +{% load corputils_extras %} + +{% block content %} + + <div class="col-lg-12"> + <h1 class="page-header text-center">Corporation Member Data</h1> + {% if perms.auth.member %} + <div class="col-lg-12 container" id="example"> + {% if corp %} + <div class="row"> + <div class="col-lg-12"> + <div class="panel panel-default"> + <div class="panel-heading">Corporation</div> + + <div class="panel-body"> + <div class="col-lg-5 col-sm-2"><img class= + "ra-avatar img-responsive" src= + "https://image.eveonline.com/Corporation/{{ corp.corporation_id }}_128.png"> + </div> + + <div class="col-lg-7 col-sm-2"> + <h4 class="">Name: {{ corp.corporation_name }}</h4> + + <p>Ticker: {{ corp.corporation_ticker }}</p> + + <p>Member: {{ corp.member_count }}</p> + </div> + </div> + </div> + </div> + + + <div class="col-lg-12"> + <div class="panel panel-default"> + <div class="panel-heading">Registered Characters</div> + <div class="panel-body"> + <div style="overflow:auto;overflow-y:auto;"> + <table class="table table-condensed"> + <tr> + <th class="text-center">Main character</th> + <th class="text-center">Character list</th> + </tr> + {% for mainid, alts in characters_with_api.items %} + <tr> + <td class="text-center"> + <p class="">{{ alts|get_dict_item:mainid }}</p> + </td> + <td class="text-center"> + {% for charid, name in alts.items %} + <p class="">{{ name}}</p> + {% endfor %} + </td> + </tr> + {% endfor %} + {% for mainid, alts in characters_without_api.items %} + <tr bgcolor="#DD5500"> + <td class="text-center"> + <p class="">{{ alts|get_dict_item:mainid }}</p> + </td> + <td class="text-center"> + <p class="">No API registered!</p> + </td> + </tr> + {% endfor %} + </table> + </div> + </div> + </div> + </div> + {% else %} + <div class="container-fluid"> + <div class="col-md-4 col-md-offset-4"> + <div class="row"> + <div class="alert alert-danger text-center" role="alert">No corporation model found. Contact your admin.</div> + </div> + </div> + </div> + </div> + {% endif %} + </div> + {% else %} + {% if IS_CORP %} + <div class="alert alert-danger" role="alert">You are not in the corporation.</div> + {% else %} + <div class="alert alert-danger" role="alert">You are not in the alliance.</div> + {% endif %} + {% endif %} + </div> +{% endblock content %} + + + + + + \ No newline at end of file From d0c5e40bc8077fae2e02f65b5e081523d7b66acb Mon Sep 17 00:00:00 2001 From: Ydmir Date: Fri, 15 Jan 2016 09:27:14 +0100 Subject: [PATCH 07/35] Also added the new app corputils to installed apps in settings.py.example --- alliance_auth/settings.py.example | 1 + 1 file changed, 1 insertion(+) diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 8eb5e13e..91d7bb5b 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -58,6 +58,7 @@ INSTALLED_APPS = ( 'hrapplications', 'timerboard', 'srp', + 'corputils', ) MIDDLEWARE_CLASSES = ( From 93c3d450af0ca17f898d1c0733eeafd2430616c8 Mon Sep 17 00:00:00 2001 From: Ydmir Date: Fri, 15 Jan 2016 11:09:17 +0100 Subject: [PATCH 08/35] Fixed a reference bug. --- stock/templates/public/base.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/templates/public/base.html b/stock/templates/public/base.html index f0279c7d..c2067ca1 100755 --- a/stock/templates/public/base.html +++ b/stock/templates/public/base.html @@ -124,8 +124,8 @@ {% if IS_CORP %}
  • Corporation Stats + href="{% url 'auth_corp_member_view' %}"> Member Tracking
  • {% endif %} {% endif %} From cc3d1765338750868bea4362e23bbdcde878639e Mon Sep 17 00:00:00 2001 From: Ydmir Date: Fri, 15 Jan 2016 14:23:17 +0100 Subject: [PATCH 09/35] Now characters are listed in sorted order. --- corputils/views.py | 10 ++++---- stock/templates/registered/corputils.html | 30 +++++++++-------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/corputils/views.py b/corputils/views.py index f75bb780..0bbd083b 100644 --- a/corputils/views.py +++ b/corputils/views.py @@ -35,15 +35,15 @@ def corp_member_view(request): char = EveCharacter.objects.get(character_id=char_id) user = char.user mainid = int(AuthServicesInfoManager.get_auth_service_info(user=user).main_char_id) - characters_with_api.setdefault(mainid,{}).update({char_id:char.character_name}) + mainname = EveCharacter.objects.get(character_id=mainid).character_name + characters_with_api.setdefault(mainname,[]).append(char.character_name) except EveCharacter.DoesNotExist: - mainid = char_id - characters_without_api.setdefault(mainid,{}).update({char_id:member_data["name"]}) + characters_without_api.setdefault(member_data["name"],[]).append(member_data["name"]) context = {"corp": corp, - "characters_with_api": characters_with_api, - "characters_without_api": characters_without_api} + "characters_with_api": sorted(characters_with_api.items()), + "characters_without_api": sorted(characters_without_api.items())} return render_to_response('registered/corputils.html',context, context_instance=RequestContext(request) ) else: diff --git a/stock/templates/registered/corputils.html b/stock/templates/registered/corputils.html index eea074e6..507d6f6b 100644 --- a/stock/templates/registered/corputils.html +++ b/stock/templates/registered/corputils.html @@ -1,8 +1,4 @@ - - - - - {% extends "public/base.html" %} +{% extends "public/base.html" %} {% block title %}Alliance Auth{% endblock %} {% block page_title %}Corporation Stats{% endblock page_title %} {% load corputils_extras %} @@ -30,7 +26,11 @@ <p>Ticker: {{ corp.corporation_ticker }}</p> - <p>Member: {{ corp.member_count }}</p> + <p>Member count: {{ corp.member_count }}</p> + + <p>Player count: {{characters_with_api|length}}</p> + + <p>Unregistered characters: {{characters_without_api|length}}</p> </div> </div> </div> @@ -47,22 +47,22 @@ <th class="text-center">Main character</th> <th class="text-center">Character list</th> </tr> - {% for mainid, alts in characters_with_api.items %} + {% for main, alts in characters_with_api %} <tr> <td class="text-center"> - <p class="">{{ alts|get_dict_item:mainid }}</p> + <p class="">{{ main }}</p> </td> <td class="text-center"> - {% for charid, name in alts.items %} + {% for name in alts %} <p class="">{{ name}}</p> {% endfor %} </td> </tr> {% endfor %} - {% for mainid, alts in characters_without_api.items %} + {% for main, value in characters_without_api %} <tr bgcolor="#DD5500"> <td class="text-center"> - <p class="">{{ alts|get_dict_item:mainid }}</p> + <p class="">{{ main }}</p> </td> <td class="text-center"> <p class="">No API registered!</p> @@ -93,10 +93,4 @@ {% endif %} {% endif %} </div> -{% endblock content %} - - - - - - \ No newline at end of file +{% endblock content %} \ No newline at end of file From 030a0e9a8c4dc5b465bc5667c0619bf2cced4cbd Mon Sep 17 00:00:00 2001 From: Ydmir Date: Fri, 15 Jan 2016 22:54:53 +0100 Subject: [PATCH 10/35] Added search functionality to member list. --- alliance_auth/urls.py | 4 +- corputils/forms.py | 5 ++ corputils/views.py | 58 ++++++++++++++- stock/templates/public/base.html | 2 +- stock/templates/registered/corputils.html | 42 ++++++++++- .../registered/corputilssearchview.html | 71 +++++++++++++++++++ 6 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 corputils/forms.py create mode 100644 stock/templates/registered/corputilssearchview.html diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 4d065330..e1b562ad 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -164,7 +164,9 @@ urlpatterns = patterns('', name="auth_srp_request_update_amount_view"), #corputils - url(r'^corp_utils/$', 'corputils.views.corp_member_view', name='auth_corp_member_view'), + url(r'^corputils/$', 'corputils.views.corp_member_view', name='auth_corp_member_view'), + url(r'corputils_search/', 'corputils.views.corputils_search', + name="auth_corputils_search"), # FLEET FITTINGS url(r'^fits/$', 'services.views.fleet_fits', name='auth_fleet_fits'), diff --git a/corputils/forms.py b/corputils/forms.py new file mode 100644 index 00000000..1d1ba9a2 --- /dev/null +++ b/corputils/forms.py @@ -0,0 +1,5 @@ +from django import forms + + +class CorputilsSearchForm(forms.Form): + search_string = forms.CharField(max_length=254, required=True, label="Search String") diff --git a/corputils/views.py b/corputils/views.py index 0bbd083b..a148bc38 100644 --- a/corputils/views.py +++ b/corputils/views.py @@ -3,12 +3,16 @@ from django.shortcuts import render_to_response from django.template import RequestContext from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required +from django.shortcuts import HttpResponseRedirect + +from collections import namedtuple from authentication.managers import AuthServicesInfoManager from services.managers.eve_api_manager import EveApiManager from eveonline.models import EveCorporationInfo from eveonline.models import EveCharacter from authentication.models import AuthServicesInfo +from forms import CorputilsSearchForm import logging @@ -30,7 +34,7 @@ def corp_member_view(request): member_list = EveApiManager.get_corp_membertracking() characters_with_api = {} characters_without_api = {} - for char_id, member_data in member_list.iteritems(): + for char_id, member_data in member_list.items(): try: char = EveCharacter.objects.get(character_id=char_id) user = char.user @@ -43,10 +47,60 @@ def corp_member_view(request): context = {"corp": corp, "characters_with_api": sorted(characters_with_api.items()), - "characters_without_api": sorted(characters_without_api.items())} + "characters_without_api": sorted(characters_without_api.items()), + "search_form": CorputilsSearchForm()} return render_to_response('registered/corputils.html',context, context_instance=RequestContext(request) ) else: logger.error("Not running in corporation mode. Cannot provide corp member tracking data." % (request.user, auth_info.main_char_id)) return render_to_response('registered/corputils.html', None, context_instance=RequestContext(request)) + +@login_required +@permission_required('auth.corp_stats') +def corputils_search(request): + logger.debug("corputils_search called by user %s" % request.user) + if request.method == 'POST': + form = CorputilsSearchForm(request.POST) + logger.debug("Request type POST contains form valid: %s" % form.is_valid()) + if form.is_valid(): + # Really dumb search and only checks character name + # This can be improved but it does the job for now + searchstring = form.cleaned_data['search_string'] + logger.debug("Searching for player with character name %s for user %s" % (searchstring, request.user)) + + member_list = EveApiManager.get_corp_membertracking() + + Member = namedtuple('Member', ['name', 'main', 'api_registered']) + + members = [] + for memberid, member_data in member_list.items(): + if searchstring.lower() in member_data["name"].lower(): + try: + char = EveCharacter.objects.get(character_name=member_data["name"]) + user = char.user + mainid = int(AuthServicesInfoManager.get_auth_service_info(user=user).main_char_id) + mainname = EveCharacter.objects.get(character_id=mainid).character_name + api_registered = True + except EveCharacter.DoesNotExist: + api_registered = False + mainname = "" + members.append(Member(name=member_data["name"], main=mainname, api_registered=api_registered)) + + + logger.info("Found %s members for user %s matching search string %s" % (len(members), request.user, searchstring)) + + context = {'members': members, 'search_form': CorputilsSearchForm()} + + return render_to_response('registered/corputilssearchview.html', + context, context_instance=RequestContext(request)) + else: + logger.debug("Form invalid - returning for user %s to retry." % request.user) + context = {'applications': None, 'search_form': form} + return render_to_response('registered/corputilssearchview.html', + context, context_instance=RequestContext(request)) + + else: + logger.debug("Returning empty search form for user %s" % request.user) + return HttpResponseRedirect("/corputils/") + diff --git a/stock/templates/public/base.html b/stock/templates/public/base.html index c2067ca1..f015fcf8 100755 --- a/stock/templates/public/base.html +++ b/stock/templates/public/base.html @@ -123,7 +123,7 @@ {% if IS_CORP %}
  • - Member Tracking
  • diff --git a/stock/templates/registered/corputils.html b/stock/templates/registered/corputils.html index 507d6f6b..04b4ee92 100644 --- a/stock/templates/registered/corputils.html +++ b/stock/templates/registered/corputils.html @@ -1,13 +1,15 @@ {% extends "public/base.html" %} -{% block title %}Alliance Auth{% endblock %} -{% block page_title %}Corporation Stats{% endblock page_title %} +{% load bootstrap %} {% load corputils_extras %} +{% block title %}Alliance Auth{% endblock %} +{% block page_title %}Corporation Member Tracking{% endblock page_title %} + {% block content %}

    Corporation Member Data

    - {% if perms.auth.member %} + {% if perms.auth.corp_stats %}
    {% if corp %}
    @@ -32,6 +34,13 @@

    Unregistered characters: {{characters_without_api|length}}

    + +
    + + +
    @@ -93,4 +102,31 @@ {% endif %} {% endif %}
    + + {% if perms.auth.corp_stats %} + + + {% endif %} {% endblock content %} \ No newline at end of file diff --git a/stock/templates/registered/corputilssearchview.html b/stock/templates/registered/corputilssearchview.html new file mode 100644 index 00000000..3ffce71f --- /dev/null +++ b/stock/templates/registered/corputilssearchview.html @@ -0,0 +1,71 @@ +{% extends "public/base.html" %} +{% load bootstrap %} +{% load staticfiles %} +{% load corputils_extras %} + +{% block title %}Alliance Auth{% endblock %} + +{% block page_title %}Corporation Member Tracking{% endblock page_title %} +{% block extra_css %}{% endblock extra_css %} + +{% block content %} +
    + {% if perms.auth.corp_stats %} +

    Member Search Results +
    + + +
    +

    +
    + + + + + + {% for member in members %} + + + + + {% endfor %} +
    CharacterMain Character
    {{ member.name }} + {% if member.api_registered%} + {{ member.main }} + {% else %} + No API registered! + {% endif %} +
    +
    + {% endif %} +
    + + {% if perms.auth.corp_stats %} + + + {% endif %} +{% endblock content %} From f4eac57b0f68751cad4dddd64c0dd5eb184aaffe Mon Sep 17 00:00:00 2001 From: Ydmir Date: Fri, 22 Jan 2016 21:25:30 +0100 Subject: [PATCH 11/35] Users without a selected main character is not a problem anymore. Main will be listed as "User: [username]" and will be highlighted. Also added a row showing corp of main character. --- corputils/views.py | 25 ++++++++++++++----- stock/templates/registered/corputils.html | 24 +++++++++++------- .../registered/corputilssearchview.html | 5 ++-- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/corputils/views.py b/corputils/views.py index a148bc38..729f72f1 100644 --- a/corputils/views.py +++ b/corputils/views.py @@ -31,23 +31,36 @@ def corp_member_view(request): if settings.IS_CORP: corp = EveCorporationInfo.objects.get(corporation_id=settings.CORP_ID) + Player = namedtuple("Player", ["main", "maincorp", "altlist"]) + member_list = EveApiManager.get_corp_membertracking() characters_with_api = {} - characters_without_api = {} + characters_without_api = [] + for char_id, member_data in member_list.items(): try: char = EveCharacter.objects.get(character_id=char_id) user = char.user - mainid = int(AuthServicesInfoManager.get_auth_service_info(user=user).main_char_id) - mainname = EveCharacter.objects.get(character_id=mainid).character_name - characters_with_api.setdefault(mainname,[]).append(char.character_name) + try: + mainid = int(AuthServicesInfoManager.get_auth_service_info(user=user).main_char_id) + mainchar = EveCharacter.objects.get(character_id=mainid) + mainname = mainchar.character_name + maincorp = mainchar.corporation_name + except ValueError: + mainname = "User: " + user.username + maincorp = None + characters_with_api.setdefault(mainname, Player(main=mainname, + maincorp=maincorp, + altlist=[]) + ).altlist.append(char.character_name) + except EveCharacter.DoesNotExist: - characters_without_api.setdefault(member_data["name"],[]).append(member_data["name"]) + characters_without_api.append(member_data["name"]) context = {"corp": corp, "characters_with_api": sorted(characters_with_api.items()), - "characters_without_api": sorted(characters_without_api.items()), + "characters_without_api": sorted(characters_without_api), "search_form": CorputilsSearchForm()} return render_to_response('registered/corputils.html',context, context_instance=RequestContext(request) ) diff --git a/stock/templates/registered/corputils.html b/stock/templates/registered/corputils.html index 04b4ee92..359b1dc3 100644 --- a/stock/templates/registered/corputils.html +++ b/stock/templates/registered/corputils.html @@ -1,6 +1,5 @@ {% extends "public/base.html" %} {% load bootstrap %} -{% load corputils_extras %} {% block title %}Alliance Auth{% endblock %} {% block page_title %}Corporation Member Tracking{% endblock page_title %} @@ -54,24 +53,31 @@ + - {% for main, alts in characters_with_api %} - + {% for mainchar, player in characters_with_api %} + + {% endfor %} - {% for main, value in characters_without_api %} - + {% for charname in characters_without_api %} + + From bd7bbc93397632d58272d664b79216236fd7a15b Mon Sep 17 00:00:00 2001 From: Ydmir Date: Sun, 24 Jan 2016 22:32:54 +0100 Subject: [PATCH 15/35] Added portraits in the list, because why not. --- corputils/views.py | 12 +++++++----- services/managers/evewho_manager.py | 2 +- stock/templates/registered/corputils.html | 17 +++++++++++++---- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/corputils/views.py b/corputils/views.py index ba3f9ac7..bda698b1 100644 --- a/corputils/views.py +++ b/corputils/views.py @@ -44,7 +44,7 @@ def corp_member_view(request, corpid = settings.CORP_ID): member_list = EveWhoManager.get_corporation_members(corpid) characters_with_api = {} - characters_without_api = [] + characters_without_api = {} for char_id, member_data in member_list.items(): try: @@ -58,7 +58,9 @@ def corp_member_view(request, corpid = settings.CORP_ID): maincorpid = mainchar.corporation_id except (ValueError, EveCharacter.DoesNotExist): mainname = "User: " + user.username - maincorp = None + mainchar = char + maincorp = mainchar.corporation_name + maincorpid = mainchar.corporation_id characters_with_api.setdefault(mainname, Player(main=mainchar, maincorp=maincorp, maincorpid=maincorpid, @@ -66,7 +68,7 @@ def corp_member_view(request, corpid = settings.CORP_ID): ).altlist.append(char) except EveCharacter.DoesNotExist: - characters_without_api.append(member_data["name"]) + characters_without_api.update({member_data["name"]: member_data["id"]}) if not settings.IS_CORP: @@ -74,13 +76,13 @@ def corp_member_view(request, corpid = settings.CORP_ID): context = {"form": form, "corp": corp, "characters_with_api": sorted(characters_with_api.items()), - "characters_without_api": sorted(characters_without_api), + "characters_without_api": sorted(characters_without_api.items()), "search_form": CorputilsSearchForm()} else: logger.debug("corp_member_view running in corportation mode") context = {"corp": corp, "characters_with_api": sorted(characters_with_api.items()), - "characters_without_api": sorted(characters_without_api), + "characters_without_api": sorted(characters_without_api.items()), "search_form": CorputilsSearchForm()} diff --git a/services/managers/evewho_manager.py b/services/managers/evewho_manager.py index 364c11f2..35e0093c 100644 --- a/services/managers/evewho_manager.py +++ b/services/managers/evewho_manager.py @@ -16,4 +16,4 @@ class EveWhoManager(): jsondata = requests.get(url).content data=json.loads(jsondata.decode()) - return {row["character_id"]:{"name":row["name"]} for row in data["characters"]} + return {row["character_id"]:{"name":row["name"], "id":row["character_id"]} for row in data["characters"]} diff --git a/stock/templates/registered/corputils.html b/stock/templates/registered/corputils.html index 5482eb44..c84abe23 100644 --- a/stock/templates/registered/corputils.html +++ b/stock/templates/registered/corputils.html @@ -66,14 +66,19 @@
    Main characterMain corporation Character list
    -

    {{ main }}

    +

    {{ mainchar }}

    +
    +

    {{ player.maincorp }}

    - {% for name in alts %} -

    {{ name}}

    + {% for charname in player.altlist %} +

    {{ charname }}

    {% endfor %}
    -

    {{ main }}

    +

    {{ charname }}

    +
    +

    No API registered!

    diff --git a/stock/templates/registered/corputilssearchview.html b/stock/templates/registered/corputilssearchview.html index 3ffce71f..42d882e8 100644 --- a/stock/templates/registered/corputilssearchview.html +++ b/stock/templates/registered/corputilssearchview.html @@ -1,7 +1,6 @@ {% extends "public/base.html" %} {% load bootstrap %} {% load staticfiles %} -{% load corputils_extras %} {% block title %}Alliance Auth{% endblock %} @@ -10,7 +9,7 @@ {% block content %}
    - {% if perms.auth.corp_stats %} + {% if perms.auth.corputils %}

    Member Search Results
    @@ -42,7 +41,7 @@ {% endif %}
    - {% if perms.auth.corp_stats %} + {% if perms.auth.corputils %}

    - {% for charname in player.altlist %} -

    {{ charname }}

    + {% for char in player.altlist %} +

    {{ char.character_name }}

    {% endfor %}
    + - {% for mainchar, player in characters_with_api %} + {% for maincharname, player in characters_with_api %} + {% endfor %} - {% for charname in characters_without_api %} + {% for character_name, character_id in characters_without_api %} + - - + + {% for maincharname, player in characters_with_api %} @@ -100,9 +100,6 @@ - + {% endfor %}
    Main character Main corporation Character list
    + + -

    {{ mainchar }}

    +

    {{ maincharname }}

    {{ player.maincorp }}

    @@ -85,10 +90,14 @@
    + + -

    {{ charname }}

    +

    {{ character_name }}

    From 29e5790ec7335dc9f0c695403150fd56689aece9 Mon Sep 17 00:00:00 2001 From: Ydmir Date: Mon, 25 Jan 2016 23:19:28 +0100 Subject: [PATCH 16/35] Now the search function works in alliance mode as well, searching the corp that is currently active. Also, the select corporation is nicer now. --- alliance_auth/urls.py | 4 ++-- corputils/views.py | 26 ++++++++++---------- stock/static/css/bootstrap.min.css | 5 ++++ stock/templates/registered/corputils.html | 29 ++++++++++++----------- 4 files changed, 35 insertions(+), 29 deletions(-) diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 4b0b37a4..2b865aaa 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -166,8 +166,8 @@ urlpatterns = patterns('', #corputils url(r'^corputils/$', 'corputils.views.corp_member_view', name='auth_corp_member_view'), url(r'^corputils/(?P[0-9]+)/$', 'corputils.views.corp_member_view', name='auth_corp_member_view'), - url(r'^corputils/search/', 'corputils.views.corputils_search', - name="auth_corputils_search"), + url(r'^corputils/search/$', 'corputils.views.corputils_search', name="auth_corputils_search"), + url(r'^corputils/search/(?P[0-9]+)/$', 'corputils.views.corputils_search', name="auth_corputils_search"), # FLEET FITTINGS url(r'^fits/$', 'services.views.fleet_fits', name='auth_fleet_fits'), diff --git a/corputils/views.py b/corputils/views.py index bda698b1..aa8c0fbb 100644 --- a/corputils/views.py +++ b/corputils/views.py @@ -28,13 +28,6 @@ logger = logging.getLogger(__name__) def corp_member_view(request, corpid = settings.CORP_ID): logger.debug("corp_member_view called by user %s" % request.user) - if request.method == 'POST': - form = SelectCorpForm(request.POST) - if form.is_valid(): - return HttpResponseRedirect("/corputils/"+form.cleaned_data["corpid"]) - else: - return HttpResponseRedirect("/corputils/") - corp = EveCorporationInfo.objects.get(corporation_id=corpid) Player = namedtuple("Player", ["main", "maincorp", "maincorpid", "altlist"]) @@ -59,8 +52,8 @@ def corp_member_view(request, corpid = settings.CORP_ID): except (ValueError, EveCharacter.DoesNotExist): mainname = "User: " + user.username mainchar = char - maincorp = mainchar.corporation_name - maincorpid = mainchar.corporation_id + maincorp = "Not set." + maincorpid = None characters_with_api.setdefault(mainname, Player(main=mainchar, maincorp=maincorp, maincorpid=maincorpid, @@ -72,8 +65,12 @@ def corp_member_view(request, corpid = settings.CORP_ID): if not settings.IS_CORP: - form = SelectCorpForm() - context = {"form": form, + alliance = EveAllianceInfo.objects.get(alliance_id=settings.ALLIANCE_ID) + alliancecorps = EveCorporationInfo.objects.filter(alliance=alliance) + membercorp_list = [(int(membercorp.corporation_id), str(membercorp.corporation_name)) for membercorp in alliancecorps] + membercorp_list.sort(key=lambda tup: tup[1]) + + context = {"membercorp_list": membercorp_list, "corp": corp, "characters_with_api": sorted(characters_with_api.items()), "characters_without_api": sorted(characters_without_api.items()), @@ -91,7 +88,7 @@ def corp_member_view(request, corpid = settings.CORP_ID): @login_required @permission_required('auth.corputils') -def corputils_search(request): +def corputils_search(request, corpid=settings.CORP_ID): logger.debug("corputils_search called by user %s" % request.user) if request.method == 'POST': form = CorputilsSearchForm(request.POST) @@ -102,7 +99,10 @@ def corputils_search(request): searchstring = form.cleaned_data['search_string'] logger.debug("Searching for player with character name %s for user %s" % (searchstring, request.user)) - member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE) + if settings.IS_CORP: + member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE) + else: + member_list = EveWhoManager.get_corporation_members(corpid) Member = namedtuple('Member', ['name', 'main', 'api_registered']) diff --git a/stock/static/css/bootstrap.min.css b/stock/static/css/bootstrap.min.css index ee15bd7a..d368d7be 100644 --- a/stock/static/css/bootstrap.min.css +++ b/stock/static/css/bootstrap.min.css @@ -3401,6 +3401,11 @@ tbody.collapse.in { box-shadow: 0 6px 12px rgba(0, 0, 0, .175) } +.dropdown-menu.scrollable { + overflow: auto; + max-height: 450px; +} + .dropdown-menu.pull-right { right: 0; left: auto diff --git a/stock/templates/registered/corputils.html b/stock/templates/registered/corputils.html index c84abe23..b8678029 100644 --- a/stock/templates/registered/corputils.html +++ b/stock/templates/registered/corputils.html @@ -35,19 +35,20 @@

    Unregistered characters: {{characters_without_api|length}}

    - {% if form %} -
    -
    -
    - -
    -
    -
    + + {% if membercorp_list %} + {% endif %}
    Main characterKillboard Main corporationCharacter listCharacter listKillboard

    {{ maincharname }}

    - Killboard - {% if not corp.corporation_name == player.maincorp%} @@ -119,6 +116,11 @@

    {{ char.character_name }}

    {% endfor %}
    + {% for char in player.altlist %} +

    Killboard

    + {% endfor %} +
    @@ -138,8 +140,7 @@ Character - Killboard - API + Killboard {% for character_name, character_id in characters_without_api %} @@ -152,9 +153,6 @@ Killboard - - No API registered! - {% endfor %} From 2ce48c47966e65167d92c151f46d90e94d57ccfc Mon Sep 17 00:00:00 2001 From: Joakim Strandberg Date: Thu, 28 Jan 2016 23:30:08 +0100 Subject: [PATCH 25/35] Fixed indentation. --- alliance_auth/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 2b865aaa..40068575 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -175,7 +175,7 @@ urlpatterns = patterns('', # Sig Tracker url(r'^sigtracker/$', 'sigtracker.views.sigtracker_view', name='auth_signature_view'), url(r'^add_signature/$', 'sigtracker.views.add_signature_view', name='auth_add_signature_view'), - url(r'^remove_signature/(\w+)', 'sigtracker.views.remove_signature', name='auth_remove_signature'), + url(r'^remove_signature/(\w+)', 'sigtracker.views.remove_signature', name='auth_remove_signature'), # Fleet Operations Timers url(r'^optimer/$', 'optimer.views.optimer_view', name='auth_optimer_view'), From 1e86df3992e52cc5f5a72e0da0fe7eec2a92e7c3 Mon Sep 17 00:00:00 2001 From: Ydmir Date: Fri, 29 Jan 2016 09:12:26 +0100 Subject: [PATCH 26/35] Fixed indentation for real... --- alliance_auth/settings.py.example | 12 ++++++++++++ alliance_auth/urls.py | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index a376f1dc..3a66bb3b 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -441,6 +441,18 @@ LOGGING = { 'handlers': ['log_file', 'console'], 'level': 'DEBUG', }, + 'sigtracker': { + 'handlers': ['log_file', 'console'], + 'level': 'DEBUG', + }, + 'optimer': { + 'handlers': ['log_file', 'console'], + 'level': 'DEBUG', + }, + 'corputil': { + 'handlers': ['log_file', 'console'], + 'level': 'DEBUG', + }, 'util': { 'handlers': ['log_file', 'console'], 'level': 'DEBUG', diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 40068575..96c56fe7 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -172,10 +172,10 @@ urlpatterns = patterns('', # FLEET FITTINGS url(r'^fits/$', 'services.views.fleet_fits', name='auth_fleet_fits'), - # Sig Tracker + # Sig Tracker url(r'^sigtracker/$', 'sigtracker.views.sigtracker_view', name='auth_signature_view'), url(r'^add_signature/$', 'sigtracker.views.add_signature_view', name='auth_add_signature_view'), - url(r'^remove_signature/(\w+)', 'sigtracker.views.remove_signature', name='auth_remove_signature'), + url(r'^remove_signature/(\w+)', 'sigtracker.views.remove_signature', name='auth_remove_signature'), # Fleet Operations Timers url(r'^optimer/$', 'optimer.views.optimer_view', name='auth_optimer_view'), From 185805ecc1a1a12e4c8b8d9d81a44347f004b59d Mon Sep 17 00:00:00 2001 From: Ydmir Date: Sat, 30 Jan 2016 11:05:09 +0100 Subject: [PATCH 27/35] Added simple caching. --- requirements.txt | 1 + services/managers/evewho_manager.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ce742155..ec35fc39 100755 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,7 @@ evelink dnspython passlib requests>=2.9.1 +requests_cache json # Django Stuff # diff --git a/services/managers/evewho_manager.py b/services/managers/evewho_manager.py index 35e0093c..595efb46 100644 --- a/services/managers/evewho_manager.py +++ b/services/managers/evewho_manager.py @@ -1,10 +1,11 @@ - from django.conf import settings import logging import requests +import requests_cache import json +requests_cache.install_cache("evewhocache", backend="sqlite", expire_after=3600) class EveWhoManager(): def __init__(self): From 49d1b8656699e412c301f47eadec414dcbab0a08 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Sun, 31 Jan 2016 08:06:38 +0000 Subject: [PATCH 28/35] Check apis during refresh by user state --- celerytask/tasks.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 559cd4ad..595f2811 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -404,7 +404,8 @@ def run_api_refresh(): #check to ensure API key meets min spec logger.info("Determined api key %s is still active." % api_key_pair.api_id) still_valid = True - if authserviceinfo.is_blue: + state = determine_membership_by_user(user) + if state == "BLUE": if settings.BLUE_API_ACCOUNT: type = EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key) if type == None: @@ -424,7 +425,7 @@ def run_api_refresh(): elif full == False: logger.info("Determined api key %s for blue user %s no longer meets minimum access mask as required." % (api_key_pair.api_id, user)) still_valid = False - else: + elif state == "MEMBER": if settings.MEMBER_API_ACCOUNT: type = EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key) if type == None: From 9041f0e7c7f8958f34622b4d010a2e09b40acf77 Mon Sep 17 00:00:00 2001 From: Ydmir Date: Sun, 31 Jan 2016 11:29:54 +0100 Subject: [PATCH 29/35] Handling missing settings.CORP_ID in alliance mode, and api-scope error in corporation mode. Also fixing visual on the corputilsearchview. --- alliance_auth/settings.py.example | 2 +- alliance_auth/urls.py | 4 +-- corputils/views.py | 33 ++++++++++++++----- stock/static/css/bootstrap.min.css | 4 +++ stock/templates/registered/corputils.html | 2 +- .../registered/corputilssearchview.html | 15 +++++---- 6 files changed, 41 insertions(+), 19 deletions(-) diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 3a66bb3b..2664add0 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -449,7 +449,7 @@ LOGGING = { 'handlers': ['log_file', 'console'], 'level': 'DEBUG', }, - 'corputil': { + 'corputils': { 'handlers': ['log_file', 'console'], 'level': 'DEBUG', }, diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 96c56fe7..12120190 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -165,9 +165,9 @@ urlpatterns = patterns('', #corputils url(r'^corputils/$', 'corputils.views.corp_member_view', name='auth_corp_member_view'), - url(r'^corputils/(?P[0-9]+)/$', 'corputils.views.corp_member_view', name='auth_corp_member_view'), + url(r'^corputils/(?P[0-9]+)/$', 'corputils.views.corp_member_view'), url(r'^corputils/search/$', 'corputils.views.corputils_search', name="auth_corputils_search"), - url(r'^corputils/search/(?P[0-9]+)/$', 'corputils.views.corputils_search', name="auth_corputils_search"), + url(r'^corputils/search/(?P[0-9]+)/$', 'corputils.views.corputils_search'), # FLEET FITTINGS url(r'^fits/$', 'services.views.fleet_fits', name='auth_fleet_fits'), diff --git a/corputils/views.py b/corputils/views.py index 96cc965a..8498541c 100644 --- a/corputils/views.py +++ b/corputils/views.py @@ -15,6 +15,7 @@ from eveonline.models import EveAllianceInfo from eveonline.models import EveCharacter from authentication.models import AuthServicesInfo from forms import CorputilsSearchForm +from evelink.api import APIError import logging @@ -24,14 +25,31 @@ logger = logging.getLogger(__name__) # Because corp-api only exist for the executor corp, this function will only be available in corporation mode. @login_required @permission_required('auth.corputils') -def corp_member_view(request, corpid = settings.CORP_ID): +def corp_member_view(request, corpid = None): logger.debug("corp_member_view called by user %s" % request.user) + if not settings.IS_CORP: + alliance = EveAllianceInfo.objects.get(alliance_id=settings.ALLIANCE_ID) + alliancecorps = EveCorporationInfo.objects.filter(alliance=alliance) + membercorp_list = [(int(membercorp.corporation_id), str(membercorp.corporation_name)) for membercorp in alliancecorps] + membercorp_list.sort(key=lambda tup: tup[1]) + + if not corpid: + if(settings.CORP_ID): + corpid = settings.CORP_ID + else: + corpid = membercorp_list[0][0] + + corp = EveCorporationInfo.objects.get(corporation_id=corpid) Player = namedtuple("Player", ["main", "maincorp", "maincorpid", "altlist"]) if settings.IS_CORP: - member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE) + try: + member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE) + except APIError: + logger.debug("Corp API does not have membertracking scope, using EveWho data instead.") + member_list = EveWhoManager.get_corporation_members(corpid) else: member_list = EveWhoManager.get_corporation_members(corpid) @@ -64,11 +82,6 @@ def corp_member_view(request, corpid = settings.CORP_ID): if not settings.IS_CORP: - alliance = EveAllianceInfo.objects.get(alliance_id=settings.ALLIANCE_ID) - alliancecorps = EveCorporationInfo.objects.filter(alliance=alliance) - membercorp_list = [(int(membercorp.corporation_id), str(membercorp.corporation_name)) for membercorp in alliancecorps] - membercorp_list.sort(key=lambda tup: tup[1]) - context = {"membercorp_list": membercorp_list, "corp": corp, "characters_with_api": sorted(characters_with_api.items()), @@ -102,7 +115,11 @@ def corputils_search(request, corpid=settings.CORP_ID): logger.debug("Searching for player with character name %s for user %s" % (searchstring, request.user)) if settings.IS_CORP: - member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE) + try: + member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE) + except APIError: + logger.debug("Corp API does not have membertracking scope, using EveWho data instead.") + member_list = EveWhoManager.get_corporation_members(corpid) else: member_list = EveWhoManager.get_corporation_members(corpid) diff --git a/stock/static/css/bootstrap.min.css b/stock/static/css/bootstrap.min.css index 6822b5b8..ce8cda62 100644 --- a/stock/static/css/bootstrap.min.css +++ b/stock/static/css/bootstrap.min.css @@ -4240,6 +4240,10 @@ textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group- line-height: 20px } +.navbar-wide { + width: 100%; +} + @media (max-width: 767px) { .navbar-nav .open .dropdown-menu { position: static; diff --git a/stock/templates/registered/corputils.html b/stock/templates/registered/corputils.html index bbb67a93..7529f890 100644 --- a/stock/templates/registered/corputils.html +++ b/stock/templates/registered/corputils.html @@ -45,7 +45,7 @@